Redis實現高併發下的搶購,秒殺,解決方案

2021-08-10 12:32:50 字數 1465 閱讀 3812

在電子商務發達的今天,各種秒殺,搶購活動的場景不少,如何解決高併發下出現的訂單超發情況呢?

在常規情況下,我們會根據使用者提交的請求去查詢商品庫存,如果庫存小於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....