Database 微服务:原子事件
我现在正在学习microservice数据复制,有一件事我遇到了麻烦,那就是提出了确保事件原子性的正确体系结构。据我理解,基本流程是:Database 微服务:原子事件,database,events,microservices,Database,Events,Microservices,我现在正在学习microservice数据复制,有一件事我遇到了麻烦,那就是提出了确保事件原子性的正确体系结构。据我理解,基本流程是: 将更改提交到数据库 在全局消息总线上发布详细说明更改的事件 但是,如果,例如,在步骤1和步骤2之间发生断电,该怎么办?在一个幼稚构建的系统中,这意味着更改将持续,但详细说明更改的事件将永远不会发布。为了创造更好的担保,我考虑了以下想法,但我不太确定每种想法的利弊: 答:在我的microservice实例中使用一个嵌入式数据库(比如SQLite)来跟踪整个事务,从
using(var scope = new TransactionScope())
{
_repository.UpdateUser(data);
_eventStore.Publish(new UserUpdated { ... });
scope.Complete();
}
此伪代码假定您正在使用与和类似的内容
因此,即使您的事件存储实现为某种外部服务,在事件存储发出成功信号之前,您的UpdateUser事务也不会提交。
当您已经收到来自_eventStore的响应,但尚未提交ORM事务范围时,失败的可能性仍然很小。在这种最坏的情况下,您将得到一个已发布的事件,但数据库中始终存储状态最新快照的数据丢失。本质上,快照对此聚合无效
如果您的域不能容忍此类风险,您根本不应该在关系数据库中存储状态/快照。事件存储将是您可以依赖的唯一真相来源(这是许多CQR/ES从业者推荐的方法)
B:在我的主数据库中创建一个事件表,使用数据库事务插入事件,同时提交相关更改。然后,服务将事件推送到总线,然后向主数据库再次提交,以将事件标记为已发布
这种方法同样有效,但是,您必须重新发明轮子,而不是简单地重用一些事件存储
选项A和C太异乎寻常/过度设计以至于不能认真考虑是否可行。 我一直在想同样的事情。
显然,有许多方法可以处理更新数据库和发布相应事件的原子性。
例如: Order服务在Order表中插入一行,并插入 将创建的事件排序到事件表中[在单个本地db事务的范围内]。
事件发布者线程 或进程查询事件表中未发布的事件,发布 事件,然后更新事件表以将事件标记为 出版 () 如果事件发布服务器在任何时候崩溃或以其他方式失败,它未处理的事件仍将标记为未发布。
因此,当事件发布者重新联机时,它将立即发布这些事件。
如果事件发布者发布了一个事件,然后在将该事件标记为已发布之前崩溃,则可能会多次发布该事件。
因此,订阅者必须消除收到的重复消息 此外,对于一个stackoverflow问题——这听起来可能与你的问题大不相同,但本质上是问同样的问题——链接到几个相关的博客帖子
- [请参阅:Q:您构建至少支持服务总线和Azure SQL数据库之间事务性切换的东西的可能性有多大?]
听起来好像你应该考虑事件源。这意味着您不需要提交事件数据,只需提交事件本身即可。许多事件源框架在不使用两阶段提交的情况下,负责提交和发布事件的一致性语义。AWS DynamoDB Streams with Lambda:这个问题是一个非常重要的方面,在许多有关微服务和事件源的讲座/文章/教程中通常没有讨论。他们没有强调需要对事件日志进行原子推送。