秒殺系統的實現

2021-10-06 03:57:33 字數 1196 閱讀 3899

按照正常的購買流程:查詢商品庫存,庫存大於0時,生成訂單,去庫存。如果出現併發,導致在查詢商品庫存的時候,庫存會一直出現大於0的情況,出現超賣現象。

基於mysql的事務和鎖實現方式:

如果不開啟事務,第二步即使加鎖,第乙個會話讀庫存結束後,變會釋放鎖,第二個會話仍有機會在去庫存前讀庫存,出現超賣。

如果開啟事務,第二步不加鎖,第乙個會話讀庫存結束後,第二個會話容易出現【髒讀】,出現超賣。

即加事務,又加讀鎖:開啟事務,第乙個會話讀庫存時加讀鎖,併發時,第二個會話也允許獲得讀庫存的讀鎖,但是在第乙個會話執行寫操作時,寫鎖便會等待第二個會話的讀鎖,第二個會話執行寫操作時,寫鎖便會等待第乙個會話的讀鎖,出現死鎖

即加事務,又加寫鎖:第乙個會話讀庫存時加寫鎖,寫鎖會阻止其它事務的讀鎖和寫鎖。直到commit才會釋放,允許第二個會話查詢庫存,不會出現超賣現象。

先查詢redis中是否有庫存資訊,如果沒有就去資料庫查,這樣就可以減少訪問資料庫的次數。 獲取到後把數值填入redis,以商品id為key,數量為value。 注意要設定序列化方式為stringredisserializer,不然不能把value做加減操作。 還需要設定redis對應這個key的超時時間,以防所有商品庫存資料都在redis中。

比較下單數量的大小,如果夠就做後續邏輯。

執行redis客戶端的increment,引數為負數,則做減法。因為redis是單執行緒處理,並且因為increment讓key對應的value 減少後返回的是修改後的值。 有的人會不做第一步查詢直接減,其實這樣不太好,因為當庫存為1時,很多做減3,或者減30情況,其實都是不夠,這樣就白減。

扣減資料庫的庫存,這個時候就不需要再select查詢,直接樂觀鎖update,把庫存欄位值減1 。

做完扣庫存就在訂單系統做下單。

public void order(orderreq req) 

// 減少經常訪問資料庫,因為磁碟比記憶體訪問速度要慢

}if (num < req.getnum())

// 第二步:減少庫存

long value = redistemplate.increment(key, -req.getnum().lon**alue());

// 庫存充足

if (value >= 0) else

}

redis實現的秒殺系統

利用redis的樂觀鎖,實現秒殺系統的資料同步 基於watch實現 import redis conn redis.redis host 127.0.0.1 port 6379 conn.set count 1000 with conn.pipeline as pipe 先監視,自己的值沒有被修改過...

秒殺系統實現總結

訪問量大,對網路頻寬要求高 系統如何支援瞬間的高併發 如何防止商品超賣 如何防刷 防黃牛等 cdn快取,nginx lua實現活動資料快取2秒 高併發 限流 防刷 超賣 使用redis實現原子性的操作 防刷 openresty lua 實現限流 驗證黑名單等 黑名單機制 手動 自動收集ip user...

秒殺系統的設計與實現

redis 高併發鎖機制 如何限制乙個ip使用搶購軟體?秒殺的超賣問題?將存庫從mysql前移到redis中,所有的寫操作放到記憶體中,由於redis中不存在鎖故不會出現互相等待,並且由於redis的寫效能和讀效能都遠高於mysql,這就解決了高併發下的效能問題。然後通過佇列等非同步手段,將變化的資...