数据一致性与消息¶
服务拥有独立数据后,跨服务业务不能依赖一个本地数据库事务完成。目标应从“所有数据瞬间一致”转为“关键约束明确、状态可追踪、失败可补偿、最终达到正确结果”。
基本模式¶
| 模式 | 作用 | 风险 |
|---|---|---|
| Saga | 多个本地事务组成流程,失败时补偿 | 补偿并不总能完全撤销现实动作 |
| Transactional Outbox | 业务数据与待发事件写入同一事务 | 需要可靠投递和清理 Outbox |
| 幂等消费 | 同一消息重复到达只产生一次业务效果 | 需业务唯一键和状态记录 |
| CQRS/读模型 | 写模型与查询模型分离 | 同步延迟和更多数据管道 |
Outbox 流程¶
订单本地事务:写 orders + 写 outbox_event
→ 发布器读取未发送事件
→ Kafka/RabbitMQ
→ 库存服务消费
→ 以 event_id 去重并更新本地状态
→ 成功确认;失败重试/进入死信处理
消息中间件通常提供“至少一次”交付,因此消费者必须假设重复。不要把“Broker 已确认”理解为“下游业务已经成功完成”。
事件设计¶
- 事件表达已发生事实,如
OrderCreated,而不是模糊的“更新订单”。 - 包含
event_id、业务键、时间、来源服务、Schema 版本和 Trace 上下文。 - 新增字段尽量向后兼容;消费者忽略未知字段。
- 大对象可传引用,但要处理引用数据生命周期和权限。
- 敏感信息只放业务真正需要的最小集合。
运维关注¶
积压排障先区分消费者停机、处理变慢、下游依赖慢、分区不均和毒消息。扩容消费者前确认分区/队列并发上限以及下游容量。
对账和修复能力是最终一致性系统的一部分:定期比较关键状态,生成差异,支持安全重放或人工补偿,并完整审计。