【发布时间】:2018-02-22 07:16:05
【问题描述】:
由于我没有在我的 CQRS 应用程序中使用事件溯源,因此我引入了一个简单的事件日志,使我能够更新读取存储。
这意味着我的应用程序的状态更改包含两个操作:
- 更新写入模型状态,例如SQL 插入
- 将事件插入事件日志
两个写操作都必须作为一个原子操作发生。不幸的是,事件日志位于另一个数据库中,所以我必须考虑分布式事务。
大多数 CQRS 示例都处理 saga 模式,而且它们似乎都使用了事件溯源,这让事情变得更加简单。
我的问题是“半完成”状态更改,例如
- SQL 插入成功
- 事件日志插入失败
我可以想出一个补偿 SQL 操作(伪代码):
SQLTransaction.Commit(); // if this fails, all is fine. Nothing to revert
try
{
EventLog.Insert(event);
}
catch(Exception ex)
{
// Try to undo the SQL stuff.
CompensatingSQLTransaction().Commit();
// uh-oh! The commit fails!!
// What now? Do a Retry?
}
有什么概念可以帮助我吗? 我考虑了以下方案来防止读取数据库不同步:
- 每个事件都有一个序列号
- 如果读取端复制检测到未处理的事件(例如,接收到 40,然后是 42),它会在事件日志中查询事件 41。
- 如果事件 41 不可用,系统将停止复制任何事件,直到有人仔细查看。
这需要手动维护,但可以防止读取数据库不同步。
任何真实的生活经历?
【问题讨论】:
-
您的系统分布如何?您希望它具有多大的弹性/可扩展性?
-
它应该能够每月处理大约 10 或 2000 万个事件。它应该能够利用多个节点来处理由总线系统连接的命令和/或事件。所以事件复制可能发生在多个节点上。
标签: events domain-driven-design microservices cqrs distributed-system