MQ 端到端 exactly-once 为什么无法只由 Broker 语义单独保证,业务处理链路还需要哪些约束?
旗舰版来源:jd高级工程师未确认消息与消费位点控制Redis分布式锁分布式事务两阶段提交消息消费幂等去重
草稿
答案解析
我会先区分“消息只投递一次”和“业务效果只发生一次”。Broker 的 exactly once 通常只覆盖它自己的生产、存储和消费语义,无法自动把消费者的数据库写入、调用外部服务等操作纳入同一个原子事务。
典型问题是:消费者先提交业务数据、后确认消息,如果确认失败,消息会重投,业务可能重复执行;反过来先确认消息、后提交业务数据,进程崩溃时就可能丢业务处理。因此,端到端要保证的是业务效果的幂等或原子性,通常需要这些约束:
生产端 :消息有稳定的业务标识;业务数据变更与消息发布要可靠衔接,常用本地事务消息或 Outbox,避免数据提交了但消息没发出去,或消息发出但业务事务回滚。 消费端 :以消息 ID 或业务唯一键做去重,例如使用 Inbox 表和唯一约束;去重记录与业务数据更新放在同一个数据库事务里。处理成功后再确认消息,失败则允许重试。 跨系统副作用 :调用支付、邮件等外部服务时也要传幂等键,或使用具备幂等能力的接口;无法做原子提交时,通常需要状态机、补偿或 Saga,而不是依赖 Broker 的 exactly once。 重试与顺序 :
登录后查看完整内容
