在電子商務發達的今天,各種秒殺,搶購活動的場景不少,如何解決高併發下出現的訂單超發情況呢?
在常規情況下,我們會根據使用者提交的請求去查詢商品庫存,如果庫存小於0則訂單生成失敗。但是這種情況下經常了訂單需要的數量超過了庫存數量,即出現負庫存。
先討論常規場景測試:
我們在redis中設定乙個庫存表,就是個簡單的string型別, 用以標示庫存即可。
set inventory 100
使用多程序測試如下:因為我的ab測試不能用。所以使用多程序的方式進行
//register a signal
pcntl_signal(sigchld, sig_ign);
$times = 200;
while ($times-- > 0) else
}sleep(20);
function order() else
die;
}
執行結果變為了負數:
如何解決這個問題呢? 熟悉redis 的同學都知道 redis 支援事務,我們加個事務試試。
<?php
//register a signal
pcntl_signal(sigchld, sig_ign);
$times = 200;
while ($times-- > 0) else
}sleep(20);
function order() else
die;
}?>
同樣結果還是會變成負數。
接下來可以使用redis 的watch 實現乙個樂觀鎖來試試
<?php
//register a signal
pcntl_signal(sigchld, sig_ign);
$times = 200;
while ($times-- > 0) else
}sleep(20);
function order()
$conn->multi();
$conn->decr("inventory");
} while ($conn->exec());
die;
}?>
執行結果:
大致場景就是這樣的, 如果是搶購,每次只搶購乙個 可以往佇列裡新增庫存個商品的1 佇列, 如圖:
當使用者每次搶購丟擲乙個佇列,然後再去減少真正的庫存即可。 當然真實的場景要稍複雜一些, 不過原理就是這樣的。
成功!
php結合redis實現高併發下的搶購 秒殺功能
搶購 秒殺是如今很常見的乙個應用場景,主要需要解決的問題有兩個 1 高併發對資料庫產生的壓力 2 競爭狀態下如何解決庫存的正確減少 超賣 問題 對於第乙個問題,已經很容易想到用快取來處理搶購,避免直接運算元據庫,例如使用redis。重點在於第二個問題 優化方案1 將庫存欄位number欄位設為uns...
高併發下搶購
了解高併發以及怎麼處理後,測試一下專案中下單的 邏輯很簡單,goods表中stock設定為unsigned。剛開始你可能會覺得這樣會出現超單的情況,但是測試後,沒有出現超單的情況。看似沒有問題,但是看過日誌發現問題還挺多的。這之前請看下這篇文章裡面有處理高併發下單的情況。goods id num g...
redis實現高併發下的搶購 秒殺功能
常規寫法 查詢出對應商品的庫存,看是否大於0,然後執行生成訂單等操作,但是在判斷庫存是否大於0處,如果在高併發下就會有問題,導致庫存量出現負數 redis的解決方案 1,inlcude oncea include db.php redis new redis resid connect 127.0....