标准答案
- 业务表提交成功而消息发送失败时,数据已经改变但下游永远不知道;先发消息再提交则可能发送一个最终回滚的事实。
- Transactional Outbox 在同一事务中写业务表和 outbox 表,后台发布器扫描未发送事件并投递到消息系统。
- 发布器要记录尝试、状态和重试,消息可能重复发送,消费者仍需幂等;成功标记与消息确认之间也要允许恢复。
- 还要处理过期事件、顺序、死信、监控和清理,Outbox 解决的是事务内记录问题,不是全链路恰好一次。
题目解析
先写业务表再直接发消息存在进程崩溃窗口,先发消息再提交又可能发布最终回滚的事实。Outbox 把业务变更和待发事件放进同一数据库事务,先保证“要发什么”可恢复。
发布器读取未发送事件并投递,投递确认和状态更新之间仍可能崩溃,所以消息可以重复发送。消费者必须幂等,发布器也要有租约、重试、死信和监控。
Outbox 表是生产链路的一部分,要控制索引、批量、保留和归档,并监控最老未发送事件。它解决事务内记录,不承诺跨数据库、HTTP 和消息系统的全链路恰好一次。
常见误区
- 误区:发送成功后更新 outbox 就是原子操作。改正:承认确认与状态更新之间仍有重复窗口,并让消费者幂等。
- 误区:认为 Outbox 能消除重复消息。改正:Outbox 提供可恢复事件,重复投递仍需消费端处理。
- 误区:没有清理和监控导致 outbox 无限增长。改正:按发送状态、保留期和归档策略治理,并监控最老事件。