讲分布式事务之前,我们知道事务(ACID)它是用在单一架构系统中,是强一致性。而在微服务中需要可用性和高可伸缩性,而不是强一致性。微服务中一般通过弱处理或最终一致性的技术来实现强一致性。此外ACID 只支持关系型数据库,对于nosql不太支持。
强一致性技术在微服务系统的情况下几乎不可能实现。
最终一致性的驱动因素之一是分布式数据存储遵循 CAP 定理,该定理指出,分布式系统在任何时候只能实现三个特性(一致性、可用性和分区容错性)中的两个。
1)一致性(Consistency):群集中的每个节点都使用最新数据进行响应, 如果查询当前正在更新的项"一致性系统",则在所有副本成功更新之前,不会获得响应(阻塞)。 但是,你始终会收到最新的数据。
2)可用性(Availability): 每个节点都返回即时响应,即使该响应不是最新数据。 如果是"可用性系统"来查询正在更新的项,你将获得服务此时的数据(不阻塞)。
3)分区容错性(Partition tolerance):保证数据节点发生故障或数据节点失去连接,系统仍继续运行。
在CAP定理中,P是必须要有的。当数据节点发生故障,系统仍继续运行,因此分布式应用程序必须是AP或CP。一般是选择AP 最终一致性。
1.数据冗余更新难点
还有一个挑战是当某些数据需要冗余时,如何在多个微服务之间传播更改。使用“事件驱动的异步通信”来解决,考虑用rabbitmq的发布订阅消息传递队列。将事件发布到事件总线,许多微服务可以订阅它,以获取通知并对其进行操作。参考“多个微服务中数据检索”文章
2.最终一致性如何处理失败步骤
最终一致性模型中的一个难题是如何处理失败步骤。 这种情况下,可能需要撤销此操作中,先前步骤已完成的所有工作。然而数据不能回滚,因为应用程序的其他并发实例可能已更改了数据,即使在数据并未被并发实例更改的情况下,撤销步骤也可能不仅仅是还原原始状态。 可能需要应用多种业务特定规则。
如果实现最终一致性的操作跨多个异类数据存储,则撤销操作中的步骤需要依次访问每个数据存储。 必须以可靠方式撤销每个数据存储中执行的工作,以此防止系统保持不一致。
解决方案是实现补偿事务。 补偿事务中的步骤必须撤销原始操作中的步骤, 补偿事务可能无法将当前状态替换为此操作开始时系统所处的状态,因为此方法可能会覆盖其他并发实例所作的更改。
相反,必须是一个智能过程,该智能过程会考虑到并发实例执行的所有工作。 该过程通常特定于应用程序,由原始操作执行的工作的性质驱动。
常见方法是使用工作流来实现需要补偿的最终一致操作。 原始操作进行期间,系统会记录每个步骤以及如何可撤销相应步骤执行的操作的相关信息。补偿事务也是最终一致操作,并且也可能会失败。 系统应能够在失败时恢复补偿事务,然后继续。 可能需要重复已失败的步骤,因此补偿事务中的步骤应定义为幂等命令。
某些情况下,除非手动干预,否则可能无法恢复已失败的步骤。 这类情况下,系统应会发出警报,并会提供尽可能多的有关失败原因的信息。