【发布时间】:2021-04-08 18:22:21
【问题描述】:
当我们需要更改 2 个系统中的数据时,双写是一个问题:数据库(SQL 或 NoSQL)和 Apache Kafka(例如)。 必须更新数据库并可靠/原子地发布消息。 最终的一致性是可以接受的,但不一致是不能接受的。
没有 2 阶段提交 (2PC) 双写会导致不一致。
但在大多数情况下,2PC 不是一个选项。
Transactional Outbox 是一种微服务架构模式,其中一个单独的消息中继进程将插入数据库的事件发布到消息代理。
并行运行的多个消息中继进程会导致发布重复(2 个进程读取 OUTBOX 表中的相同记录)或无序(如果每个进程只读取 OUTBOX 表的一部分)。
单个消息中继进程也可能多次发布消息。消息中继可能会在处理 OUTBOX 记录之后但在记录它已经这样做的事实之前崩溃。当消息中继重新启动时,它会再次发布相同的消息。
如何在事务性发件箱模式中实现消息中继,从而将重复消息或无序消息的风险降至最低,并且该概念适用于所有 SQL 和 NoSQL 数据库?
【问题讨论】:
-
Kafka 的排序保证比 Confluent 声称的要弱得多(和/或在实践中不太适用)。
-
对于您的特定场景,在我看来,使用数据库进行分布式锁的最佳方式,因为您已经依赖它。 Postgres 有咨询锁的概念。想象一下,您有 n 个 ServiceA 的副本,在每个副本中,您都有一个后台作业,它试图在无限循环中获取锁,如果锁被占用,这个副本将成为主副本并开始处理事务中的消息,如果它被提交或回滚或服务崩溃,锁被释放,另一个副本可以快速成为主副本。
标签: duplicates microservices distributed-transactions 2phase-commit outbox-pattern