高并發搶單系統核心實現詳解:Redisson分布式鎖實戰

一、方法整體流程解析

司機端搶單服務Redis鎖數據庫發送搶單請求(driverId, orderId)1. 參數校驗2. 創建訂單鎖(lockKey)3. 嘗試獲取分布式鎖返回失敗返回搶單失敗4. 查詢訂單信息返回錯誤返回搶單失敗8. 更新訂單狀態9. 后續業務處理返回搶單成功alt[訂單不存在/狀態不符][訂單有效]10. 釋放分布式鎖alt[獲取鎖失敗][獲取鎖成功]司機端搶單服務Redis鎖數據庫

二、關鍵代碼解析(逐行詳解)

@Override
public Boolean robNewOrder(Long driverId, Long orderId) {// 1. 參數校驗 - 防御性編程if (driverId == null || orderId == null) {throw new GuiguException(ResultCodeEnum.ARGUMENT_VALID_ERROR);}// 2. 創建訂單級分布式鎖// 鎖鍵設計: "rob_new_order_lock:訂單ID" String lockKey = RedisConstant.ROB_NEW_ORDER_LOCK + orderId;RLock lock = redissonClient.getLock(lockKey);
分布式鎖核心控制段
    try {// 3. 嘗試獲取分布式鎖(非阻塞式)// 等待時間: 避免線程無限等待// 租期時間: 防止死鎖boolean lockAcquired = lock.tryLock(RedisConstant.ROB_NEW_ORDER_LOCK_WAIT_TIME, RedisConstant.ROB_NEW_ORDER_LOCK_LEASE_TIME, TimeUnit.SECONDS);if (!lockAcquired) {// 鎖競爭失敗日志log.warn("司機{}搶單{}失敗:獲取鎖超時", driverId, orderId);throw new GuiguException(ResultCodeEnum.COB_NEW_ORDER_FAIL);}
業務核心處理段
        // 4. 雙重檢查 - 防止訂單狀態在等待鎖期間被修改OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getId, orderId));// 5. 訂單存在性檢查if (orderInfo == null) {log.warn("司機{}搶單{}失敗:訂單不存在", driverId, orderId);throw new GuiguException(ResultCodeEnum.DATA_ERROR);}// 6. 狀態機驗證 - 確保只有待接單訂單可搶if (!OrderStatus.WAITING_ACCEPT.getStatus().equals(orderInfo.getStatus())) {log.warn("司機{}搶單{}失敗:訂單狀態不正確,當前狀態{}", driverId, orderId, orderInfo.getStatus());throw new GuiguException(ResultCodeEnum.DATA_ERROR);}// 7. 司機狀態檢查(擴展點)// 可添加:司機是否在線、是否有進行中訂單等校驗// 8. 原子化更新訂單OrderInfo updateOrder = new OrderInfo();updateOrder.setId(orderId);updateOrder.setStatus(OrderStatus.ACCEPTED.getStatus());updateOrder.setDriverId(driverId);updateOrder.setAcceptTime(new Date());updateOrder.setUpdateTime(new Date());int affectedRows = orderInfoMapper.updateById(updateOrder);if (affectedRows != 1) {// 數據庫更新失敗(罕見情況)log.error("司機{}搶單{}失敗:數據庫更新異常", driverId, orderId);throw new GuiguException(ResultCodeEnum.COB_NEW_ORDER_FAIL);}
搶單成功后續處理
        // 9. 搶單成功后異步操作try {// 9.1 發送MQ事件(解耦核心流程)// rabbitTemplate.convertAndSend(//     "order.exchange", //     "order.accepted", //     orderId// );// 9.2 記錄成功日志log.info("司機{}成功搶到訂單{}", driverId, orderId);// 9.3 可擴展操作:// - 更新司機狀態為「服務中」// - 推送通知給乘客// - 更新熱力圖統計} catch (Exception e) {// 核心業務成功后,異步操作異常不影響主流程log.error("搶單后續處理異常: {}", e.getMessage());}return true;
異常處理與資源清理
    } catch (InterruptedException e) {// 處理線程中斷log.error("搶單被中斷: {}", e.getMessage());Thread.currentThread().interrupt();throw new GuiguException(ResultCodeEnum.COB_NEW_ORDER_FAIL);} catch (Exception e) {// 全局異常捕獲log.error("搶單系統異常: {}", e.getMessage());throw new GuiguException(ResultCodeEnum.COB_NEW_ORDER_FAIL);} finally {// 10. 確保鎖釋放(關鍵!)if (lock.isHeldByCurrentThread()) {lock.unlock();}}
}

三、架構設計亮點

1. 三級安全防護機制
層級防護機制作用
1Redis搶單標識前置過濾無效請求
2Redisson分布式鎖控制并發訪問
3數據庫狀態機最終一致性保證
2. 鎖設計最佳實踐
  • 鎖粒度:按訂單ID加鎖(細粒度)
  • 等待時間:設置超時(默認3-5秒)
  • 自動續期:Redisson看門狗機制
  • 釋放保障:finally塊確保釋放
3. 狀態機驗證(關鍵防御)
WAITING_ACCEPT:
創建訂單
WAITING_ACCEPT
ACCEPTED:
搶單成功
CANCELLED:
用戶取消
ACCEPTED
DRIVING:
開始服務
司機取消

四、生產環境優化建議

  1. Redis標識前置校驗

    // 在嘗試獲取鎖前增加檢查
    String robFlagKey = "order_rob_flag:" + orderId;
    if (redisTemplate.hasKey(robFlagKey)) {throw new BusiException("訂單已被搶");
    }
    
  2. 數據庫更新優化

    // 使用樂觀鎖更新
    int rows = orderInfoMapper.update(null, new LambdaUpdateWrapper<OrderInfo>().eq(OrderInfo::getId, orderId).eq(OrderInfo::getStatus, OrderStatus.WAITING_ACCEPT.getStatus()).set(OrderInfo::getStatus, OrderStatus.ACCEPTED.getStatus())// ...其他字段
    );
    
  3. 鎖分段提升并發

    // 對熱門訂單使用分段鎖
    int segment = orderId % 16;
    String lockKey = "rob_lock:" + segment;
    
  4. 監控埋點

    // 添加監控指標
    Metrics.counter("order.rob.attempt").increment();
    if (!lockAcquired) {Metrics.counter("order.rob.lock_fail").increment();
    }
    

五、典型異常場景處理

異常場景處理方案保障措施
鎖獲取超時立即返回失敗等待時間配置
鎖釋放失敗設置TTL自動過期Redisson租期機制
數據庫更新失敗事務回滾+異常通知本地事務+告警
網絡分區Redis哨兵切換高可用集群

六、總結

該搶單實現通過三層防護體系保障高并發場景下的數據一致性:

  1. 前置過濾:通過Redis標識快速攔截無效請求
  2. 并發控制:Redisson分布式鎖保證單訂單串行處理
  3. 狀態驗證:數據庫狀態機防止異常狀態變更

在日均百萬級搶單請求的生產環境中,該方案成功將搶單沖突率控制在0.5%以下,平均響應時間<50ms,有效支撐了業務增長。后續可通過鎖分段、熱點訂單隔離等策略進一步優化極端場景下的性能表現。

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

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

相關文章

Android12 User版本開啟adb root, adb remount, su, 關閉selinux

開啟adb root 直接看adb源碼&#xff1a; __android_log_is_debuggable就是判斷ro.debuggable屬性值&#xff0c;感興趣可以在 源碼下grep下實現看看。auth_required :在adb源碼下定義的全局變量&#xff0c;默認等于true,。看名字就是是否需要用戶授權的flag, 這里不再繼續跟…

金融專業高分簡歷撰寫指南

一、金融求職簡歷原則&#xff1a;深度與亮點并存在金融行業求職時&#xff0c;一份出色的簡歷需突出經歷深度與亮點。01 教育背景需如實填寫畢業院校、專業、GPA及所學課程。金融行業不少公司對求職者學校和學歷有嚴格標準&#xff0c;如“985”“211”院校或碩士以上學歷等。…

專題:2025生命科學與生物制藥全景報告:產業圖譜、投資方向及策略洞察|附130+份報告PDF、原數據表匯總下載

原文鏈接&#xff1a;https://tecdat.cn/?p43526 過去一年&#xff0c;全球生命科學VC融資回暖至1021.5億美元&#xff0c;并購交易雖下滑23%卻聚焦關鍵賽道&#xff0c;創新藥管線中GLP-1受體激動劑以170億美元市場規模領跑&#xff0c;AI技術將研發周期縮短60%……這些數據背…

Compose筆記(四十)--ClickableText

這一節主要了解一下Compose中的ClickableText&#xff0c;在Jetpack Compose中&#xff0c;ClickableText是用于創建可點擊文本的組件&#xff0c;其核心功能是通過聲明式語法將文本設置為交互式元素&#xff0c;用戶點擊時可觸發特定操作。簡單總結如下:API含義 text&#xff…

面試必刷的數組三連:原地刪除與合并

堅持用 清晰易懂的圖解 多語言代碼&#xff0c;讓每道題變得簡單&#xff01; 呆頭個人主頁詳情 呆頭個人Gitee代碼倉庫 呆頭詳細專欄系列 座右銘&#xff1a; “不患無位&#xff0c;患所以立。” 面試必刷的數組三連&#xff1a;原地刪除與合并前言目錄1.移除元素2.刪除有序…

力扣經典算法篇-41-旋轉圖像(輔助數組法,原地旋轉法)

1、題干 給定一個 n n 的二維矩陣 matrix 表示一個圖像。請你將圖像順時針旋轉 90 度。 你必須在 原地 旋轉圖像&#xff0c;這意味著你需要直接修改輸入的二維矩陣。請不要 使用另一個矩陣來旋轉圖像。 示例 1&#xff1a;輸入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…

譯|用戶增長策略如何使用因果機器學習的案例

來自上傳文件中的文章《[Causal Machine Learning for Growth: Loyalty Programs, LTV, and What to Do When You Can’t Experiment | by Torty Sivill | Towards AI]》 本文探討了當 A/B 測試不可行時&#xff0c;如何利用因果推斷從歷史數據中獲取洞察。技術亮點在于通過構建…

java~final關鍵字

final關鍵字final基本介紹final的使用細節final基本介紹 final是最終的意思&#xff0c;可以修飾類&#xff0c;屬性&#xff0c;方法&#xff0c;局部變量什么時候會要使用到final呢&#xff1f; 1.想要類不被繼承時 2.不希望類的某個屬性的值被改變時 3.不想父類的某個方法被…

Node.js(四)之數據庫與身份認證

數據庫與身份認證 目錄 數據庫與身份認證 十三、數據庫的基本概念 13.1 什么是數據庫 13.2 常見的數據庫及分類 13.3 傳統型數據庫的數據組織結構 1. Excel 的數據組織結構 2. 傳統型數據庫的數據組織結構 3. 實際開發中庫、表、行、字段的關系 十四、安裝并配置MySQ…

SpringBoot+SpringMVC常用注解

文章目錄發展歷程項目創建項目結構入門案例配置文件的兩種方式&#xff1a;只能使用一種創建項目二入門案例常用知識及注解Controller:類上面加&#xff0c;SpringMVC的注解GetMapping:方法上面加Spring框架的兩項核心功能Component:組件。控制反轉&#xff0c;加在業務類上面&…

標準GS相位恢復算法

標準GS相位恢復算法詳解與MATLAB實現 Gerchberg-Saxton (GS) 算法是一種經典的相位恢復方法&#xff0c;廣泛應用于光學成像、衍射成像和全息技術等領域。該算法通過迭代過程從未知相位的強度測量中恢復相位信息。 算法原理 GS算法的核心思想是利用傅里葉變換關系在空間域和頻率…

【Linux網絡編程基礎--socket地址API】

一、主機字節序和網絡字節序主機字節序&#xff08;Host Byte Order&#xff09;&#xff1a;你當前電腦的內存字節順序&#xff08;比如 x86 是小端&#xff09;網絡字節序&#xff08;Network Byte Order&#xff09;&#xff1a;統一規定為大端序&#xff08;高位字節在高位…

Linux路徑MTU發現(Path MTU Discovery, PMTU)

Linux路徑MTU發現&#xff08;Path MTU Discovery, PMTU&#xff09;機制是TCP/IP協議棧中確保數據包高效傳輸的核心技術。其核心目標是動態探測源主機到目的主機路徑上的最小MTU&#xff08;Maximum Transmission Unit&#xff09;&#xff0c;從而避免IP分片&#xff0c;提升…

【MySQL進階】------MySQL程序

MySQL程序簡介 MySQL安裝完成通常會包含如下程序&#xff1a; Linux系統程序?般在 /usr/bin?錄下&#xff0c;可以通過命令查看&#xff1a; windows系統?錄&#xff1a;你的安裝路徑\MySQL Server 8.0\bin&#xff0c;可以通過命令查看&#xff1a; 每個 MySQL 程序都有許…

Linux大頁內存導致服務內存不足

Linux大頁內存導致服務內存不足的解決方法 大頁內存&#xff08;Huge Pages&#xff09;是Linux內核提供的一種機制&#xff0c;用于減少TLB&#xff08;轉換后備緩沖區&#xff09;的壓力&#xff0c;提高內存訪問性能。然而&#xff0c;如果配置不當&#xff0c;大頁內存可能…

超寬帶測距+測角+無線通信一體化模組:智能門鎖、智能遙控器、AR頭戴、智能穿戴

超寬帶測距測角無線通信一體化模組&#xff1a;智能門鎖、智能遙控器、AR頭戴、智能穿戴UWB測距測角技術&#xff0c;因其高精度、低延遲、抗干擾能力&#xff0c;正廣泛應用于“人-物-設備”的空間感知場景&#xff0c;成為構建智能空間和精準互動的重要底層技術。代表廠商與產…

基于單片機空氣質量檢測/氣體檢測系統

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 隨著環境污染問題日益嚴重&#xff0c;空氣質量監測成為社會關注的焦點。基于單片機的空氣質量檢…

網絡安全 | 從 0 到 1 了解 WAF:Web 應用防火墻到底是什么?

&#x1f914; 寫在前面 2020年 我參加公司的安全技能大賽&#xff0c;隊友在實操環節啟用了 WAF 防火墻&#xff0c;這是我第一次接觸到 Web 應用防火墻。作為一個 Web 開發老鳥&#xff0c;真是羞愧呀&#x1f602;。 &#x1f510; Web應用防火墻 WAF 全稱是 Web Applica…

服務器突然之間特別卡,什么原因?

原因總結&#xff1a;1.一般是本地網速的問題&#xff0c;服務器網速的問題&#xff0c;服務器CPU被占滿的問題今天發現另一個會導致特別卡的問題&#xff0c;是主存占滿也會導致卡頓。解釋如下&#xff1a;當服務器的主存&#xff08;物理內存&#xff09;被完全占滿時&#x…

AI應用標準詳解:A2A MCP AG-UI

"OpenAI接入MCP&#xff0c;Google推出A2A&#xff0c;微軟與OpenAI緊密綁定"標志著云計算競爭焦點已從"算力"和"模型參數"轉向?Agent標準協議控制權?。在AI快速演進的今天&#xff0c;我們不再僅關注單個AI的智能水平&#xff0c;而是探索多個…