事件溯源
事件溯源如何从历史得到当前状态?
- 事件溯源: 把领域发生过的事件按顺序追加保存,以事件记录作为事实来源,而不只保存最后一份状态;
- 重建: 从初始状态依次应用事件,得到当前状态或指定历史时点的状态;
- 示例: 余额由“存入 100、支出 30”等已发生事件推导为 70,当前余额是投影结果;
- 追加约束: 修改历史会改变重放结果,纠错通常记录新的更正或补偿事件;
初始余额 0
→ 已存入 100
→ 已支出 30
→ 当前余额 70
事件存储为什么不同于普通日志?
- 事实地位: 事件存储是恢复业务状态的权威数据,丢失事件就可能无法重建正确状态;
- 业务语义: 事件应描述稳定的领域事实,而不是只记录某行代码执行过;
- 顺序范围: 同一实体的状态变化需要有明确顺序或并发控制,不要求所有实体共享一个全局序号;
- 持久性: 必须明确提交与恢复保证,不能把临时消息缓存直接当作可靠事件存储;
事件溯源有哪些收益?
- 审计: 保留状态变化的来龙去脉,帮助追踪为什么得到当前结果;
- 重放: 可以修复派生视图或构建新的查询模型,不必只依赖当前快照;
- 历史分析: 能基于事件时间序列生成报告或重建历史状态;
- 补偿依据: 过去发生的事实能帮助决定后续更正动作,但无法保证所有现实动作都可逆;
事件模式演进为何需要特别谨慎?
- 版本兼容: 旧事件会长期存在,新代码需要继续理解旧载荷,模式注册与转换规则可辅助治理;
- 重放成本: 事件量增长后全量重放可能很慢,可以增加快照,但快照仍应可从事实数据校验;
- 副作用隔离: 重放派生状态时不能再次发送真实通知或扣款,需要区分恢复计算与外部动作;
- 运维成本: 可靠存储、格式演进和多种事件处理增加复杂度,不是所有 CRUD 系统都值得采用;
事件溯源和事件驱动架构是什么关系?
- 区别: 事件驱动解决系统如何通信,事件溯源解决系统如何保存并恢复状态;
- 组合: 事件溯源可以发布事件供其他服务使用,也可以仅在单个系统内部使用;
- 反例: 一个服务更新普通关系表后发通知事件,属于事件驱动,但不因此成为事件溯源;