跳转至

数据一致性与消息

服务拥有独立数据后,跨服务业务不能依赖一个本地数据库事务完成。目标应从“所有数据瞬间一致”转为“关键约束明确、状态可追踪、失败可补偿、最终达到正确结果”。

基本模式

模式 作用 风险
Saga 多个本地事务组成流程,失败时补偿 补偿并不总能完全撤销现实动作
Transactional Outbox 业务数据与待发事件写入同一事务 需要可靠投递和清理 Outbox
幂等消费 同一消息重复到达只产生一次业务效果 需业务唯一键和状态记录
CQRS/读模型 写模型与查询模型分离 同步延迟和更多数据管道

Outbox 流程

订单本地事务:写 orders + 写 outbox_event
  → 发布器读取未发送事件
  → Kafka/RabbitMQ
  → 库存服务消费
  → 以 event_id 去重并更新本地状态
  → 成功确认;失败重试/进入死信处理

消息中间件通常提供“至少一次”交付,因此消费者必须假设重复。不要把“Broker 已确认”理解为“下游业务已经成功完成”。

事件设计

  • 事件表达已发生事实,如 OrderCreated,而不是模糊的“更新订单”。
  • 包含 event_id、业务键、时间、来源服务、Schema 版本和 Trace 上下文。
  • 新增字段尽量向后兼容;消费者忽略未知字段。
  • 大对象可传引用,但要处理引用数据生命周期和权限。
  • 敏感信息只放业务真正需要的最小集合。

运维关注

生产速率 / 消费速率 / Lag
重复与失败次数
死信队列数量和最老消息年龄
事件从产生到业务完成的端到端延迟
补偿任务和人工处置积压

积压排障先区分消费者停机、处理变慢、下游依赖慢、分区不均和毒消息。扩容消费者前确认分区/队列并发上限以及下游容量。

对账和修复能力是最终一致性系统的一部分:定期比较关键状态,生成差异,支持安全重放或人工补偿,并完整审计。