跳到主要内容

事件溯源

事件溯源如何从历史得到当前状态?​

  • 事件溯源: 把领域发生过的事件按顺序追加保存,以事件记录作为事实来源,而不只保存最后一份状态;
  • 重建: 从初始状态依次应用事件,得到当前状态或指定历史时点的状态;
  • 示例: 余额由“存入 100、支出 30”等已发生事件推导为 70,当前余额是投影结果;
  • 追加约束: 修改历史会改变重放结果,纠错通常记录新的更正或补偿事件;
初始余额 0
→ 已存入 100
→ 已支出 30
→ 当前余额 70

事件存储为什么不同于普通日志?​

  • 事实地位: 事件存储是恢复业务状态的权威数据,丢失事件就可能无法重建正确状态;
  • 业务语义: 事件应描述稳定的领域事实,而不是只记录某行代码执行过;
  • 顺序范围: 同一实体的状态变化需要有明确顺序或并发控制,不要求所有实体共享一个全局序号;
  • 持久性: 必须明确提交与恢复保证,不能把临时消息缓存直接当作可靠事件存储;

事件溯源有哪些收益?​

  • 审计: 保留状态变化的来龙去脉,帮助追踪为什么得到当前结果;
  • 重放: 可以修复派生视图或构建新的查询模型,不必只依赖当前快照;
  • 历史分析: 能基于事件时间序列生成报告或重建历史状态;
  • 补偿依据: 过去发生的事实能帮助决定后续更正动作,但无法保证所有现实动作都可逆;

事件模式演进为何需要特别谨慎?​

  • 版本兼容: 旧事件会长期存在,新代码需要继续理解旧载荷,模式注册与转换规则可辅助治理;
  • 重放成本: 事件量增长后全量重放可能很慢,可以增加快照,但快照仍应可从事实数据校验;
  • 副作用隔离: 重放派生状态时不能再次发送真实通知或扣款,需要区分恢复计算与外部动作;
  • 运维成本: 可靠存储、格式演进和多种事件处理增加复杂度,不是所有 CRUD 系统都值得采用;

事件溯源和事件驱动架构是什么关系?​

  • 区别: 事件驱动解决系统如何通信,事件溯源解决系统如何保存并恢复状态;
  • 组合: 事件溯源可以发布事件供其他服务使用,也可以仅在单个系统内部使用;
  • 反例: 一个服务更新普通关系表后发通知事件,属于事件驱动,但不因此成为事件溯源;