mcpField
A
arch-event-sourcing

arch-event-sourcing

github.com/yonatankarp开发139 次安装23 周前更新
代码仓库

关于 arch-event-sourcing

面向评估事件溯源的开发者的架构指南,说明如何以仅追加的事件日志作为事实来源,并介绍重放、快照、版本管理和运维考量。

主要功能

  1. 01仅追加事件日志
  2. 02通过事件重放恢复状态
  3. 03使用快照加速读取
  4. 04事件模式演进
  5. 05与 CQRS 配合

适用场景

  1. 01保留审计历史
  2. 02查询过去某时点的状态
  3. 03生成多个读取模型

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatankarp/software-design-skills --skill arch-event-sourcing

安装后在 Claude Code 中输入/arch-event-sourcing确认已加载。

详细介绍

一句话总结

将状态变更事件序列持久化为唯一事实来源。当前状态通过重放事件得出。事件日志仅追加、不可变且具有权威性。

何时使用此技能

  • 需要完整变更历史的审计或监管要求。
  • 业务确实以“发生了什么”的方式思考问题(银行交易、理赔调整、供应链事件)。
  • 需要回答时间查询(“日期 X 的状态是什么”)。
  • 需要同一数据的多个投影,且从事件物化比手动维护更容易。
  • 与 CQRS 配合自然(参见 arch-cqrs),适用于读取需要不同于规范事件流的数据形态的情况。

何时不使用此技能

  • 领域并不以事件为思维方式——强行将模型改造成事件形态,成本会超过收益。
  • 当前状态已足够,且很少查询历史——CRUD 更简单。
  • 团队不熟悉最终一致性、重放语义或事件版本管理——运维难题会非常严重。
  • 因为微服务正流行,而且我们在哪里读到过“事件溯源”就想采用——这不是理由。

核心内容

事件存储。 仅追加的事件日志,每个事件都带有聚合 ID、序列号和时间戳。写入操作为 append(events);读取特定聚合的操作为 eventsFor(aggregateId)。

重建状态。 聚合的当前状态是对其事件进行折叠的结果:

state = events.fold(initial) { acc, event -> apply(acc, event) }

处理新命令时:加载事件,重放以获取当前状态,执行命令,然后追加新事件。内存中的状态是临时的;磁盘上的事件才是真相。

快照。 对于生命周期较长的聚合(包含数年事件),从头重放会变慢。快照是定期保存的事件 N 时的状态。加载时使用快照以及 N 之后的事件。快照是一种优化,不是唯一事实来源——事件仍然才是事实来源。

事件版本管理。 事件会永久保留。其架构必须向前兼容地演进。策略:

  • 仅做增量变更——新增字段应为可选字段,绝不能设为必填。
  • 升级器——在读取时将旧版本事件转换为当前形态的代码。
  • 宽松架构(使用宽容解析的 JSON)——以编译时安全性为代价换取灵活性。

与 CQRS 配合。 事件溯源写入会自然地产生用于投影到读取模型的事件。大多数生产环境中的事件溯源系统会在查询中使用 CQRS,因为直接查询事件流并不方便。

运维注意事项。

  • 事件存储的可用性至关重要——它是唯一事实来源。
  • 工具(重放、重建投影、架构迁移)必须在做出承诺之前就已具备;项目中途才构建这些工具会很痛苦。
  • 存储量会单调增长。应提前规划。
  • 不带快照且包含数百万个事件的聚合将难以处理。

决策启发

  • 对确实需要审计、时间查询或多个投影的聚合采用事件溯源。不要一概采用。
  • 快照间隔是一个调节参数——从 100-500 个事件开始,根据重放性能进行调整。
  • 将事件架构视为公共 API——为其添加版本;绝不要破坏它们。
  • 在生产环境依赖事件溯源之前,先构建运维工具集(重放、重建、迁移)。

反模式

  • 不加思考地对整个系统采用事件溯源。 大多数子域并不需要。应选择性应用——通常只用于有强烈审计需求的核心领域。
  • 可变事件。 编辑过去的事件来“修正”历史。这会破坏整个模式。要“更正”,应追加一个补偿事件。
  • 将事件当作 DTO。 事件除了表示“字段已更改”外没有任何语义含义。事件应是领域事件:使用过去时态,并具有业务意义。
  • 在热点聚合上不使用快照进行重放。 每条命令都需要数秒,甚至数十秒。
  • 架构变更时不使用升级器。 旧事件将无法读取。实际上,历史记录就此丢失。

另请参阅

  • arch-cqrs — 从事件投影读取模型。
  • arch-event-driven — 将事件作为跨上下文通信(通常使用相同的事件)。
  • ddd-domain-event — 战术层面的事件概念。
  • ddd-aggregate — 事件溯源聚合在处理命令时生成事件。

参考资料

  • Khononov,Learning DDD,第 7 章(事件溯源领域模型)。
  • Vaughn Vernon,Implementing Domain-Driven Design — 第 8 章提供了经典的 Java 讲解。
  • Greg Young,关于事件溯源的演讲和文章(奠基性资料)。

评论

支持 Markdown