You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Event Sourcing/CQRS中如何处理静态数据?

在Event Sourcing/CQRS中处理静态数据的正确姿势

先明确核心原则:事件的本质是记录「业务决策发生时的上下文事实」,而非存储完整的关联静态数据;读模型的设计则完全服务于业务查询的需求。下面逐个解答你的困惑:

1. 命令端:静态数据是否该纳入事件?

不需要把完整的静态实体(比如整个Product记录,包括关联的分类、供应商)塞进事件里,但要把决策发生时依赖的、会影响业务逻辑或后续读模型展示的关键静态数据快照加进去。

  • 比如LineAdded事件里的itemPrice就是典型的快照:产品价格后续可能调整,但订单里的价格必须是下单时的价格,所以必须固化到事件中。
  • 如果业务要求旧订单展示「下单时的产品描述」,那就要把itemDescription也放进事件;但如果业务允许旧订单自动同步最新的产品描述,那就不用加。
  • 分类、供应商这类关联数据,只有当它们是当时决策的依据(比如下单时限制只能选某类供应商的产品),或者读模型需要展示历史状态时,才需要把当时的快照(比如categoryName、supplierName)放进事件,否则完全没必要。

2. 查询端:静态数据该进读模型还是查询时JOIN?

完全取决于业务需求:

  • 如果业务要求查询结果展示静态数据的最新状态(比如产品描述改了,所有旧订单的展示都要同步更新),那读模型只需要存静态数据的ID(比如itemID),查询时直接JOIN静态表即可。这种方式不用处理静态数据变更的同步问题,若担心性能,可通过缓存静态数据(如Redis)优化。
  • 如果业务要求查询结果展示数据发生时的历史状态(比如旧订单必须显示下单时的产品描述和价格),那必须把当时的静态数据快照放进事件,投影时直接写入读模型,查询时不需要JOIN。这种方式能精准还原历史,查询效率也更高。

3. 不纳入事件就必须JOIN?

没错,但这不是问题——JOIN是数据库的常规操作,只要业务允许展示静态数据的最新状态,这种方式反而更简洁,避免了事件数据冗余。

4. 纳入事件后静态数据变更无法反映?

这是有意为之的取舍。如果业务要求历史记录必须保持当时的状态,那这正是你想要的效果;如果业务要求历史记录同步最新静态数据,那你就不该把静态数据塞进事件,而是用JOIN的方式。


总结下来,正确的处理方式分两种场景:

  • 场景1:静态数据变更需要同步到所有历史记录:
    • 命令端:事件只存静态数据的ID,不存快照
    • 查询端:读模型存ID,查询时JOIN静态表(或缓存)
  • 场景2:历史记录必须保留静态数据的当时状态:
    • 命令端:事件存入决策时依赖的关键静态数据快照(不用全量,只存需要展示或后续业务逻辑需要的字段)
    • 查询端:投影时把快照写入读模型,查询时直接读取,无需JOIN

内容的提问来源于stack exchange,提问作者user1102018

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:35:26