核心是让秒杀请求“快进快出”,web层仅校验登录态和活动时间后毫秒级发消息至rabbitmq,其余查库存、扣库存、建订单全部异步化;库存预减走redis,消费端只做确认落地与建单,不参与决策,配合限流、幂等、死信兜底与最终一致性保障。

核心是让秒杀请求“快进快出”,把真正耗时的业务逻辑(查库存、扣库存、建订单)从主流程剥离,交给 RabbitMQ 缓冲后异步处理。不是靠 MQ 扛住所有流量,而是靠它做可控的“中转站”——消息不丢、不积压、不拖垮下游,同时结果可追溯。
生产端:毫秒级发消息,不做任何阻塞
用户点“抢购”那一刻,Web 层只做两件事:校验登录态和活动时间,然后立刻发消息到 RabbitMQ。其余所有操作全部后置。
- 用 RabbitTemplate.convertAndSend() 发送,不等响应;设置 deliveryMode = PERSISTENT,保证 Broker 重启后消息不丢
- 禁止在发送前查数据库、调远程服务或做复杂计算,否则线程卡住,反而成瓶颈
- 前端统一返回“请求已接收,请稍候查看结果”,不承诺成功,避免误导
队列端:设容量上限 + 持久化 + 死信兜底
队列不是越大越好,要匹配系统实际吞吐和运维容忍度。比如每秒最多处理 2000 单,10 万并发请求进来,队列长度设为 10 万,超了就拒绝,比堆满内存 OOM 更可控。
- 声明队列时指定 x-max-length=100000 和 x-overflow=reject-publish,新消息直接被拒
- 开启 durable=true,配合生产者 confirm 模式,确保消息落盘且投递成功才返回
- 配置死信交换机(DLX),消费失败重试 3 次后转入死信队列,供人工或定时任务核查异常单
消费端:限速消费 + 幂等校验 + 状态闭环
消费者数量不是越多越好,要跟 MySQL 和 Redis 的写入能力匹配。比如 MySQL 单实例极限约 2000 TPS,开 4~6 个消费者线程更稳,每个线程每秒拉取 300~500 条即可。
- 用 @RabbitListener(concurrency="4-6") 控制并发数,搭配 prefetch=10 防止预取过多压垮消费者
- 每条消息处理前,先查 Redis 缓存(key 用订单号或用户+商品组合),判断是否已处理,避免重复下单
- 处理完成后更新订单状态,并发一条“结果通知”消息到另一个 exchange,由推送服务异步触达用户
配套保障:MQ 不是万能解药,必须前后协同
RabbitMQ 是缓冲中枢,但不能单独扛压。它前面要有拦截,后面要有校验,才能形成完整闭环。
- 接入层用 Nginx limit_req 或 Spring Cloud Gateway 做第一道限流,过滤明显刷量
- 库存扣减走 Redis 预减(decrby),RabbitMQ 消费时只做“确认落地”和“建单”,不参与库存决策
- 定时任务定期比对 Redis 库存与 MySQL 订单,发现不一致自动修复,保障最终一致性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











