每个命令的事件溯源再水合?
Event Sourcing Re-hydration every Command?
我有一个以 CQRS 模式作为补充的事件源系统。
假设命令有效,向服务器发出的每个命令都会使用事件流将我的聚合(新初始化的聚合)重新水合到当前状态。
我的问题是 - 为什么我应该在每个命令中重新水合我的聚合状态?为什么我不能只保留一个聚合每个聚合 ID 的实例而不用担心重新水合每个命令?在这种情况下,我只会在启动服务器时重新水化事件。
这样做有什么问题吗?它仍然会保留状态历史,因为事件会继续存在。
谢谢!
编辑: 我每隔 n 个事件就对我的聚合状态进行快照,因此我不必在每次重新水化时重新水化超过 n 个事件。此外,每次保存新快照以保存对状态的请求时,我都会缓存聚合状态。 我更想知道,如果我可以在内存中保留一个 运行 聚合实例(每个 aggregateId),为什么还要再补水呢?
Why can't I just keep an aggregate instance per aggregate Id and not worry about re-hydrating every command?
当然,没关系 - 您可以通过 缓存 内存中的聚合表示来节省一些工作。
如果您有多个可以更改事件流的进程,那就更难了;您需要做一些额外的簿记工作,这样当您的本地缓存副本碰巧与最近的编辑不同步时,您就不会错误地计算事件。
我同意@voiceofunreason 在几乎所有情况下(根据个人经验),storing\caching "current" 聚合状态非常好。但是,您应该意识到这样做可能会遗漏一些东西:
- 你没有在运动补充水分。这可能会隐藏版本控制问题足够长的时间,从而成为一个大问题。认为这类似于备份数据库,但从不测试恢复。
- 通过存储缓存,您将失去使用延迟事件的机会。例如,您可以有一个像 "New pricing applies after November" 这样的事件。一旦你拥有这个事件,你就会存储它,但它只会在特定日期之后影响状态(定价)。诚然,这是一个特定的(诚然不是特别常见的)情况,但它是你会失去的东西。
- 您将无法使用 "What did I know about X aggregate at that point in time".
这样的(双)时态查询
第 1 点比其他点更重要,但有很多方法可以解决这个问题,而不是每次都实际补水。只是补水在很多情况下是一个不错的选择。
将快照与事件一起使用,并使用快照和更新的事件进行再水化解决了这些问题,因为:
- 重组是直到你拍摄
- 当您有 "late-fire-event" 时,由于快照与事件并排存储,因此很容易停止快照,直到延迟事件应用,之后您就可以拍摄快照了。
- 您可以绕过临时查询的快照。
我有一个以 CQRS 模式作为补充的事件源系统。 假设命令有效,向服务器发出的每个命令都会使用事件流将我的聚合(新初始化的聚合)重新水合到当前状态。
我的问题是 - 为什么我应该在每个命令中重新水合我的聚合状态?为什么我不能只保留一个聚合每个聚合 ID 的实例而不用担心重新水合每个命令?在这种情况下,我只会在启动服务器时重新水化事件。
这样做有什么问题吗?它仍然会保留状态历史,因为事件会继续存在。
谢谢!
编辑: 我每隔 n 个事件就对我的聚合状态进行快照,因此我不必在每次重新水化时重新水化超过 n 个事件。此外,每次保存新快照以保存对状态的请求时,我都会缓存聚合状态。 我更想知道,如果我可以在内存中保留一个 运行 聚合实例(每个 aggregateId),为什么还要再补水呢?
Why can't I just keep an aggregate instance per aggregate Id and not worry about re-hydrating every command?
当然,没关系 - 您可以通过 缓存 内存中的聚合表示来节省一些工作。
如果您有多个可以更改事件流的进程,那就更难了;您需要做一些额外的簿记工作,这样当您的本地缓存副本碰巧与最近的编辑不同步时,您就不会错误地计算事件。
我同意@voiceofunreason 在几乎所有情况下(根据个人经验),storing\caching "current" 聚合状态非常好。但是,您应该意识到这样做可能会遗漏一些东西:
- 你没有在运动补充水分。这可能会隐藏版本控制问题足够长的时间,从而成为一个大问题。认为这类似于备份数据库,但从不测试恢复。
- 通过存储缓存,您将失去使用延迟事件的机会。例如,您可以有一个像 "New pricing applies after November" 这样的事件。一旦你拥有这个事件,你就会存储它,但它只会在特定日期之后影响状态(定价)。诚然,这是一个特定的(诚然不是特别常见的)情况,但它是你会失去的东西。
- 您将无法使用 "What did I know about X aggregate at that point in time". 这样的(双)时态查询
第 1 点比其他点更重要,但有很多方法可以解决这个问题,而不是每次都实际补水。只是补水在很多情况下是一个不错的选择。
将快照与事件一起使用,并使用快照和更新的事件进行再水化解决了这些问题,因为:
- 重组是直到你拍摄
- 当您有 "late-fire-event" 时,由于快照与事件并排存储,因此很容易停止快照,直到延迟事件应用,之后您就可以拍摄快照了。
- 您可以绕过临时查询的快照。