如何保持rdms和Kafka的同步?

j91ykkif  于 2021-06-07  发布在  Kafka
关注(0)|答案(2)|浏览(286)

我们想介绍一个kafka事件总线,它将包含以下事件 EntityCreated 或者 EntityModified 这样系统的其他部分就可以使用它了。主应用程序在引擎盖下使用rdms(即postgres)来存储实体及其关系。
现在的问题是如何确保你只发送 EntityCreated Kafka事件,如果您成功保存到rdms。如果你不确定这是事实,你最终会在消费者身上产生矛盾。
我看到了三个解决方案,但没有一个是令人信服的:
不要在意:非常危险,插入rdms时可能会出错。
在保存实体时,还要保存应该发送到自己表中的消息。然后有一个单独的进程从这个表中消费并发布到kafka,成功后从这个表中删除。这是一个非常复杂的实现,而且看起来像一个反模式。
插入到rdms中,保持(sql-)事务处于打开状态,直到您成功地向kafka写入了代码,然后才提交。问题是您可能会将rdms事务保持打开状态一段时间。不知道问题有多大。
执行真正的cqrs,这意味着您根本不保存到rdms,而是从kafka队列中构造rdms。这似乎是一个理想的方式,但很难改装到一个服务。此外,还存在由于延迟而导致的不一致性问题。
我在网上很难找到好的解决办法。
也许这个问题太宽泛了,请随意给我指出一个更合适的地方。

fhg3lkii

fhg3lkii1#

如果您的需求是将sql和kafka看作一个节点,那么没有完美的方法可以做到这一点。所以问题应该是:“如果发生了什么坏事(电源故障、硬件故障),我能承受得起?如果必须应用到我的应用程序中,我可以做哪些更改(编程、架构)
对于你提到的几点:
如果节点在从sql中删除之前插入到kafka之后失败了呢?
如果在提交sql事务之前插入kafka之后节点失败了怎么办?
如果在提交kafka偏移量之前,节点在插入到sql之后失败了呢?
它们都将面临数据不一致的风险(如果数据插入到sql不能多次成功,例如它们有一个非数据库生成的pk,则4稍微好一些)。
从变化的Angular 来看,3是最小的,但是它会降低sql吞吐量。4是最大的,因为您的业务逻辑模型在编码时会面对两种数据库(通过数据编码器写入kafka,通过sql语句读取sql),它比其他数据库耦合性更强。
因此,选择取决于你的业务是什么。没有通用的方法。

c7rzv4ha

c7rzv4ha2#

在保存实体时,还要保存应该发送到自己表中的消息。然后有一个单独的进程从这个表中消费并发布到kafka,成功后从这个表中删除。这是一个非常复杂的实现,而且看起来像一个反模式。
实际上,这就是udi dahan在他的演讲中描述的解决方案:没有分布式事务的可靠消息传递。它实际上非常接近“最佳实践”;因此,有必要探讨一下为什么你认为这是一种反模式。
执行真正的cqrs,这意味着您根本不保存到rdms,而是从kafka队列中构造rdms。
不!那就是怪物藏身的地方(见下文)。
如果您正在进行“真正的cqr”,那么您的主要用例将是您的编写者使事件在您的记录簿中持久化,并且消费者将定期轮询更新。想想“atom提要”,还有一个额外的约束,即条目和条目顺序是不可变的;您可以共享事件和事件页面;缓存失效不是一个问题,因为状态不变,所以事件表示“永远”有效。
这也有好处,你的消费者不需要担心消息订购;使用者正在读取有序事件的文档,其中包含指向先前和后续文档的指针。
此外,您还获得了一个版本控制故事的解决方案:与广播同一事件的n个不同表示不同,您发送一个表示,然后在消费者轮询您时协商内容。
现在,轮询确实存在延迟问题;您可以通过广播更新公告并通知使用者新事件可用来减少延迟。
如果您想降低错误轮询的比率(唤醒消费者不关心的事件),那么可以开始向通知中添加更多信息,以便消费者可以判断是否拉入更新。
请注意,“唤醒并可能轮询”是一个单独由单个事件触发的过程唤醒并投票只是这个信息“是另一个相同的想法变化。我们播放了emaildeliveryscheduled的精简版本;负责此项服务的服务会回电话询问电子邮件/事件的增强版本,以及构建电子邮件所需的详细信息。
这些是“唤醒并使用通知”的专门化。如果您有一个无法承受轮询所需的额外延迟的用例,您可以在隔离事件的表示中使用状态。
但是当这些信息已经作为一个可共享、可缓存的文档公开时,试图重现一个有序的事件序列。。。这是一个非常不寻常的用例。我不会把它当作一个需要解决的一般问题来考虑——我的猜测是,这些案例很罕见,而且不容易推广。
请注意,以上所有内容都是关于消息传递的,而不是关于Kafka的。注意,消息传递和事件源是作为不同的用例记录的。jay kreps写道(2013)
我在这里使用术语“log”而不是“messaging system”或“pub sub”,因为它更具体地描述了语义,更详细地描述了您在支持数据复制的实际实现中需要什么。
您可以将日志看作是一种具有持久性保证和强排序语义的消息传递系统
记录簿应是事件消息顺序的唯一权限。任何关心订单的消费者都应该阅读记录簿中的订单文档,而不是阅读无序的文档并重新构建订单。
在您当前的设计中。。。。
现在的问题是,如果成功保存到rdms,如何确保只在kafka上发送entitycreated事件。
如果rdbms是记录之书(“真相”的来源),那么Kafka日志就不是了。
你可以从这里走几步就到那里;大致来说,你将事件添加到现有的数据库中,你从现有的数据库中读取并写入Kafka的日志;您使用kafka的日志作为(延时的)真相源来构建现有rdbms的副本,您将读取用例迁移到副本,您将写入用例迁移到kafka,并且您取消了遗留数据库的使用。
Kafka的日志可能是,也可能不是你想要的记录本。greg young开发get event store已有相当一段时间了,并列举了一些折衷方法(2016年)。我不认为用一个编写良好的代码库将日志从一个转换到另一个会太困难,但是我根本不能谈论可能发生的额外耦合。

相关问题