下單減庫存


1. 減庫存

一般下單減庫存的流程大概是這樣的:

1、查詢商品庫存。這里直接查的Redis中的庫存。

2、Redis中的庫存減1。這里用到的Redis命令是:incrby -1

3、扣減數據庫中的庫存。這里用數據庫樂觀鎖,不用額外加鎖

4、異步刷新Redis中的庫存

5、定時掃描超時未支付的交易,庫存加回去

總結一下這個流程就是:先減redis庫存,再減數據庫庫存,最后刷新redis庫存

用到的Redis命令可能:DECR key  或者  INCRBY key -1

更新數據庫的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

 

https://redis.io/commands/incr 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM