秒殺搶購時的併發處理方案
阿新 • • 發佈:2020-12-13
類似商城的秒殺場景,大家肯定都遇到過。如何處理好秒殺時候商品的庫存限制問題,真的一直讓人頭大。
常見的處理方案不外乎下面兩種:
1、鎖
表鎖、行鎖、檔案鎖。將需要操作的商品資料鎖定,當前使用者購買成功後,釋放鎖,允許其他使用者操作該條資料。
2、佇列
將請求放入佇列中,也就是所有的請求都進行排隊等待,按照順序依次處理。併發請求都放到佇列中,由額外程序序列處理,併發問題就不存在了,但是要額外程序支援以及處理延遲嚴重。
以上兩種方案都避免不了“等待”的問題,高併發極端場景下,很可能會造成系統響應異常。暫時不對這兩種方案作詳解。
最近在學習 redis,發現可以結合 redis 的事物和 watch 命令巧妙解決超賣的問題。
老規矩,使用 watch 之前先來了解下它的特性。畢竟使用場景是以事物的特性為基礎的。
watch 命令可以監控一個或多個鍵,一旦其中一個鍵被修改或刪除,之後的事物就不會執行。監控一直持續到 exec 命令。
話不多說,直接上程式碼。
$redis = JRedis::getInstance(); $key = 'saleCount:id:3'; $redis->watch($key); //銷量 $sales = $redis->get($key); //庫存 $qty = 8; if ($sales >= $qty) { exit("已售罄"); } //開啟事務 $redis->multi(); $redis->incrby($key, 1); $result = $redis->exec(); if ($result) { //執行資料庫的銷量增加操作,執行訂單建立等操作 exit("校驗成功,開始資料庫操作"); } else { $redis->incrby($key, -1); exit("重新下單"); }
親測效果槓槓的,而且就效率來說,要優於鎖和佇列。而且,還可以使用 redis 分攤資料庫的壓力,豈不是美滋滋。
5分推薦。
好文章分享:
https://zhuanlan.zhihu.com/p/269746986
https://zhuanlan.zhihu.com/p/336113193