高併發下搶購

2021-08-23 12:30:21 字數 1186 閱讀 4426

了解高併發以及怎麼處理後,測試一下專案中下單的**,邏輯很簡單,goods表中stock設定為unsigned。剛開始你可能會覺得這樣會出現超單的情況,但是測試後,沒有出現超單的情況。看似沒有問題,但是看過日誌發現問題還挺多的。這之前請看下這篇文章裡面有處理高併發下單的情況。

$goods_id;

$num;

$goods_model = goodsmodel::self();

$goods = $goods_model->where('id', $goods_id)->field('stock')->find();

if ($goods['stock'] < $num)

$goods_model->starttrans();

try

$goods_model->commit();

}} catch (\exception $e)

這裡無意間用了上述文章中的優化方案一,沒有超單得虧了資料庫欄位有設定stock為unsigned,導致很多請求其實有報錯資訊:numeric value out of range: 1690 bigint unsigned value is out of range。其次是很多請求已經通過了下單的判斷(這裡實在是阻止不了多個請求同時通過這個判斷),最後是庫存為0後商品並沒有自動下架。要解決上述情況還有要加上優化方案二里的加鎖。加了鎖後問題都解決了。

$goods = $goods_model->where('id', $goods_id)->field('stock')->lock(true)->find();
我一直不喜歡鎖,1是不太了解鎖的原理,2是有各種鎖,樂觀鎖,悲觀鎖等,3是鎖很耗資料庫效能,但是不加的話又會出現問題。這裡用了主鍵id查詢,鎖的是行資料,如果不是用了主鍵,鎖的是整個資料表,很影響效能的(怎麼個影響法也沒仔細研究,容易出現死鎖吧)。雖然不喜歡用鎖,但是很多涉及到重要字段(即使不是高併發的情況)的地方都會加鎖,之前就是有乙個地方沒加鎖,導致使用者資金出現問題,幸虧早發現。

網上很多都是說用redis佇列的,提前建立列表,然後pop資料,因為redis是單執行緒而且是原子性的,保證不會超單。這種也試了,是可行的,網上也有很多教程就不細說了。

總結一下,資料庫字段哪些不能負數的都設定為unsigned,一些重要的操作加事務和加鎖,這樣就可以避免很多問題。當然這些不會是最好的做法,卻是最簡單最好用能解決大多問題的方法。

redis實現高併發下的搶購 秒殺功能

常規寫法 查詢出對應商品的庫存,看是否大於0,然後執行生成訂單等操作,但是在判斷庫存是否大於0處,如果在高併發下就會有問題,導致庫存量出現負數 redis的解決方案 1,inlcude oncea include db.php redis new redis resid connect 127.0....

php結合redis實現高併發下的搶購 秒殺功能

搶購 秒殺是如今很常見的乙個應用場景,主要需要解決的問題有兩個 1 高併發對資料庫產生的壓力 2 競爭狀態下如何解決庫存的正確減少 超賣 問題 對於第乙個問題,已經很容易想到用快取來處理搶購,避免直接運算元據庫,例如使用redis。重點在於第二個問題 優化方案1 將庫存欄位number欄位設為uns...

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

在電子商務發達的今天,各種秒殺,搶購活動的場景不少,如何解決高併發下出現的訂單超發情況呢?在常規情況下,我們會根據使用者提交的請求去查詢商品庫存,如果庫存小於0則訂單生成失敗。但是這種情況下經常了訂單需要的數量超過了庫存數量,即出現負庫存。先討論常規場景測試 我們在redis中設定乙個庫存表,就是個...