深度解析:Redis 预扣减与 RabbitMQ 异步解耦,如何完美平衡延迟与一致性?
深度解析Redis 预扣减与 RabbitMQ 异步解耦如何完美平衡延迟与一致性核心导读在高并发架构中“延迟Latency”和“一致性Consistency”天生就是一对死敌。要想快低延迟就不能等数据库慢慢落盘要想准强一致性就必须加锁排队系统必然会慢。Redis 预扣减 RabbitMQ 异步解耦的核心思想本质上是放弃了传统的“强一致性ACID”转而全面拥抱分布式系统中的“BASE 理论”。通过引入“软状态排队中”最终实现数据的“最终一致性Eventual Consistency”。下面为你深度拆解这套架构是如何在两者之间走钢丝做到既快又稳的⚡️ 一、 极致降低延迟把耗时操作全部“踢”出主线程为了做到极低的延迟Controller 在处理用户的 HTTP 请求时绝对不碰任何耗时的 I/O如 MySQL 事务、外部 RPC 调用。主线程只做三件超快的事查本地内存耗时 0.1ms。️Redis Lua 脚本扣库存单机 Redis QPS 可达 10万网络 执行耗时约 1~2ms。把消息丢进 RabbitMQ仅仅是网络投递耗时约 2~5ms。极致结果一个秒杀请求从发起到返回“抢购成功正在排队”后端总耗时在 10 毫秒级别。用户体验极其丝滑系统吞吐量拉满。⚠️遗留问题这也挖了一个坑——Redis 里库存扣了但 MySQL 里的库存还没扣订单也没生成。此时数据是不一致的。 二、 用“软状态”掩盖延迟产品与技术的完美配合在数据到达最终一致之前系统处于一个“中间状态”软状态。如果这个时候直接告诉用户“购买成功”但最后 MySQL 扣款却失败了用户一定会发飙。如何平衡答案是靠前端的交互设计话术转换Controller 返回的不是“订单已生成”而是“已抢到名额正在排队处理”。视觉缓冲前端展示一个友好的动画比如一只奔跑的猫或者加载进度条。后台轮询前端在后台以 1次/秒 的频率通过另一个接口去轮询或建立 WebSocket查询真实的订单状态。⏳偷来的时间这短短的2~5 秒钟动画时间就是技术团队从用户那里“偷来”的缓冲期。在这段时间里后端的 RabbitMQ 和消费者MySQL正在疯狂补平数据。️ 三、 兜底最终一致性RabbitMQ 的“死磕”机制既然把压力交给了异步的 RabbitMQ 和消费者就必须保证这条消息绝对不能丢且不能被重复执行。这是平衡一致性的核心技术 1. 怎么防“丢”可靠性投递与消费如果在偷来的 5 秒钟里消息丢了或者服务器宕机了用户的名额就彻底成了黑洞。✅ 生产者确认Publisher ConfirmsController 发消息给 MQ 后必须收到 MQ 的 ACK才给用户返回“排队中”。如果没收到就重试或回滚 Redis 库存。 MQ 持久化开启交换机、队列和消息的持久化就算 MQ 宕机重启消息依然安全躺在磁盘上。 消费者手动确认Manual ACK消费者订单服务从队列拿到消息后先写 MySQL。只有 MySQL 的本地事务成功提交了才向 MQ 发送 ACK。如果处理期间 Tomcat 挂了MQ 会把消息重新放回队列交给下一台机器处理。 2. 怎么防“重”消费端幂等性MQ 有个特点为了保证绝对不丢在网络抖动时可能会重复投递同一条消息。 全局唯一 ID每个丢进 MQ 的消息必须带上一个唯一的 RequestID 或流水号。️ 数据库兜底在 MySQL 订单表中将 RequestID 或 (UserID GoodsID) 设为唯一索引Unique Key。即使 MQ 重复发了两次同一条消息MySQL 在执行第二次 Insert 时也会抛出 DuplicateKeyException唯一键冲突。代码捕获此异常并直接向 MQ 返回 ACK 即可绝对不会超卖或生成双份订单。 四、 最后的闭环超时未支付与对账逆向回滚业务的一致性不仅在于正向的“创建”更在于逆向的“回滚”。典型场景用户抢到了Redis 扣了MQ 发了MySQL 订单也生成了但他后悔了15分钟没付款。此时必须把库存加回去否则就成了“少卖”。️解决方案引入延迟队列Delay Queue设定闹钟订单生成时顺便往 RabbitMQ 的“延迟队列”发一条消息设置延迟时间为 15 分钟。到点检查15 分钟后消费者收到这条消息去 MySQL 查订单状态。执行补偿如果发现还是“待支付”则触发完整的逆向回滚逻辑❌关闭 MySQL 订单➕恢复 MySQL 库存UPDATE goods SET stock stock 1➕恢复 MySQL 库存UPDATE goods SET stock stock 1恢复 Redis 库存执行 Lua 脚本 INCR 加 1清理本地售罄标记通过 MQ 广播通知所有 Controller 节点清除 ConcurrentHashMap 里的售罄标记让后续请求可以重新进来 总结在这套高并发架构中平衡延迟与一致性的哲学非常清晰对用户前端只做最轻量级的检查内存 Redis牺牲强一致性来换取极致的低延迟响应。对系统后端利用软状态排队动画争取时间通过 RabbitMQ 的可靠机制 MySQL 唯一约束 延迟补偿死磕到底最终实现数据的绝对一致。大白话比喻 —— 去网红餐厅吃饭秒杀前台服务员Controller Redis只负责秒速发给你一张“叫号凭证”低延迟而不是让你在门口傻等厨师现炒阻塞而后厨MQ MySQL拿着排队单子按自己的最大产能有条不紊地颠勺炒菜只要这张排队单子没弄丢可靠性投递最后你一定能吃到饭最终一致性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2420284.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!