Database 微服务:原子事件

Database 微服务:原子事件,database,events,microservices,Database,Events,Microservices,我现在正在学习microservice数据复制,有一件事我遇到了麻烦,那就是提出了确保事件原子性的正确体系结构。据我理解,基本流程是: 将更改提交到数据库 在全局消息总线上发布详细说明更改的事件 但是,如果,例如,在步骤1和步骤2之间发生断电,该怎么办?在一个幼稚构建的系统中,这意味着更改将持续,但详细说明更改的事件将永远不会发布。为了创造更好的担保,我考虑了以下想法,但我不太确定每种想法的利弊: 答:在我的microservice实例中使用一个嵌入式数据库(比如SQLite)来跟踪整个事务,从

我现在正在学习microservice数据复制,有一件事我遇到了麻烦,那就是提出了确保事件原子性的正确体系结构。据我理解,基本流程是:

  • 将更改提交到数据库
  • 在全局消息总线上发布详细说明更改的事件
  • 但是,如果,例如,在步骤1和步骤2之间发生断电,该怎么办?在一个幼稚构建的系统中,这意味着更改将持续,但详细说明更改的事件将永远不会发布。为了创造更好的担保,我考虑了以下想法,但我不太确定每种想法的利弊:

    答:在我的microservice实例中使用一个嵌入式数据库(比如SQLite)来跟踪整个事务,从提交到主数据库再到事件发布

    B:在我的主数据库中创建一个事件表,使用数据库事务插入事件,同时提交相关更改。然后,服务将事件推送到总线,然后向主数据库再次提交,以将事件标记为已发布

    C:如上所述,在我的主数据库中创建一个事件表,使用数据库事务插入事件,同时提交相关更改。然后,通知(通过服务内的REST/消息或通过数据库挂钩手动通知)专用EventPusher服务已附加新事件。EventPusher服务将查询Events表并将事件推送到总线,在确认后将每个事件标记为已发布。如果某段时间没有任何通知,EventPusher将执行手动查询

    以上每种选择的优缺点是什么?还有另一个更好的选择吗?

    但是,如果,例如,在步骤1和步骤2之间发生断电,该怎么办

    考虑以下方法:

    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:这个问题是一个非常重要的方面,在许多有关微服务和事件源的讲座/文章/教程中通常没有讨论。他们没有强调需要对事件日志进行原子推送。