最终一致性的保障方法

331 阅读5分钟

背景

在分布式事务场景中,事务的参与者、支持事务的服务器、资源服务器以及事务管理器通常会位于分布式系统的不同节点上,例如在下单场景,库存和叮当如果不在同一个节点上,就涉及到分布式事务。因此为了保证分布式事务流程的有效进行,通过获取本地消息来实现事务的最终一致性,其中,本地消息是将分布式事务拆成一系列本地事务,通过定时轮询的方式,检查数据库中的本地消息,当发现新数据时,则通知对方。在高并发场景下,频繁的定时轮询操作,对数据库吞吐量和性能有较高的要求,同时也会导致数据库处理效率降低。

常规解决方法:

两阶段提交:

通过引入协调者来协调参与者的行为,并最终决定这些参与者是否要真正执行事务,包括阶段一:开始向事务涉及到的全部资源发送提交前信息。此时,事务涉及到的资源还有最后一次机会来异常结束事务。如果任意一个资源决定异常结束事务,则整个事务取消,不会进行资源的更新。否则,事务将正常执行,除非发生灾难性的失败。为了防止会发生灾难性的失败,所有资源的更新都会写入到日志中。这些日志是永久性的,因此,这些日志会幸免于难 并且在失败之后可以重新对所有资源进行更新。阶段二:只在阶段一没有异常结束的时候才会发生。此时,所有能被定位和单独控制的资源管理器都将开始执行真正的数据更新。在分布式事务两阶段提交协议中,有一个主事务管理器负责充当分布式事务协调器的角色。 事务协调器负责整个事务并使之与网络中的其他事务管理器协同工作。为了实现分布式事 务,必须使用一种协议在分布式事务的各个参与者之间传递事务上下文信息,IIOP便是这 种协议。这就要求不同开发商开发的事务参与者必须支持一种标准协议,才能实现分布式 的事务。

最终一致性:不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。也可以简单的理解为在 一段时间后,节点间的数据会最终达到一致状态。

存在问题

  • 同步阻塞 所有的事务参与者在等待其它参与者相应的时候都处于同步阻塞状态,无法进行其它操作
  • 单点问题 协调者在这两个阶段中起到非常大的作用,发生故障将会造成很大影响,特别是在阶段二,所有参与者会一直等待状态, 无法完成其他操作。
  • 数据不一致,在阶段二,如果协调者只发送了部分commit消息,此时网络发生异常,那么只有部分参与者接收到commit消息,也就是说只有部分参与者了提交了事务,使得系统数据不一致。
  • 容错性差,任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

补偿事务:

采用补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:1)try阶段主要是对业务系统做检测及资源预留;2)confirm阶段主要是对业务系统做确认提交,try阶段执行成功并开始执行 confirm阶段时,默认confirm阶段是不会出错的。即:只要try成功,confirm一定成功。3) cancel阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。例如,假设甲要向乙转账,思路大概是:我们有一个本地方法,里面依次调用。首先在try阶段,要先调用远程接口把甲和乙的钱给冻结起来。然后在confirm阶段,执行远程调用的转账操 作,转账成功进行解冻。最后,如果第二步执行成功,那么转账成功,如果第二步执行失败, 则调用远程冻结接口对应的解决方法。存在的问题是第二步和第三步都有可能失败,补偿 事务属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用事务补偿不太好定义处理。

强一致性事务处理方案,该方案进行实施需按照事务确认模型的提交、确认、回滚三个步骤分别编写相应业务逻辑处理。 存在对业务代码侵入度高,开发复杂度高这些问题, 抽象度较低导致代码复用度不高,每次开发需要将部分代码重复编写一次。 运行可靠性较低,每一个事件 的执行需要所有的事件节点全部执行成功才能提交成功,对分布式系统意外宕机、网络波 动导致的服务断联容错率较低。

方式一

在高并发场景下分布式事务最终一致性有两种应用场景 一种是同步场景一种是异步场景。

同步

在同步场景下出现异常,一种处理方法就是确定确定所发生的异常类型和对应的回滚操作。

异步

在异步场景下出现异常,确保异步调用场景中的幂等性和重试机制。