一次线上事故,我学到了事件驱动架构的5个教训
凌晨3点17分监控大屏突然一片血红。用户订单成功了但库存没扣、支付没扣、物流没发...上百万的交易数据人间蒸发。排查结果让所有人傻眼只是一个无关紧要的代码改动让整个事件驱动系统安静地死亡了——没有报错没有日志就像什么都没发生过。1 那个让我们全员进制服的夜晚2025 年 12 月 12 日双 12 大促。凌晨 2:47我正在值班室刷手机突然手机疯狂震动 监控告警订单事件处理量 0 监控告警库存事件处理量 0 监控告警支付回调处理量 0 监控告警物流通知处理量 0我瞬间清醒裤子都没穿好就冲进了机房。发生了什么用户下单成功了订单服务正常返回了。但后续所有流程 - 库存扣减、支付处理、物流通知、短信推送 - 全都消失了。后来排查发现只是因为某个同事修改了一行看似无关紧要的日志打印代码。导致事件总线初始化失败。最恐怖的是系统没有任何报错它只是安静的不工作了。这就是事件驱动EDA最可怕的地方传统架构某个服务挂了你会收到报错事件驱动架构事件总线挂了所有人都相安无事2 消息重复消费 - 用户收到 5 条扣款短信2.1 发生了什么大促高峰期某用户手机突然收到了 5 条“库存已扣减”的短信。投诉电话被打爆。2.2 根因分析消息队列的“至少投递一次”语义 消费者没有“去重保护” 用户收到5条消息2.3 怎么解决核心原则消费者必须幂等方案一数据库唯一键重复插入 报错方案二Redis 缓存已存在 跳过方案三业务状态机已经是 RESERVED 跳过3 时间丢失 - 127笔订单“成功”但没付款3.1 发生了什么财务对账时发现当天 127 笔订单显示“成功”但数据库里没有任何支付记录。顺着链路查下去订单服务确实发布了事件但支付服务所在的服务器正好在发版重启消息还没来得及处理就丢了...3.2 根因分析发布时没持久化消费失败直接丢弃网络抖动丢消息3.3 怎么解决核心原则宁可慢也不能丢发布时先持久化再发送消费失败重试 死信死信队列人工兜底时间乱序 - 后下的单先发货4.1 发生了什么用户投诉命名先下的单 A后下的单 B为什么 B 先发货了排查发现订单 A 和订单 B 的时间恰好被分发到不同的消费者分区加上高峰期处理延迟不同事件处理顺序完全乱套。4.2 根因分析事件乱序大有可能因为消息队列分区策略轮询将订单 A 分发到了处理速度慢的消费者所监听的分区订单 B 分发到了处理速度快的消费者所监听的分区。导致了订单 B 比订单 A 先处理完。4.3 怎么解决核心原则同一个订单的时间必须交给同一个消费者处理方案分区键可以通过订单 ID 作为分区键同一个订单的所有事件一定进入同一个分区备选方案消费者端排序通过事件序列号消费者收到后按照 seq 排序再处理5 事件循环 - CPU 100%罪魁祸首5.1 发生了什么监控显示某个服务器 CPU 100%内存持续飙升。日志显示同一个事件被反复处理每秒数万次。最终定位订单服务发布“订单已创建”事件触发通知服务发送短信通知服务发完短信后发布“通知已发送”事件订单服务订阅了这个事件一激动又发布了“订单已创建”事件...无限循环开始5.2 根因分析订单服务发布了 order 事件会触发服务通知服务通知发布了 notify 事件同时订单服务订阅了 notify 事件循环启动每秒数万次直到服务器挂掉5.3 怎么解决核心原则要么预防要么检测方案一状态机控制订单的状态不可逆CREATED ──▶ STOCK_RESERVED ──▶ PAID ──▶ SHIPPED ──▶ COMPLETED只有 CREATED 状态才能处理 order.created 事件如果已经是 STOCK_RESERVED收到 order.created 直接忽略方案二循环检测最简单的计数器机制就可以做到计数器机制如下方案三过滤末端事件定义一些事件不要二次触发其他事件6 根本不知道卡在哪 30 分钟的订单6.1 发生了什么一个订单处理了30分钟还没完成。中间经过订单服务 → 库存服务 → 支付服务 → 物流服务 → 通知服务...每个服务都说处理成功了但整体就是慢。根本不知道卡在哪一步。传统请求请求A ──▶ 服务1 ──▶ 服务2 ──▶ 服务3 ──▶ 响应请求到哪了一目了然事件驱动事件A ──▶ 队列 ──▶ [?][?][?] ──▶ [?][?]事件去哪了谁都不知道找不到问题才是最可怕的问题6.3 怎么解决核心原则全链路追踪TraceID 贯穿始终任何一步出问题都可以用 trace:nb123 搜到所有相关日志7 避坑 checklistEDA 保命 checklist消费者实现幂等性了吗 - 用唯一键 / Redis / 状态机防止重复处理消息持久化了吗- 先写数据库再发消息队列失败重试 死信队列有了吗 - 超过3次进 DLQ人工处理同一订单的事件进同一分区了吗 - 用业务 ID 做分区键状态机防止事件循环了吗 - 状态不可逆跳过非法转换全链路追踪配了吗 - traceId 贯穿所有服务8 最后的忠告事件驱动架构是双刃剑好处坏处系统松耦合问题难排查性能高容易丢消息扩展性强容易损坏容错性好容易重复我的建议从小功能开始试 ---别一上来就该核心流程监控告警先做好 ---上线前先把追踪搭建好逐步前进--- 一个服务一个服务的迁移宁可慢也不要丢凌晨3点的那些教训现在都变成这篇文章了。觉得有用点个赞再走
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2423470.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!