【问题标题】:Reverting the Transactional Outbox Pattern恢复事务性发件箱模式
【发布时间】:2020-12-16 23:22:49
【问题描述】:

问题描述:

使用跨数据库和消息代理的分布式事务以原子方式更新数据库和发布消息/事件是不可行的。

发件箱模式描述了一种让服务以安全一致的方式执行这两个任务的方法;它为源服务提供即时“读取您自己的写入”语义,同时提供跨服务边界的可靠、最终一致的数据交换。

如果我从 topicA 读取消息 -> 向 topicB 写入消息(使用 Kafka Streams 的语义恰好一次)并使用事件监听器更新数据库,会有什么缺点?

这意味着在数据库实体被持久化之前我将拥有最终的一致性,但不会丢失数据,因为我在 Kafka 主题中有消息(重试直到持久性有效)。

这种模式还存在以下问题:

消息中继可能会多次发布消息。例如,它可能会在发布消息之后但在记录它已经这样做的事实之前崩溃。当它重新启动时,它将再次发布消息。因此,消息消费者必须是幂等的,可能通过跟踪它已经处理的消息的 ID 来实现。幸运的是,由于消息消费者通常需要是幂等的(因为消息代理可以多次传递消息),这通常不是问题。

问题:

那么当谈到妥协时,什么更好,保持 Kafka 作为单一事实来源并处理数据库中的最终一致性,还是将 Db 作为事实来源并将 kafka 用作愚蠢的消息代理?

我对你的意见很感兴趣!谢谢!

【问题讨论】:

    标签: apache-kafka apache-kafka-streams eventual-consistency exactly-once outbox-pattern


    【解决方案1】:

    我不确定您是否真的需要流处理器。 也许一个好的方法是写入数据库并使用 CDC 连接器将数据流式传输到 Kafka。 CDC 将跟踪 DB Tables 的事务日志并将更改反映到 kafka 主题。 即使在连接失败的情况下,一旦重新启动主题最终将与数据库状态同步

    【讨论】:

    • 感谢您的回答。这实际上是目前的计划。用 Debezium 替换此自定义实现以发送消息。流处理器将保证从一个主题到另一个主题的事务只需要一次,我认为这个解决方案的性能要好得多。
    • 是的,没错。但是,如果没有对来自 TopicA->TopicB 的数据进行转换,则数据将在集群中重复。这可能是一个可能的缺点。此外,如果数据更新到流处理器中的数据库,您将失去恰好一次的权限,因为 Kafka 事务不是跨系统事务。
    • 是的,如果您想让 Kafka 集群作为事实来源,那么在 Kafka 中复制数据以及在不通过 kafka 主题的情况下更新数据库是没有意义的。从某种意义上说,它是 CQRS 的一个版本,其中写入发生在 kafka 中,读取发生在 db 中,具有随之而来的所有良好属性......
    猜你喜欢
    • 2020-10-01
    • 2021-04-08
    • 1970-01-01
    • 2017-10-27
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多