原始方案(失敗):在每次下訂單前我們判斷**商品的數量夠不夠,不夠不允許下訂單,更改庫存量時加上乙個條件,只更改商品庫存大於0的商品的庫存,當時我們使用ab進行壓力測試,當併發超過500,訪問量超過2000時,還是會出現超賣現象。
public
function
buyone
() }
第1種方案:使用mysql的事務加排他鎖來解決,首先我們選擇資料庫的儲存引擎為innodb,使用的是排他鎖實現的,剛開始的時候我們測試了下共享鎖,發現還是會出現超賣的現象。有個問題是,當我們進行高併發測試時,對資料庫的效能影響很大,導致資料庫的壓力很大。
//2.利用資料庫的forupdate來加鎖(在數量少的情況下並不會出現問題,但是當併發達到(ab -n 1000 -c 200),
//就會出現請求非2xx的響應增多,1000 失敗了 60)time per request 65.195
//在高併發的情況下,會導致資料庫連線數不夠,部分php獲取不到連線而報錯,或者是超過等待時間而報錯
public function indexmysql() else
} else
}
第2種方案:使用檔案鎖實現。當使用者搶到一件**商品後先觸發檔案鎖,防止其他使用者進入,該使用者搶到**品後再解開檔案鎖,放其他使用者進行操作。這樣可以解決超賣的問題,但是會導致檔案得i/o開銷很大。
第3種方案:使用redis的setnx來實現鎖機制。但是併發大的情況下,鎖的爭奪會變多,導致響應越來越慢。(與第四種方案類似)
//在數量少的情況下並不會出現問題,但是當併發達到(ab -n 1000 -c 200 就會出現請求非2xx的響應增多,1000 失敗了 54) time per request 127.575
public function index() else
}private function buy()
redis::del(self
::key);
}
第4種方案:redis的佇列來實現。將要**的商品數量以佇列的方式存入redis中,每當使用者搶到一件**商品則從佇列中刪除乙個資料,確保商品不會超賣。這個操作起來很方便,而且效率極高
//4.使用redis佇列來,使用者過來直接入佇列,然後再將操作更新到資料庫
//最佳體驗(redis pconnect 9.481s, 無丟失, 無框架)
public function push()
//指令碼呼叫pop方法 * * * * * php ***.php
public function pop()
}}
商品庫超賣的樂觀鎖
商品庫存的樂觀鎖實現。出現場景 避免商品出現超賣 即成功下單的訂單中商品的庫存數量大於商品現有的庫存量,則稱為商品超賣 的問題,核心技術是利用資料庫的事務鎖機制,即不允許同一商品的庫存記錄在同一時間被不同的兩個資料庫事務修改。功能實現 在前柔性事務介紹中所提到的,使用者在進行商品下單操作中,會進行一...
如何解決秒殺商品時,商品超賣的情況
文章的思路主要 於 解決方案 以下方案都是基於分布式的redis快取 1.用佇列解決大併發 建立一條佇列,將每個請求加入到佇列中,然後非同步獲取佇列資料進行處理,把多執行緒的事情變成單執行緒,處理完乙個就從佇列中刪除乙個。但是會出現乙個現象,請求特別多的時候,一瞬間將redis佇列記憶體撐爆,導致系...
庫存超賣的解決方案
update sku info set kc kc 1 where sku id and kc 0 在高併發下,多人搶同一庫存,由於資料庫讀寫可以並行執行的原因,會導致修改庫存時,庫存不足出現超賣。悲觀鎖解決 在select加乙個行鎖,與更新庫存操作互斥,保證查詢庫存時,庫存不被修改 在查詢和更新庫...