本文用于排查和补偿 SAAS 向 DGJ 同步维修厂订单、订单更新和出库单时的消息丢失、顺序错乱、锁冲突与重试耗尽问题。公开文档只保留流程和判断规则,不记录内网地址、令牌、客户订单号或完整业务报文。

1. 核心入口

  • 消费者:app/Amqp/Consumer/Dgj/DgjConsumer.php
  • 延迟队列声明:app/Listener/MainWorkerStartListener.php
  • 订单同步:app/Service/Order/Sync/GarageRepairOrderSyncService.php
  • 出库同步:app/Service/Order/Sync/GarageRepairOutboundSyncService.php
  • 主要事件:garage_repair_order_created、garage_repair_order_updated、garage_repair_outbound_created

2. 排查顺序

  1. 使用订单 ID、订单号、出库单号和 sid 查询消息接收、事务开始、事务完成、锁冲突和重试耗尽日志。
  2. 查询 SAAS 分表订单、订单明细和 t_order_out_flow,确认业务事实是否已经落库。
  3. 订单不存在时先补订单创建;订单存在但出库流水不存在时再补出库创建。
  4. 如果存在待补偿缓存,先确认订单创建是否会自动排空缓存,避免重复手工补发。
  5. 补偿后同时验证日志、订单状态、明细出库数量和出库流水。

3. 重试规则

  • 生产者的延迟后缀必须与消费者启动时声明的 TTL 队列一致。
  • 死信路由必须回到正常消费 routing key。
  • 锁异常不能无边界 REQUEUE,否则会形成同一消息的热循环消费。
  • eventId 会在延迟重试时变化,统计风暴时还要按业务键去重。
  • 对比健康时段和异常起点,结合连接中断、消费者重启、锁失败和 retry_times 判断根因。

4. 补偿安全条件

  • 默认先只读检查,不直接重发。
  • t_order_out_flow.out_bill_no 已存在时禁止重复补发出库事件。
  • 订单创建和出库创建必须按依赖顺序执行。
  • 补偿接口地址、会话令牌和完整 payload 从受控环境临时取得,不写入网站、技能、提交或聊天记录。

5. 验收清单

  • 订单同步事务完成且没有持续锁冲突。
  • 订单主表状态和出库单号正确。
  • 明细出库数量与来源单一致。
  • t_order_out_flow 只有一条目标出库事实。
  • 延迟队列没有继续产生同一业务键的无界重试。
  • 失败告警和待补偿缓存已恢复或有明确后续负责人。

6. 改动风险

  • 修改 QoS、锁 TTL、延迟 TTL 或重试次数时必须一起检查生产者、队列声明和消费者处理。
  • 修改订单/出库幂等条件时要回归乱序、重复、订单未就绪、明细未就绪和消费者重启场景。
  • 任何补偿都需要保存脱敏后的执行时间、事件类型、判断依据和验收结果。