我现在正在学习微服务数据复制,我遇到的一件事是想出正确的架构来确保事件的原子性。按照我的理解,基本流程是:
- 提交对数据库的更改。
- 发布一个事件,详细说明全局消息总线上的变化。
但是,如果在第 1 步和第 2 步之间发生断电怎么办?在天真构建的系统中,这意味着更改会持续存在,但详细说明它们的事件将永远不会发布。我考虑过以下想法来创建更好的保证,但我不太确定每个想法的所有优缺点:
A:在我的微服务实例中使用嵌入式数据库(如 SQLite)来跟踪整个事务,从提交到主数据库再到事件发布。
B:在我的主数据库中创建一个事件表,使用数据库事务插入事件并同时提交相关更改。然后服务会将事件推送到总线,然后再次提交到主数据库以将事件标记为已发布。
C:同上,在我的主数据库中创建一个Events表,使用数据库事务插入Event并同时提交相关的更改。然后,通知(通过服务内的 REST/Messages 手动或通过数据库 Hook )一个专用的 EventPusher 服务已附加一个新事件。 EventPusher 服务将查询事件表并将事件推送到总线,并在确认后将每个事件标记为已发布。如果一段时间后没有任何通知,EventPusher 将进行手动查询。
上述每种选择的优缺点是什么?我还没有考虑其他更好的选择吗?
最佳答案
我一直在想同样的事情。
显然,有很多方法可以处理更新数据库和发布相应事件的原子性。
( Pattern: Event-driven architecture )
Application events模式听起来与您的想法相似。
一个例子可以是:
The Order Service inserts a row into the ORDER table and inserts an Order Created event into the EVENT table [in the scope of a single local db transaction].
The Event Publisher thread or process queries the EVENT table for unpublished events, publishes the events, and then updates the EVENT table to mark the events as published.
( Event-Driven Data Management for Microservices )
如果事件发布者在任何时候崩溃或以其他方式失败,它没有处理的事件仍然被标记为未发布。
因此,当 Event Publisher 重新上线时,它会立即发布这些事件。
如果事件发布者发布了一个事件,然后在将事件标记为已发布之前崩溃了,则该事件可能会发布多次。
因此,订阅者对收到的消息进行重复数据删除非常重要。
此外,the answer到一个 stackoverflow 问题——这听起来可能与你的问题截然不同,但本质上是在问同样的事情——链接到几篇相关的博客文章。
- Removing 2PC (Two Phase Commit)
- Idempotency Patterns
- Transactions in Windows Azure (with Service Bus) [请参阅:问:您构建至少支持服务总线与 Azure SQL 数据库之间事务切换的东西的可能性有多大?]
关于database - 微服务:原子事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41655915/