1. 減庫存redis
通常下單減庫存的流程大概是這樣的:數據庫
一、查詢商品庫存。這裏直接查的Redis中的庫存。緩存
二、Redis中的庫存減1。這裏用到的Redis命令是:incrby -1併發
三、扣減數據庫中的庫存。這裏用數據庫樂觀鎖,不用額外加鎖異步
四、異步刷新Redis中的庫存分佈式
五、定時掃描超時未支付的交易,庫存加回去性能
總結一下這個流程就是:先減redis庫存,再減數據庫庫存,最後刷新redis庫存優化
用到的Redis命令可能:DECR key 或者 INCRBY key -1spa
更新數據庫的SQL多是這樣的:線程
update 商品庫存表 set 庫存 = 庫存 - 1 where 商品ID = xxx and 庫存 > 0;
或者
update 商品庫存表 set 庫存 = 庫存 - 1 where 商品ID = xxx and version = xxx;
用樂觀鎖是一種比較好的方式,並且一遍ID字段都有索引,能夠充分利用MySQL行級鎖
這種方式還有一個比較巧妙的地方是,利用redis的單線程來操做庫存,並且又是原子命令,能夠避免併發問題
同時,先減redis庫存後能夠防止後續因庫存不足而形成下單失敗
最後,數據庫更新完之後,再經過MQ異步刷新緩存,可使得redis中的庫存偏差不會太大
交易系統會定時掃描超時未支付的訂單,而後用MQ異步通知訂單和商品中心,將訂單關閉,庫存再放回去
2. 加鎖
加鎖(好比:基於Redis的分佈式鎖)
MQ能夠把並行轉成串行,可是並不能很好的解決併發訪問的問題,只能靠鎖
加鎖會影響性能,可是影響不大。假設咱們用Redisson分佈式鎖,操做redis只須要幾毫秒,所以這點兒損耗不是什麼大問題。都是這麼玩兒的,不加鎖還能怎麼辦呢。
3. 內存緩存
在cms管理後臺修改數據後,同步或異步刷新redis緩存,同時利用zookeeper刷新內存緩存,這樣就能夠不用等到須要用的時候再從redis中同步。
必定要避免redis大key,最多見的就是hash key,設置的時候不注意,一不當心裏面就幾千個field了,這對查詢很是不利,能夠取模進行分片。
必定要避免HGETALL命令,利用Pinpoint能夠幫助咱們分析每一個請求在每一個操做所消耗的時候,從而有助於咱們優化
數據遷移用Canal