歡迎大家關(guān)注我的其他<a >Github博客</a>和<a >Csdn</a>锦募,互相交流!
博主最近在項目中遇到了搶購問題邻遏!現(xiàn)在分享下糠亩。
搶購、秒殺是如今很常見的一個應用場景准验,主要需要解決的問題有兩個:
1 高并發(fā)對數(shù)據(jù)庫產(chǎn)生的壓力
2 競爭狀態(tài)下如何解決庫存的正確減少("超賣"問題)
對于第一個問題赎线,已經(jīng)很容易想到用緩存來處理搶購,避免直接操作數(shù)據(jù)庫糊饱,例如使用Redis垂寥。
重點在于第二個問題
常規(guī)寫法:
查詢出對應商品的庫存,看是否大于0另锋,然后執(zhí)行生成訂單等操作滞项,但是在判斷庫存是否大于0處,如果在高并發(fā)下就會有問題夭坪,導致庫存量出現(xiàn)負數(shù)
優(yōu)化方案1:將庫存字段number字段設(shè)為unsigned文判,當庫存為0時,因為字段不能為負數(shù)室梅,將會返回false
優(yōu)化方案2:使用MySQL的事務戏仓,鎖住操作的行
優(yōu)化方案3:使用非阻塞的文件排他鎖
優(yōu)化方案4:使用redis隊列潭流,因為pop操作是原子的,即使有很多用戶同時到達柜去,也是依次執(zhí)行,推薦使用(mysql事務在高并發(fā)下性能下降很厲害拆宛,文件鎖的方式也是)
搶購嗓奢、描述邏輯
模擬5000高并發(fā)測試
webbench -c 5000 -t 60 http://192.168.1.198/big/index.php
ab -r -n 6000 -c 5000 http://192.168.1.198/big/index.php
上述只是簡單模擬高并發(fā)下的搶購,真實場景要比這復雜很多浑厚,很多注意的地方
如搶購頁面做成靜態(tài)的股耽,通過ajax調(diào)用接口
再如上面的會導致一個用戶搶多個,思路:
需要一個排隊隊列和搶購結(jié)果隊列及庫存隊列钳幅。高并發(fā)情況物蝙,先將用戶進入排隊隊列,用一個線程循環(huán)處理從排隊隊列取出一個用戶敢艰,判斷用戶是否已在搶購結(jié)果隊列诬乞,如果在,則已搶購钠导,否則未搶購震嫉,庫存減1,寫數(shù)據(jù)庫牡属,將用戶入結(jié)果隊列票堵。