Microservices 使用数据库CDC的事件源是否被认为是良好的体系结构?

Microservices 使用数据库CDC的事件源是否被认为是良好的体系结构?,microservices,cqrs,software-design,event-sourcing,debezium,Microservices,Cqrs,Software Design,Event Sourcing,Debezium,当我们谈到事件源时,我们有一个简单的双写体系结构,在这个体系结构中,我们可以写入数据库,然后将事件写入类似Kafka的队列。其他下游系统可以读取这些事件并相应地采取行动/使用它们 但是,当试图使DB和事件同步时,就会出现问题,因为需要对这些事件进行排序才能使其有意义 为了解决这个问题,人们鼓励使用数据库提交日志作为事件源,并且有围绕它构建的工具,如Airbnb的Spinal Tap、Redhat的Debezium、Oracle的Golden gate等。。。它解决了一致性、顺序保证等问题 但是使

当我们谈到事件源时,我们有一个简单的双写体系结构,在这个体系结构中,我们可以写入数据库,然后将事件写入类似Kafka的队列。其他下游系统可以读取这些事件并相应地采取行动/使用它们

但是,当试图使DB和事件同步时,就会出现问题,因为需要对这些事件进行排序才能使其有意义

为了解决这个问题,人们鼓励使用数据库提交日志作为事件源,并且有围绕它构建的工具,如Airbnb的Spinal Tap、Redhat的Debezium、Oracle的Golden gate等。。。它解决了一致性、顺序保证等问题

但是使用数据库提交日志作为事件源的问题是,我们与DB模式紧密耦合。微服务的DB模式是公开的,DB模式中的任何破坏性更改(如数据类型更改或列名更改)实际上都会破坏下游系统

那么,使用DB CDC作为事件源是一个好主意吗


如果您正在使用事件源:

那么联轴器就不应该存在了。事件存储是通用的,它不关心事件的内部状态。在最坏的情况下,您将与事件存储本身的内部结构相耦合,但这并不是特定于特定的微服务的

如果不使用事件源:


在这种情况下,聚合的内部结构与CDC组件之间存在耦合(CDC组件捕获数据更改并将事件发布到消息队列或类似组件)。为了限制这种耦合对微服务本身的影响,CDC组件应该是它的一部分。这样,当微服务中聚合的内部结构发生变化时,CDC组件也会发生变化,外部世界不会注意到。这两项更改同时部署。

扩展了康斯坦丁的答案:

TLDR

事务日志跟踪/挖掘应该对其他人隐藏

严格来说,它不是一个事件流,因为您不应该直接从其他服务访问它。它通常用于将遗留系统逐渐过渡到基于微服务的系统时。流程可能如下所示:

  • 服务A向数据库提交事务
  • 框架或服务轮询提交日志,并将新提交作为事件映射到Kafka
  • 服务B订阅Kafka流,并从那里(而不是从DB)使用事件
  • 更长的故事:

    服务B看不到您的事件来自数据库,也不直接访问数据库。提交数据应投影到事件中。如果更改DB,则只应修改投影规则,将新模式中的提交映射为“旧”事件格式,因此不能更改使用者。(我不熟悉Debezium,或者它是否能做这个投影)

    您的事件应该与发布事件和提交事务等幂 原子性在分布式场景中是一个问题,工具将保证至少一次交付,最多只使用一次处理语义,而精确一次的部分更为罕见。这是因为事件源(事务日志)与其他服务将访问的流不同,即它是分布式的。这仍然是制作人的部分,卡夫卡->消费者频道也存在同样的问题,但原因不同。同样,您实现的是一个消息队列

    如果可能的话,我建议使用专用的事件存储,比如Greg Young的:。这通过将事件存储和MessageBroker集成到单个解决方案中来解决问题。通过将事件(JSON格式)存储到流中,您还可以“发布”它,因为消费者订阅了该流。如果希望进一步解耦服务,可以编写将事件从一个流映射到另一个流的投影。您的事件消耗也应该是幂等的,但是您得到的事件存储是由聚合划分的,并且读取速度非常快

    如果您也想将数据存储在SQL DB中,那么请侦听这些事件并根据它们插入/更新表,只是不要将SQL DB用作事件存储,因为它很难正确实现(防故障)

    对于排序部分:将对从一个流读取事件进行排序。聚合多个事件流的投影只能保证源自同一流的事件之间的顺序。这通常已经足够了。(顺便说一句,如有必要,您可以根据消费者端的某些字段对消息重新排序。)

    那么,使用DB CDC作为事件源是一个好主意吗

    “这是一个好主意吗?”这个问题将取决于您的环境,以及您需要进行的不同权衡的成本和收益

    也就是说,据我所知,这不是一个与活动采购传统相一致的想法

    事件来源——我们的记录簿是状态变化的分类账——已经存在很长时间了。毕竟,当我们谈论“分类账”时,我们实际上是在暗指那些数百年前写的记录商业的文件

    但很多关于软件事件源的讨论都受到领域驱动设计的严重影响;DDD提倡(除其他外)将您的代码概念与您正在建模的领域中的概念对齐

    所以问题是:除非您处于极端的边缘情况,否则您的数据库可能是一些通用应用程序,您正在定制/配置这些应用程序以满足您的需求。变更数据捕获将受到限制,因为它是使用通用机制实现的。因此,生成的事件看起来像是通用补丁文档(这里是之前和之后的区别)

    但如果我们尝试