從0到1構建高并發秒殺系統:實戰 RocketMQ 異步削峰與Redis預減庫存

🚀從0到1構建高并發秒殺系統:實戰 RocketMQ 異步削峰與Redis預減庫存


📖一、 簡介

在電商、搶票等高并發場景中,秒殺系統面臨著“高并發、庫存稀缺、易超賣、系統易崩”的嚴峻挑戰。傳統的同步處理架構難以支撐海量請求并發下的性能與一致性要求。

本文從實戰出發,系統性地講解如何基于 Redis + RocketMQ + MySQL + Spring Boot 構建一個高性能、高可用、強一致性的秒殺系統。通過 接口限流、Redis 原子扣減庫存、RocketMQ 異步削峰、數據庫冪等落庫 等機制,徹底解決了高并發下的核心問題,如超賣、重復下單、系統崩潰等。

你將看到:

  • 🧠 秒殺系統面臨的本質問題與設計原則
  • 🧱 架構層次的分層與職責劃分
  • ?? Redis + Lua 腳本實現庫存預扣與并發控制
  • 🚀 RocketMQ 異步下單實現削峰填谷與解耦
  • 💡 MySQL 樂觀鎖 + 冪等設計實現最終一致性
  • 🛠? 全程配套詳細注釋代碼、架構圖與數據庫設計

本文不僅提供了完整可運行的思路,還具備工程級可落地性。適合架構師、后端工程師在面對實際高并發場景時作為參考與實踐藍圖。


🧠 二、秒殺系統的挑戰與本質

“秒殺”業務場景常出現在電商、搶票、預約系統中,具有以下挑戰:

維度問題說明
并發性高并發訪問瞬時請求高達數十萬甚至上百萬
數據一致性超賣/重復下單庫存是關鍵共享資源
系統穩定性容易雪崩單點性能瓶頸可能導致系統掛掉
響應速度秒級反饋用戶希望秒殺是否成功即時反饋

核心:限流 + 削峰 + 異步 + 緩存


🔧 三、系統總體架構設計

在這里插入圖片描述


🔨 四、核心技術選型與職責

技術組件作用
Redis緩存庫存、原子扣減、用戶狀態標記
RocketMQ削峰填谷、異步解耦
MySQL最終訂單存儲、庫存持久化
Spring Boot微服務框架
Guava RateLimiter接口級限流

📦 五、秒殺系統核心模塊詳細設計


1?? 接口限流 + 秒殺入口

@RestController
@RequestMapping("/seckill")
public class SeckillController {// 每秒只允許100個請求通過private final RateLimiter rateLimiter = RateLimiter.create(100);@Autowiredprivate SeckillService seckillService;@PostMapping("/{itemId}")public ResponseEntity<String> seckill(@PathVariable Long itemId) {// 通過令牌桶控制請求速率if (!rateLimiter.tryAcquire()) {return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("請求過多,請稍后重試");}// 模擬用戶獲取(實際從登錄信息中取)Long userId = 1001L;boolean success = seckillService.processSeckill(itemId, userId);if (success) {return ResponseEntity.ok("請求成功,正在排隊中...");} else {return ResponseEntity.badRequest().body("庫存不足或已搶完");}}
}

2?? Redis 原子扣減庫存(Lua 腳本)+ RocketMQ 消息發送

@Service
public class SeckillServiceImpl implements SeckillService {private static final String STOCK_KEY_PREFIX = "seckill:stock:";@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate RocketMQTemplate rocketMQTemplate;@Overridepublic boolean processSeckill(Long itemId, Long userId) {String stockKey = STOCK_KEY_PREFIX + itemId;// Lua 腳本:原子檢查庫存并扣減String luaScript = "if (tonumber(redis.call('get', KEYS[1])) > 0) then " +" return redis.call('decr', KEYS[1]) " +"else return -1 end";// 執行腳本,防止并發引起庫存超賣DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();redisScript.setScriptText(luaScript);redisScript.setResultType(Long.class);Long result = redisTemplate.execute(redisScript, Collections.singletonList(stockKey));if (result == null || result < 0) {// 庫存不足return false;}// 構建訂單消息并發送到 MQSeckillOrderMessage message = new SeckillOrderMessage(userId, itemId);rocketMQTemplate.convertAndSend("seckill-topic", message);return true;}
}

3?? RocketMQ 消費者:監聽秒殺訂單消息,落庫處理

@Component
@RocketMQMessageListener(topic = "seckill-topic", consumerGroup = "seckill-consumer-group")
public class SeckillConsumer implements RocketMQListener<SeckillOrderMessage> {@Autowiredprivate SeckillOrderService orderService;@Overridepublic void onMessage(SeckillOrderMessage msg) {try {// 調用下單服務進行庫存校驗和訂單落庫orderService.createOrder(msg.getUserId(), msg.getItemId());} catch (Exception e) {// 消息重試或記錄異常用于補償System.err.println("消費失敗: " + e.getMessage());}}
}

4?? 下單服務:冪等校驗 + 數據庫存儲 + 樂觀鎖扣減

@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {@Autowiredprivate SeckillOrderRepository orderRepository;@Autowiredprivate StockRepository stockRepository;@Transactionalpublic void createOrder(Long userId, Long itemId) {// 冪等校驗:防止重復下單(可用唯一索引或Redis SET)if (orderRepository.existsByUserIdAndItemId(userId, itemId)) {return;}// 扣減數據庫庫存,使用樂觀鎖 versionint updated = stockRepository.decreaseStock(itemId);if (updated == 0) {throw new RuntimeException("庫存不足,數據庫扣減失敗");}// 寫入訂單記錄SeckillOrder order = new SeckillOrder(userId, itemId, LocalDateTime.now());orderRepository.save(order);}
}

5?? 數據庫表結構設計(庫存 + 訂單)

📌 商品庫存表(帶 version 樂觀鎖)
CREATE TABLE stock (id BIGINT PRIMARY KEY AUTO_INCREMENT,item_id BIGINT NOT NULL UNIQUE,stock INT NOT NULL,version INT NOT NULL DEFAULT 0
);
📌 庫存扣減 SQL(樂觀鎖)
UPDATE stock
SET stock = stock - 1, version = version + 1
WHERE item_id = ? AND version = ? AND stock > 0;
📌 訂單表
CREATE TABLE seckill_order (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL,item_id BIGINT NOT NULL,create_time DATETIME NOT NULL,UNIQUE KEY uniq_user_item (user_id, item_id)
);

📊 六、性能優化與高可用建議

方向建議
限流接口層限流(Guava)、網關限流(Sentinel)
削峰使用 RocketMQ 異步下單,防止數據庫擊穿
冪等Redis SETNX、唯一索引、分布式鎖
日志與監控Prometheus + Grafana、日志追蹤鏈路
高可用RocketMQ 主從部署、Broker 宕機自動切換

? 七、總結

通過將 Redis 與 RocketMQ 結合,構建出一個具備如下特性的高并發秒殺系統:

  • 并發控制得當:接口限流 + Redis 原子性操作
  • 系統抗壓能力強:消息削峰,MQ異步下單
  • 數據一致性高:數據庫落庫有冪等保障
  • 用戶體驗更好:請求秒級響應,后臺異步處理

📘 八、后續可拓展點

  • 秒殺結果異步通知(短信 / WebSocket)
  • Redis 秒殺狀態標識(用戶是否成功)
  • RocketMQ 事務消息提升可靠性
  • 異常消息記錄 + 自動補償機制

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

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

相關文章

OpenCV CUDA模塊圖像變形------對圖像進行任意形式的重映射(Remapping)操作函數remap()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數根據給定的映射表 xmap 和 ymap 對圖像進行 任意形式的重映射&#xff08;Remapping&#xff09;操作&#xff0c;是 GPU 加速版本的圖像幾…

PC 端常用 UI 組件庫

一、前言 隨著企業級應用、后臺管理系統、數據平臺等項目的不斷發展&#xff0c;前端開發已經不再局限于移動端和響應式布局&#xff0c;而是越來越多地聚焦于 PC 端系統的構建。為了提升開發效率、統一設計風格并保障用戶體驗&#xff0c;使用成熟的 UI 組件庫 成為了現代前端…

pikachu靶場通關筆記31 文件包含02之遠程文件包含

目錄 一、文件包含功能 二、文件包含Vulnerability 二、遠程文件包含 三、環境配置 1、進入靶場 2、搭建環境 &#xff08;1&#xff09;定位php.ini文件 &#xff08;2&#xff09;修改php.ini文件 四、源碼分析 五、滲透實戰 1、選擇科比 2、執行phpinfo &…

QT集成Boost庫

在Windows平臺上&#xff0c;使用Qt集成Boost庫&#xff0c;并基于MSVC編譯器在CMake文件中加載&#xff0c;可以按照以下步驟進行配置。 Boost庫的編譯 如果Boost庫未預編譯&#xff0c;需要手動編譯&#xff0c;解壓zip到D:\Library\boost_1_87_0&#xff0c;打開cmd命令行…

MySQL從庫復制延遲的監測

目錄 ?? 一、原生內置方法?? 二、心跳表工具&#xff08;如pt-heartbeat&#xff09;?? 三、MySQL 8.0 增強方案&#x1f4ca; 四、各方案對比總結&#x1f48e; 五、選擇建議 MySQL從庫復制延遲的監測是保障數據一致性和讀寫分離可靠性的關鍵環節&#xff0c;以下是主流…

slam--最小二乘問題--凹凸函數

最小二乘問題 最小二乘問題標準公式 殘差函數&#xff0c;線性和非線性最小二乘 最小二乘問題的兩種寫法&#xff1a; 目標 找到 x使得預測值 Ax與觀測值 b 的殘差平方和最小。 范數和范數平方 線性最小二乘 一般形式&#xff1a; 殘差 rAx?b是x 的線性函數。 目標函數是…

crackme008

crackme008 名稱值軟件名稱Andrnalin.1.exe加殼方式無保護方式serial編譯語言Microsoft Visual Basic調試環境win10 64位使用工具x32dbg,PEid破解日期2025-06-10 脫殼 1. 先用PEid查殼 查到無殼 尋找Serial 尋找flag&#xff0c;用x32dbg打開程序&#xff0c;鼠標右鍵->…

【C語言】圖書管理系統(文件存儲版)丨源碼+詳解

一、系統介紹 這是一個基于C語言開發的終端圖書管理系統&#xff0c;采用鏈表數據結構??二進制文件存儲技術實現。系統具有以下特點&#xff1a; ?雙角色系統?&#xff1a;管理員&#xff08;管理圖書&#xff09;和讀者&#xff08;借閱/歸還&#xff09;?完整功能?&a…

Java求職者面試題解析:Spring、Spring Boot、MyBatis框架與源碼原理

Java求職者面試題解析&#xff1a;Spring、Spring Boot、MyBatis框架與源碼原理 第一輪&#xff1a;基礎概念問題 1. 請解釋什么是Spring框架&#xff1f;它的核心特性有哪些&#xff1f; Spring是一個開源的Java/Java EE應用程序框架&#xff0c;用于簡化企業級應用開發。其…

【Chipyard】修改Gemmini 中PE的數量

實戰目標 PE數量擴大到原來4倍 原來配置 tileRows: Int 1,tileColumns: Int 1,meshRows: Int 16,meshColumns: Int 16, 改后配置 tileRows: Int 1,tileColumns: Int 1,meshRows: Int 32,meshColumns: Int 32, 修改配置 1. 修改gemmini的scala配置文件&#xff0c;用…

TCP客戶端進程分割輸入輸出

創建TCP客戶端&#xff0c;創建子進程分割TCP客戶端的read功能和write功能&#xff0c;實現分割I/O的目的。加快客戶端速率。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include …

Wi-Fi 6 在 2.4GHz 頻段的速率與優化分析

Wi-Fi 6&#xff08;802.11ax&#xff09;在 2.4GHz 和 5GHz 頻段均可工作&#xff0c;理論最高速率可達 1200 Mbps&#xff08;5GHz&#xff0c;80MHz&#xff0c;22 MIMO&#xff09;。但在 2.4GHz 頻段&#xff0c;速率受 信道寬度、MIMO、調制方式、干擾、協議開銷 影響&am…

WPF--Application.Current.Dispatcher.BeginInvoke

1.代碼示例 private void LogInfoList_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) {// 直接在這里修改集合會引發遞歸if (e.Action NotifyCollectionChangedAction.Add){if (logInfoList.Count > 200){logInfoList.RemoveAt(0); // 這里會…

ZooKeeper詳解以及應用部署(AI)

ZooKeeper 是一個開源的分布式協調服務框架&#xff0c;旨在為分布式應用提供一致性保障和關鍵協調功能。其核心設計理念是將復雜的分布式一致性邏輯封裝為簡單可靠的接口&#xff0c;讓開發者專注于業務邏輯而非底層協調難題。以下是其核心要點&#xff1a; &#x1f9e0; 一、…

將MySQL數據庫中所有表和字段編碼統一改為utf8mb4_unicode_ci

完整操作步驟 1. 首先修改數據庫默認字符集 sql ALTER DATABASE 你的數據庫名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 2. 生成批量修改所有表的SQL語句 sql SELECT CONCAT(ALTER TABLE , table_schema, ., table_name, CONVERT TO CHARACTER SET utf8mb4 C…

jupyterhub的淺淺使用-重點在解決無法登錄

jupyterhub的淺淺使用-重點在解決無法登錄 jupyterhub的淺淺使用-重點在解決無法登錄1、jupyterhub是什么2、創建Dockerfile3、啟動容器3.1、生成配置文件jupyterhub --generate-config3.2、運行容器3.3、進入容器配置用戶密碼3.4、訪問127.0.0.1:8000并登錄 4、后臺創建的用戶…

【Bitcoin基礎】比特幣的地址格式有哪些?如何應用?

比特幣地址格式的分類及應用場景 比特幣地址是用于接收和發送比特幣的標識符&#xff0c;主要有以下幾種格式&#xff0c;每中類型都有其特定的用途和特點: 比特幣地址格式 P2PKH 1xxxx leagcy地址 P2SH 3xxxx 允許更復雜的交易多重簽名 bech32 bc1xxxx bech32mP2TR…

3.1.2_棧的順序存儲實現

知識總覽&#xff1a; 順序棧的定義&#xff1a; 順序棧是用順序存儲實現的 &#xff0c;代碼定義方式和順序表類似(啥是順序表來著&#xff1f;&#xff1f;&#xff1f;) 定義一個順序棧struct結構體SqStack&#xff0c;結構體中有靜態數組data來存放棧里邊的元素1個int型的…

JavaEE初階第一期:計算機是如何 “思考” 的(上)

專欄&#xff1a;JavaEE初階起飛計劃 個人主頁&#xff1a;手握風云 一、馮諾依曼體系結構 1.1. 概念 馮諾依曼體系結構&#xff08;Von Neumann Architecture&#xff09;&#xff0c;是現代計算機的基礎設計概念&#xff0c;核心思想是“存儲程序控制”。具體來說&#xff0c…

SQL Server全局搜索:在整個數據庫中查找特定值的高效方法

SQL Server全局搜索&#xff1a;在整個數據庫中查找特定值的高效方法 一、需求背景&#xff1a;為什么需要數據庫全局搜索&#xff1f; 在數據庫管理和開發過程中&#xff0c;我們經常會遇到這樣的場景&#xff1a; 只記得某個數據值&#xff0c;但忘記了它所在的表或列需要…