博主最近在項目中遇到了搶購問題!如今分享下。
搶購、秒殺是現在很常見的一個應用場景,主要須要解決的問題有兩個:
1 高併發對數據庫產生的壓力
2 競爭狀態下如何解決庫存的正確減小("超賣"問題)
對於第一個問題,已經很容易想到用緩存來處理搶購,避免直接操做數據庫,例如使用Redis。
重點在於第二個問題
常規寫法:
查詢出對應商品的庫存,看是否大於0,而後執行生成訂單等操做,可是在判斷庫存是否大於0處,若是在高併發下就會有問題,致使庫存量出現負數php
優化方案1:將庫存字段number字段設爲unsigned,當庫存爲0時,由於字段不能爲負數,將會返回falsemysql
優化方案2:使用MySQL的事務,鎖住操做的行web
優化方案3:使用非阻塞的文件排他鎖ajax
優化方案4:使用redis隊列,由於pop操做是原子的,即便有不少用戶同時到達,也是依次執行,推薦使用(mysql事務在高併發下性能降低很厲害,文件鎖的方式也是)redis
搶購、描述邏輯sql
模擬5000高併發測試
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數據庫
上述只是簡單模擬高併發下的搶購,真實場景要比這複雜不少,不少注意的地方
如搶購頁面作成靜態的,經過ajax調用接口
再如上面的會致使一個用戶搶多個,思路:
須要一個排隊隊列和搶購結果隊列及庫存隊列。高併發狀況,先將用戶進入排隊隊列,用一個線程循環處理從排隊隊列取出一個用戶,判斷用戶是否已在搶購結果隊列,若是在,則已搶購,不然未搶購,庫存減1,寫數據庫,將用戶入結果隊列。緩存