欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

如何保证分布式系统的一致性
(last modified Feb 18, 2024, 10:04 PM )
by
侧边栏壁纸
  • 累计撰写 176 篇文章
  • 累计创建 61 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

如何保证分布式系统的一致性

橙序员
2024-01-01 / 0 评论 / 0 点赞 / 218 阅读 / 2,691 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

分布式环境中,由于数据分布在不同节点上和可能出现的网络故障、节点故障等问题,传统的单一数据库事务的ACID属性在分布式系统中难以保证。分布式事务主要解决一致性、原子性、隔离性和持久性问题。分布式事务通过一致性协议来确保一组操作要么全部成功,要么全部失败,保持数据的一致性。为确保一组操作的原子性,需要采用分布式事务协议如两阶段提交(2PC)或三阶段提交(3PC)。为保证各个事务之间的隔离性,分布式事务采用锁机制、版本控制等手段来实现。为保证持久性,分布式事务通过数据备份、数据复制等手段来保证一旦事务提交,其对数据库的改变是持久的。分布式事务通过全局事务或状态机来对分支事务进行编排,以保证分支事务的操作原子性。在CP系统中,分布式事务常见,以确保数据的强一致性。在AP系统中,对一致性要求相对较低,可能采用最终一致性或其他非事务性手段处理数据更新。存在不同的分布式事务协议,如二阶段提交(2PC)、三阶段提交(3PC)、TCC和SAGA模式等,根据不同的使用场景选择适合的协议。

在分布式环境中,由于数据分布在不同的节点上,同时有可能发生网络故障、节点故障等问题,传统的单一数据库事务的ACID属性在分布式系统中变得难以保证。分布式事务的引入主要解决以下问题:

  1. 一致性问题: 在分布式系统中,由于数据分布在不同节点上,可能导致不同节点之间的数据不一致。分布式事务通过一致性协议,确保一组操作要么全部成功,要么全部失败,从而维护数据的一致性。
  2. 原子性问题: 在分布式系统中,要保证一组操作的原子性,即要么全部执行成功,要么全部回滚,需要采用分布式事务协议,如两阶段提交(2PC)或三阶段提交(3PC)。
  3. 隔离性问题: 多个事务可能并发执行,而且在分布式环境中,需要保证各个事务之间的隔离性,防止相互干扰。分布式事务通过锁机制、版本控制等手段来实现隔离性。
  4. 持久性问题: 在分布式环境中,要确保一旦事务提交,其对数据库的改变是持久的,即使系统发生故障。分布式事务通过数据备份、数据复制等手段来保证持久性。

所谓分布式事务,即是为了管理各个子服务的分支事务,通过全局事务或者状态机的方式来对分支事务进行编排,以此来保证分支事务在操作上的原子性。而根据分支事务编排方式的不同,我们又将分布式事务分为不同的分布式事务协议。

在CP系统(强一致性系统)中,确实更强调一致性,即保证在分布式环境下的数据一致性。因此,分布式事务在CP系统中更常见,以确保数据的强一致性。

在AP系统(可用性优先系统)中,对一致性的要求相对较低,系统更注重保证可用性和分区容忍性。在这样的系统中,可能会采用一些放宽一致性要求的策略,例如最终一致性。这并不意味着完全不使用分布式事务,而是可能选择更轻量级、最终一致性的事务模型,或者采用其他非事务性的手段来处理数据更新。

二阶段提交-2PC

二阶段提交的命名是对于全局事务来讲的,全局事务只有准备和提交两个阶段。

准备阶段

协调者向所有参与者发送“准备提交”请求,等待参与者的响应。

分支事务执行实际的业务操作,但不提交事务。同时,将事务执行结果记录在本地日志中。

全局事务进入“准备提交”状态,等待参与者的执行完成的消息。

image-20240101155626256

执行阶段

执行阶段如果所有参与者都发送了提交完成的消息,全局事务进入“提交”状态,否则进入“回滚”状态。

提交阶段

如果所有参与者都发送了“同意提交”消息,协调者向所有参与者发送“提交”请求,等待参与者的确认。

协调者向所有分支事务发送“准备提交”请求,等待分支事务的响应。如果所有分支事务都成功,则协调者向所有分支事务发送“提交”请求。分支事务收到“提交”请求后,提交事务。

回滚阶段

如果有任何参与者发送了“否定提交”消息,或者在提交阶段发生超时或错误,协调者向所有参与者发送“回滚”请求。

如果任何分支事务在准备提交阶段发送“否定提交”消息,或者在提交阶段发生超时或错误,协调者向所有分支事务发送“回滚”请求,分支事务回滚

image-20240101160134555

三阶段提交-3PC

三阶段提交相比于二阶段提交,在分支事务上的交互并没有改变,只是全局事务增加了一个准备完成的阶段:

准备阶段

协调者向所有分支事务发送准备提交的请求。

全局事务进入“准备提交”状态,等待参与者的准备完成消息。

image-20240101160737733

准备完成阶段

分支事务在接收到准备提交请求后,执行实际的事务准备操作,并向协调者发送准备完成的消息。与2PC不同的是,在3PC中,准备完成的消息可能是“准备提交”或“中止”两者之一。

全局事务进入“准备完成”状态,等待参与者的最终执行完成消息。

image-20240101160927647

执行阶段

与2PC一样,也分为回滚阶段和提交阶段。如果所有参与者都发送了事务执行完成的消息,全局事务进入“提交”状态,否则进入“回滚”状态

回滚阶段

如果有任何分支事务在准备或提交阶段发生超时、错误或发送“中止”消息,协调者向所有分支事务发送“回滚”请求,分支事务回滚。

提交阶段

如果所有分支事务都成功,则协调者向所有分支事务发送“提交”请求,等待分支事务的确认。

如果所有分支事务确认提交,则事务提交;否则,协调者进入回滚阶段。

image-20240101161015632

尝试-确认-取消-TCC

TCC可以说也是2PC的一个变体,只不过全局事务的状态分为了尝试、确认和取消三个状态

尝试阶段

全局事务进入“尝试”状态,各分支事务执行尝试操作。

分支事务收到try请求后,尝试执行事务,保存执行的事务日志,但是不提交。

image-20240101161502847

确认/取消阶段

当分支事务全部尝试执行成功时,全局事务进入确认阶段;当分支事务部分尝试执行失败时,全局事务进入取消阶段

确认阶段

全局事务进入“确认提交”状态,各分支事务执行实际的事务提交操作。

取消阶段

全局事务进入“取消”状态,各分支事务执行事务回滚操作。

image-20240101161704619

SAGA模式

发起阶段

  • Saga的全局事务由一个或多个子事务(局部事务)组成。
  • 发起阶段由一个特定的子事务(起始事务)发起。

image-20240101162523555

执行阶段

  • 各个子事务按照定义的序列或图形执行,可能是串行或并行。
  • 每个子事务执行自己的操作,并可能引发其他子事务的执行。

image-20240101162615389

补偿阶段

  • 如果在执行阶段的任何点发生故障或全局事务需要回滚,将执行补偿操作。
  • 每个子事务都有对应的补偿操作,用于撤销执行阶段中的操作。

image-20240101162651907

不同协议的使用场景

总的来说,SAGA更使用在分支事务顺序执行的场景,而如果想要保证分支事务同时执行,则需要考虑2PC、3PC、TCC等模式

协议 使用场景 注意事项
两阶段提交(2PC) 需要强一致性的场景,全局事务的原子性是首要考虑的因素。 数据库间的事务操作,要求所有数据库要么都提交,要么都回滚。 小规模系统或对性能要求不是非常高的系统。 2PC可能存在的问题包括阻塞时间长、单点故障、网络分区时的不确定性等,因此在高性能和高可用性的要求下需要谨慎选择。
三阶段提交(3PC) 需要在全局决策期间减少阻塞时间的场景。 对于网络分区或协调者失效等情况,能够容忍一定不确定性的系统。 对性能和可用性有一定要求的系统。 3PC引入的准备完成阶段可以减少阻塞时间,但仍然可能存在一些不确定性,需要在具体场景中进行权衡。
TCC(Try-Confirm/Cancel)模式 需要灵活处理事务的先决条件和后置条件的场景。 需要实现自定义的Try、Confirm和Cancel操作,适用于复杂的业务逻辑。 TCC模式适用于对事务有更细粒度控制的场景,但实现相对复杂,需要考虑一致性、可靠性和性能等方面的问题。
Saga模式 需要支持长事务和异步补偿的场景。 业务逻辑需要分解为一系列顺序或并行的局部事务。 部分失败的场景,能够部分提交或部分回滚。 Saga模式更加灵活,适用于需要定制化的业务流程,但要注意处理并发和异步操作的复杂性。

大多数场景我们都是解决分支事务并发的原子性,这也就是为什么Seata使用基于二阶段提交的AT模式,而不是SAGA模式。

附:AT模式流程示意图:

image-20240101164948429

0

评论区