事件溯源中“当前状态”存储位置及业务规则校验疑问
事件溯源中聚合状态与命令校验的常见疑问解答
核心认知澄清:事件溯源并非绝对禁止存储聚合当前状态
业内所说的“不存储聚合的当前状态”,本质是指聚合的唯一权威数据源是事件序列,而非完全禁止使用派生的状态缓存(比如快照)。快照只是性能优化手段,不会取代事件序列的核心地位——即使快照丢失,依然可以通过重新回放所有事件完全恢复聚合状态,这才是事件溯源的核心原则。
处理命令时的聚合状态获取方式
针对你提到的“帖子最多更新两次”这类业务规则,标准的处理流程就是:
- 从事件仓库拉取该帖子的所有事件(或先加载最新快照+快照后的增量事件)
- 回放事件重建出聚合的当前状态
- 在聚合内部执行命令校验(检查更新次数是否已达上限)
- 校验通过则生成新事件并写入事件仓库;校验失败则直接返回错误,不生成任何事件
这种流程完全符合事件溯源的原则,因为聚合状态始终是从权威事件序列派生出来的,不存在独立于事件的“真实状态”。
为什么不能用投影做业务规则校验?
投影是基于事件异步生成的查询视图,属于最终一致的派生数据。如果用投影来校验领域规则(比如查询投影中的更新次数),确实会存在竞态条件:
- 假设当前帖子已更新2次,投影还没同步最新状态
- 两个编辑请求同时到达,都通过了投影的校验,最终生成3次更新事件,违反业务规则
所以领域不变量的校验必须在聚合内部完成,只有聚合从事件序列重建出的状态才是强一致的,能确保规则被严格执行。
关于性能优化的补充
如果担心全量回放事件的性能问题,可以引入快照机制:
- 定期(比如聚合事件达到N条时)将聚合的当前状态序列化存储为快照
- 重建聚合时,先加载最新快照,再回放快照之后产生的事件
- 快照可以随时删除或重新生成,因为它完全依赖于事件序列,不会成为权威数据源
内容的提问来源于stack exchange,提问作者stackoverflower
相关产品推荐
相关产品推荐

