事件存储可能成为单点故障?

gab*_*ssi 9 cqrs event-sourcing get-event-store microservices

几天以来,我一直试图弄清楚如何告知其余的微服务,在微服务A中创建一个新实体,将该实体存储在MongoDB中.

我想要:

  • 微服务之间的耦合很低

  • 避免像两阶段提交(2PC)这样的微服务之间的分布式事务

起初像RabbitMQ这样的消息代理似乎是一个很好的工具,但后来我看到了在MongoDB 中提交新文档并在代理中发布消息而不是原子的问题.

为何选择活动?by eventuate.io: 在此输入图像描述

解决此问题的一种方法意味着通过添加一个标记来说明文档的模式有点脏,该标记表明文档是否已在代理中发布,并且具有在MongoDB中搜索未发布文档的预定后台进程,并使用这些文档将这些文档发布到代理确认,当确认到达时,文档将被标记为已发布(使用at-least-once和idempotency语义).这个解决方案在提出并且这个答案.

阅读Chris Richardson 的微服务简介我最后在这个关于开发功能域模型的伟大演示中,其中一个幻灯片询问:

如何在没有2PC的情况下自动更新数据库发布事件和发布事件?(双写问题).

答案很简单(在下一张幻灯片中)

更新数据库发布事件

这是一种不同的方式来这一个是基于CQRS一拉Greg Young的.

域存储库负责发布事件,这通常在单个事务内部,同时将事件存储在事件存储中.

我认为委托将事件存储和发布到事件存储的责任是一件好事,因为避免了2PC或后台进程的需要.

然而,以某种方式它的真实:

如果您依赖事件存储来发布事件,那么您将与存储机制紧密耦合.

但是,如果我们采用消息代理来进行微服务的交互,我们可以说同样的话.

令我担心的是,事件存储似乎成为单点故障.

如果我们从eventuate.io看这个例子 在此输入图像描述

我们可以看到,如果事件存储已关闭,我们无法创建帐户或资金转移,失去了微服务的优势之一.(虽然系统将继续响应查询).

因此,确认eventuate示例中使用的事件存储是单点故障是正确的吗?

Aki*_*ira 6

你面临的是两个一般问题的一个例子.基本上,您希望网络上有两个实体同意某些内容,但网络不是故障安全的.Leslie Lamport证明这是不可能的.

因此,无论您向网络添加多少新实体,消息队列为一个,您将永远不会100%确定将达成协议.实际上,情况恰恰相反:您添加到分布式系统的实体越多,您就越不能确定最终会达成协议.

对你的情况一个实际的答案是,如果你考虑增加更多的复杂性和单点故障,2PC并不是那么糟糕.如果您绝对不希望出现单点故障并且想要假设网络是可靠的(换句话说,网络本身不能是单点故障),您可以尝试使用P2P算法,例如DHT,但是两个同行我打赌它减少到简单的2PC.