尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

RabbitMQ异步下单架构设计

RabbitMQ异步下单架构设计 RabbitMQ 就是一个独立的、基于 AMQP 协议的消息服务器Broker。它接收生产者发来的消息通过交换机Exchange根据路由规则将消息存入队列Queue再由消费者从队列中取出处理。它的核心价值是让服务之间实现异步、解耦、可靠的通信。没有 RabbitMQMySQL 任务太多一损俱损RabbitMQ 就是用“独立的硬盘存储”“异步确认机制”把 MySQL 的慢写压力和 Tomcat 的宝贵线程隔离开从而斩断了“一损俱损”的锁链。以后面试官问“你项目里的 RabbitMQ 是怎么用的”不要说“我用了 RabbitMQ 做异步。”太浅。你应该说“在下单场景中我把高并发请求和订单持久化进行了异步解耦。请求首先通过 Redis Lua 脚本完成库存预扣减然后将订单消息发送到 RabbitMQ接口快速返回消费者异步完成订单和订单明细的持久化从而利用消息队列削峰填谷避免大量请求直接冲击 MySQL。同时针对 RabbitMQ 的消息确认和消费者重复消费问题我分别设计了生产者 Confirm 机制和基于 orderNo 唯一索引的消费幂等。”但是 Tracker 有一个很明显的工程缺陷Claude Code 已经告诉你了应用重启 → Map 全没了。例如submitOrder ↓ 库存 -1 ↓ Tracker.register() ↓ RabbitMQ发送 ↓ 服务器突然挂了重启Tracker {}这时候如果消息最终真的没成功库存永久少1 订单不存在所以ConcurrentHashMap只能作为进程内临时状态不能作为可靠消息存储。这个你现在不用修。但是一定要记住内存Map ≠ 可靠消息表这以后是非常好的面试追问点。以后面试官问“你这个方案有没有数据一致性风险”你反而可以回答“有。当前方案通过 Publisher Confirm、失败补偿和消费端幂等降低了风险但由于 Redis、MySQL 和 RabbitMQ 不属于同一个分布式事务极端情况下仍然存在消息确认与库存补偿之间的竞态。生产环境可以进一步采用 Outbox/本地消息表 定时补偿或者可靠消息最终一致性方案解决。”“RabbitMQ发送失败之后你怎么保证库存不会丢”你不能简单回答“我调用一个restoreStock()把库存加回来。”而应该回答“我区分同步发送异常和异步Confirm失败。同步异常发生在本地事务尚未提交时MySQL库存由事务回滚恢复只补偿RedisConfirm NACK发生在本地事务提交之后此时才通过独立事务补偿MySQL和Redis“为什么要 RabbitMQ”你回答秒杀或者高并发下单场景中大量请求同时到达如果同步完成订单创建、订单明细、库存等数据库操作会导致数据库连接和锁竞争压力过大。因此我在 Redis Lua 原子扣库存之后将订单创建通过 RabbitMQ 异步化让前端请求快速返回同时利用 MQ 削峰填谷。“那 MQ 发送失败怎么办”回答我区分同步发送异常和异步 Confirm 失败。同步发送异常发生在本地事务尚未提交时MySQL 库存由事务回滚自动恢复同时补偿 Redis如果是 Confirm NACK 或消息 Return此时本地事务已经提交则通过独立事务同时补偿 Redis 和 MySQL。“重复消费怎么办”回答RabbitMQ 本身是至少一次投递语义所以消费者可能重复消费。我使用 orderNo 作为幂等键同时在数据库建立唯一索引并在消费前查询订单是否存在最终通过数据库唯一约束作为兜底。
返回列表