高并發秒殺系統如何鎖住庫存

?

博主介紹:?全網粉絲5W+,全棧開發工程師,從事多年軟件開發,在大廠呆過。持有軟件中級、六級等證書。可提供微服務項目搭建與畢業項目實戰,博主也曾寫過優秀論文,查重率極低,在這方面有豐富的經驗?

博主作品:《Java項目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+MySQL+Vue等前后端分離項目,可以在左邊的分類專欄找到更多項目。《Uniapp項目案例》有幾個有uniapp教程,企業實戰開發。《微服務實戰》專欄是本人的實戰經驗總結,《Spring家族及微服務系列》專注Spring、SpringMVC、SpringBoot、SpringCloud系列、Nacos等源碼解讀、熱門面試題、架構設計等。除此之外還有不少文章等你來細細品味,更多驚喜等著你哦

🍅uniapp微信小程序🍅面試題軟考題免費使用,還可以使用微信支付,掃碼加群。由于維護成本問題得不到解決,可能將停止線上維護。

🍅文末獲取聯系🍅精彩專欄推薦訂閱👇🏻👇🏻 不然下次找不到喲

Java項目案例《100套》
https://blog.csdn.net/qq_57756904/category_12173599.html
uniapp小程序《100套》

https://blog.csdn.net/qq_57756904/category_12173599.html

有需求代碼永遠寫不完,而方法才是破解之道,抖音有實戰視頻課程,某馬某千等培訓都是2萬左右,甚至廣東有本科院校單單一年就得3萬4年就12萬學費,而且還沒有包括吃飯的錢。所以很劃算了。另外博客左側有源碼閱讀專欄,對于求職有很大幫助,當然對于工作也是有指導意義等。在大城市求職,你面試來回一趟多多少少都在12塊左右,而且一般不會一次性就通過,還得面試幾家。而如果你對源碼以及微服務等有深度認識,這無疑給你的面試添磚加瓦更上一層樓。

最后再送一句:最好是學會了,而不是學廢了!!

2

在秒殺系統中,庫存鎖定是防止超賣的關鍵環節。以下是幾種高效可靠的庫存鎖定方案:

一、Redis原子操作方案(推薦)

1. 基于DECR的原子扣減

public boolean lockStockWithRedis(Long itemId, int quantity) {String key = "seckill:stock:" + itemId;// Lua腳本保證原子性String script ="local stock = tonumber(redis.call('get', KEYS[1])) " +"if stock >= tonumber(ARGV[1]) then " +"   return redis.call('decrby', KEYS[1], ARGV[1]) " +"else " +"   return -1 " +"end";Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(key),String.valueOf(quantity));return result != null && result >= 0;
}

2. 分布式鎖+庫存扣減

public boolean lockStockWithDistributedLock(Long itemId, int quantity) {String lockKey = "seckill:lock:" + itemId;RLock lock = redissonClient.getLock(lockKey);try {// 嘗試加鎖,等待時間100ms,鎖持有時間30sif (lock.tryLock(100, 30000, TimeUnit.MILLISECONDS)) {try {String stockKey = "seckill:stock:" + itemId;Long stock = redisTemplate.opsForValue().get(stockKey);if (stock != null && stock >= quantity) {redisTemplate.opsForValue().decrement(stockKey, quantity);return true;}} finally {lock.unlock();}}} catch (InterruptedException e) {Thread.currentThread().interrupt();}return false;
}

二、數據庫方案

1. 樂觀鎖實現

@Update("UPDATE item_stock SET stock = stock - #{quantity}, version = version + 1 " +"WHERE item_id = #{itemId} AND stock >= #{quantity} AND version = #{version}")
int deductStockWithOptimisticLock(@Param("itemId") Long itemId, @Param("quantity") int quantity,@Param("version") int version);

2. 悲觀鎖實現

@Select("SELECT * FROM item_stock WHERE item_id = #{itemId} FOR UPDATE")
ItemStock selectForUpdate(Long itemId);public boolean lockStockWithPessimisticLock(Long itemId, int quantity) {// 在事務中執行ItemStock stock = stockMapper.selectForUpdate(itemId);if (stock.getStock() >= quantity) {stock.setStock(stock.getStock() - quantity);stockMapper.update(stock);return true;}return false;
}

三、預扣庫存方案

1. 兩階段庫存鎖定

public boolean twoPhaseLockStock(Long itemId, int quantity, String orderNo) {// 第一階段:預扣Redis庫存if (!lockStockWithRedis(itemId, quantity)) {return false;}// 第二階段:異步持久化mqTemplate.send("stock_prelock_topic", new StockLockEvent(itemId, quantity, orderNo));return true;
}// 消費者處理
public void handleStockLock(StockLockEvent event) {try {// 數據庫最終扣減int updated = stockMapper.realDeduct(event.getItemId(), event.getQuantity());if (updated <= 0) {// 回滾RedisredisTemplate.opsForValue().increment("seckill:stock:" + event.getItemId(), event.getQuantity());// 標記訂單失敗orderService.markAsFailed(event.getOrderNo());}} catch (Exception e) {// 異常處理}
}

四、庫存分段方案(應對熱點商品)

public boolean segmentLockStock(Long itemId, int quantity) {// 將庫存分成16個段final int SEGMENTS = 16;int segment = (int) (itemId % SEGMENTS);String segmentKey = "seckill:stock:seg:" + itemId + ":" + segment;// 每個段維護部分庫存Long remain = redisTemplate.opsForValue().decrement(segmentKey, quantity);if (remain != null && remain >= 0) {return true;} else {// 回滾redisTemplate.opsForValue().increment(segmentKey, quantity);return false;}
}

五、庫存回滾機制

public boolean rollbackStock(Long itemId, int quantity) {String key = "seckill:stock:" + itemId;Long result = redisTemplate.opsForValue().increment(key, quantity);// 同時記錄回滾流水stockFlowMapper.insert(new StockFlow(itemId, "ROLLBACK", quantity));return result != null;
}

六、庫存狀態檢查

public StockLockResult checkStockLock(String orderNo) {// 檢查訂單狀態Order order = orderMapper.selectByNo(orderNo);if (order == null) {return StockLockResult.notFound();}// 檢查庫存鎖定狀態String lockKey = "seckill:lock:" + order.getItemId() + ":" + orderNo;boolean locked = redisTemplate.hasKey(lockKey);if (order.getStatus() == OrderStatus.PAID) {return StockLockResult.success();} else if (locked) {return StockLockResult.locking();} else {return StockLockResult.failed();}
}

七、方案對比

方案優點缺點適用場景
Redis原子操作性能高,實現簡單需要保證Redis高可用絕大多數秒殺場景
樂觀鎖無額外依賴高并發下重試率高并發量適中的場景
悲觀鎖強一致性性能差,可能死鎖對一致性要求極高的場景
預扣庫存用戶體驗好實現復雜需要快速響應的場景
庫存分段減少競爭庫存分配需合理超級熱點商品

最佳實踐建議

  1. 組合使用:Redis原子操作 + 異步數據庫更新 + 定時核對

  2. 監控報警

    • 庫存鎖定成功率

    • Redis庫存與數據庫庫存差異

    • 鎖定/釋放比例異常

  3. 壓測驗證:模擬峰值流量驗證鎖庫存邏輯

  4. 兜底方案

    // 庫存鎖定兜底檢查
    @Scheduled(fixedRate = 60000)
    public void checkStockConsistency() {List<Item> items = itemMapper.selectAll();items.forEach(item -> {Long redisStock = redisTemplate.opsForValue().get("seckill:stock:" + item.getId());if (redisStock != null && !redisStock.equals(item.getStock())) {alarmService.notify("庫存不一致:" + item.getId());}});
    }

通過以上方案,可以有效解決秒殺系統中的庫存鎖定問題,在保證系統高并發的條件下防止超賣現象。

3

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901226.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901226.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901226.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Docker】Dockerfile 編寫實踐

&#x1f47b;創作者&#xff1a;丶重明 &#x1f47b;創作時間&#xff1a;2025年4月8日 &#x1f47b;擅長領域&#xff1a;運維 目錄 1. Dockerfile編寫原則1.1.選擇合適的基礎鏡像1.2.鏡像層優化1.3.多階段構建1.4.安全增強 2. 關鍵指令與技巧2.1.COPY vs ADD2.2.ENTRYPOIN…

【數學建模】(智能優化算法)螢火蟲算法(Firefly Algorithm)詳解與實現

螢火蟲算法(Firefly Algorithm)詳解與實現 文章目錄 螢火蟲算法(Firefly Algorithm)詳解與實現前言1. 算法原理2. 算法流程3. Python實現4. 算法特點4.1 優點4.2 缺點 5. 應用領域6. 算法變種7. 總結與展望參考文獻 前言 大家好&#xff0c;今天給大家介紹一種有趣且高效的群體…

VSCode會擊敗Cursor和Windsurf嗎?

VSCode 會擊敗 Cursor 和 Windsurf 嗎&#xff1f;微軟能不能靠自己的地盤優勢和規則限制打壓對手&#xff1f;答案是"能"&#xff0c;但他們真的會這么干嗎&#xff1f; Cursor & Windsurf vs VSCode Copilot 大PKAI編程工具大戰越來越激烈現在最火最賺錢的AI…

2025-4-11 情緒周期視角復盤(mini)

簡單說兩句好了&#xff0c;做一個階段記錄&#xff0c;目前階段就是上一輪 中毅達 第二輪補漲的退潮結束&#xff0c;回盛生物 金河生物 它們的題材導致 農業和醫藥這2個題材退潮&#xff0c;注意的是不靠譜導致的反制題材是在這個二輪補漲周期里一起走的&#xff0c;所以 海…

【SLAM】將realsense-viewer錄制的rosbag視頻導出成圖片序列(RealSense D435)

本文介紹了如何將realsense-viewer錄制的rosbag格式的視頻導出成圖片序列&#xff0c;方便合并成mp4視頻或插入到論文中。 本文首發于?慕雪的寒舍 說明 Intel提供的realsense-viewer軟件錄制的視頻都是rosbag格式的&#xff0c;為了編寫論文&#xff0c;需要從錄制的視頻中截…

Ubuntu ROS 對應版本

Ubuntu 18.04 (Bionic Beaver) - 2018年4月發布 對應的ROS版本&#xff1a;ROS Melodic (2018年5月發布) Ubuntu 20.04 (Focal Fossa) - 2020年4月發布 對應的ROS版本&#xff1a;ROS Noetic (2020年5月發布) Ubuntu 22.04 (Jammy Jellyfish) - 預計2022年4月發布 對應的ROS版…

Ubuntu 軟件卸載與清理終極指南

Ubuntu 軟件卸載與清理指南 適用范圍&#xff1a;Ubuntu 及其衍生發行版&#xff08;如 Linux Mint、Pop!_OS 等&#xff09;&#xff0c;Debian 系統大部分方法也適用。 目標&#xff1a;幫助你快速、徹底卸載軟件并清理殘余文件&#xff0c;保持系統整潔。 前提&#xff1a;建…

基于javaweb的SpringBoot新聞視頻發布推薦評論系統(源碼+部署文檔)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論文…

Linux-內核驅動

open uboot.bin target-connect U-Boot&#xff08;Universal Boot Loader&#xff09;是一種廣泛使用的開源引導加載程序&#xff0c;它允許用戶從各種設備&#xff08;如硬盤、USB設備、網絡等&#xff09;加載操作系統。U-Boot提供了豐富的命令行接口&#xff08;CLI&#…

DAPP實戰篇:使用ethers.js連接以太坊智能合約

專欄:區塊鏈入門到放棄查看目錄-CSDN博客文章瀏覽閱讀344次。為了方便查看將本專欄的所有內容列出目錄,按照順序查看即可。后續也會在此規劃一下后續內容,因此如果遇到不能點擊的,代表還沒有更新。聲明:文中所出觀點大多數源于筆者多年開發經驗所總結,如果你想要知道區塊…

[原創](現代Delphi 12指南): 設置、運行和調試你的第一個macOS應用程序.

[作者] 常用網名: 豬頭三 出生日期: 1981.XX.XX 企鵝交流: 643439947 個人網站: 80x86匯編小站 編程生涯: 2001年~至今[共24年] 職業生涯: 22年 開發語言: C/C、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 開發工具: Visual Studio、Delphi、XCode、C …

Adobe Photoshop 2025 Mac中文 Ps圖像編輯

Adobe Photoshop 2025 Mac中文 Ps圖像編輯 一、介紹 Adobe Photoshop 2025 Mac版集成了多種強大的圖像編輯、處理和創作功能。①強化了Adobe Sensei AI的應用&#xff0c;通過智能摳圖、自動修復、圖像生成等功能&#xff0c;用戶能夠快速而精確地編輯圖像。②3D編輯和動畫功…

藍橋杯備賽知識點總結

一、數論 如果想要計算整除向上取整&#xff08;xy-1&#xff09;/y 或者&#xff08;x-1&#xff09;/y 1 最大公約數&#xff1a; int gcd(int a,int b){return b0?a:gcd(b,a%b); }最小公倍數&#xff1a; int lcm(int a,int b){return a/gcd(a,b)*b; } 埃氏篩法&#…

設計模式 --- 狀態模式

狀態模式??是一種??行為型設計模式??&#xff0c;允許對象在內部狀態改變時動態改變其行為??&#xff0c;使對象的行為看起來像是改變了。該模式通過將狀態邏輯拆分為獨立類??&#xff0c;消除復雜的條件分支語句&#xff0c;提升代碼的可維護性和擴展性。 狀態模式的…

【讀者求助】如何跨行業進入招聘崗位?

文章目錄 讀者留言回信崗位細分1. 中介公司的招聘崗位2. 獵頭專員3. 公司的招聘專員選擇建議 面試建議1. 請簡單介紹你過去 3 年的招聘工作經歷&#xff0c;重點說下你負責的崗位類型和規模2. 你在招聘流程中最常用的渠道有哪些&#xff1f;如何評估渠道效果&#xff1f;3. 當你…

AI Agent入門指南

圖片來源網絡 ?一、開箱暴擊&#xff1a;你以為的"智障音箱"&#xff0c;其實是賽博世界的007? ?1.1 從人工智障到智能叛逃&#xff1a;Agent進化史堪比《甄嬛傳》? ?青銅時代&#xff08;2006-2015&#xff09;? “小娜同學&#xff0c;關燈” “抱歉&…

pnpm 中 Next.js 模塊無法找到問題解決

問題概述 項目在使用 pnpm 管理依賴時,出現了 “Cannot find module ‘next/link’ or its corresponding type declarations” 的錯誤。這是因為 pnpm 的軟鏈接機制在某些情況下可能導致模塊路徑解析問題。 問題診斷 通過命令 pnpm list next 確認項目已安裝 Next.js 15.2.…

vulnhub:sunset decoy

靶機下載地址https://www.vulnhub.com/entry/sunset-decoy,505/ 滲透過程 簡單信息收集 nmap 192.168.56.0/24 -Pn # 確定靶機ip&#xff1a;192.168.56.121 nmap 192.168.56.121 -A -T4 # 得到開放端口22,80 在80端口得到save.zip&#xff0c;需要密碼解壓。 john破解壓縮…

代碼學習總結(一)

代碼學習總結&#xff08;一&#xff09; 這個系列的博客是記錄下自己學習代碼的歷程&#xff0c;有來自平臺上的&#xff0c;有來自筆試題回憶的&#xff0c;主要基于 C 語言&#xff0c;包括題目內容&#xff0c;代碼實現&#xff0c;思路&#xff0c;并會注明題目難度&…

OSPF的接口網絡類型【復習篇】

OSPF在不同網絡環境下默認的不同工作方式 [a3]display ospf interface g 0/0/0 # 查看ospf接口的網絡類型網絡類型OSPF接口的網絡類型&#xff08;工作方式&#xff09;計時器BMA&#xff08;以太網&#xff09;broadcast &#xff0c;需要DR/BDR的選舉hello&#xff1a;10s…