分布式技术栈1.3–基础理论之常见几种补偿提交事务模型

引言

补偿提交是实现分布式最终一致性的一种思想。常见的方案有TCC、本地消息表、Sagas模型等。

1 TCC模型

1.1 原理介绍

TCC模型是典型的补偿模型之一,即Try、Confirm、Cancel,共有两步:第一步是尝试;第二步是确认/取消。该模型分为参与者调用者,参与者可以理解为例如分布式存储中的数据节点;调用者是分布式事务的发起者。

1.1.1 尝试阶段

尝试阶段的过程如下:

  • 调用者向所有参与者发起尝试操作请求,并等待各个参与者的响应;
  • 参与者接收到调用者的尝试操作请求后执行资源预留,例如要将张三的钱转100给李四,那么张三就执行冻结100的请求;
  • 参与者执行操作成功,给协同者成功响应;反之,返回失败响应。例如张三冻结100成功返回成功响应,反之,返回失败;

1.1.2 确认/取消阶段

如果尝试阶段,调用者等待某个参与者响应超时 或 至少一个参与者返回失败,那么就会执行取消操作;反之,所有参与者返回成功,则执行确认操作

取消操作

  • 调用者向所有的参与者发起取消请求,并等待各个参与者的响应;
  • 参与者接收到调用者的取消请求,进行取消资源预留。例如张三的钱转100给李四的场景,会撤销对张三的100元冻结;
  • 参与者返回调用者取消完毕;
  • 调用者接收到所有参与者返回,中断事务。特别地,若参与者返回超时,调用者会重新发起取消请求,所以取消请求需要具备幂等性

确认操作

  • 调用者向所有的参与者发起确认请求,并等待各个参与者的响应;
  • 参与者接收到调用者的确认请求,进行正式资源操作。例如张三的钱转100给李四的场景,会将张三的余额减100并删除冻结记录,同时,该过程需要具备幂等性,所以操作前要判断对应的冻结记录是否存在,不存在就不进行扣钱。所有操作是一个本地事务来确保一致性;
  • 参与者返回调用者确认完毕;
  • 调用者接收到所有参与者返回,完成事务。特别地,若参与者返回超时,调用者会重新发起确认请求,所以确认请求需要具备幂等性

1.2 优缺点总结

1.2.1 优点

  • 由于参与者的确认/取消具备幂等性。网络中断、异常时,可重试达到最终一致性;
  • 整个过程相对简单、对业务透明。适用于像电商之类对一致性高要求的业务场景;

1.2.1 缺点

  • 所有参与者的确认/取消必须具备幂等性。有一定业务的局限;
  • 当调用者在Try后崩溃,需要通过人工手段去恢复资源的预留。

2 本地消息表

2.1 原理介绍

在介绍本地消息表原理前,先简介下普通的消息中间件功能。普通的消息中间件,发送和消费消息由六步组成,如下:
在这里插入图片描述

  • 首先消息生产方发送消息给MQ;
  • MQ将消息持久化到存储系统;
  • MQ返回ACK给生产方;
  • MQ 将消息推给对应的消费方,然后等待消费方返回ACK。若超时将继续推送消息并等待;
  • 消费方返回ACK给MQ;
  • 消费方在指定时间内成功返回ACK,MQ在存储中删除消息;

通过对普通消息中间件的过程分析,不难看出普通的消息中间件是无法做到生产方和消费方的一致性问题。例如电商系统的订单处理成功,消息存储成功,但是MQ处理超时,从而ACK确认失败,导致发送方本地事务回滚;但是消费方却收到了消息进行了下一个处理流程。
本地消息表一样分为生成方消费方,结合本地数据库的事务机制加消息中间件确保一致性。

2.1.1 生产方

生产方在业务数据库中添加一张消息数据表。发送消息步骤如下:

  • 在业务数据库中依次执行业务操作、添加消息数据。消息数据共有待发送、待确认、已发送三个状态,此时为待发送状态。整个过程为一个数据库事务确保原子性;
  • 生产方有后台定时任务,会定时检索出待发送和待确认的消息,然后发送到MQ中并将消息改为待确认状态;
  • 生产方接收到MQ的ACK消息,就会将消息数据的状态设置为已发送状态,或者将消息删除。

2.1.2 消费方

消费方比较简单,按照普通消息中间件的消费者一样消费消息。消费方需要确保消息处理业务的幂等性。此外,消息方如果处理失败,可以基于本地消息表发起回滚消息到生产方,也可以人工修改。

2.2 优缺点总结

2.2.1 优点

  • 相对简单的一种实现方式,避免了分布式事务,实现了最终一致性。

2.2.1 缺点

  • 消息表耦合到业务中,相对通用的事务框架有很多额外的开发工作。

3 Sagas模型

3.1 原理介绍

Saga模型又叫做长时间运行事务。核心思想为:

  • 拆分分布式系统中的长事务为多个子事务,最终拆分成多个节点的本地事务;
  • 然后有序串行依次执行拆分后的子事务;
  • 当所有子事务成功,那么长事务完成。否则,反向依次回滚已经完成的子事务。

注1:在本地事务的传递过程中可以借助本地消息表实现子事务的传递可靠性;
注2:在反向撤销事务过程中,采用补偿机制实现最终一致性地撤销本地事务;

3.2 优缺点总结

3.2.1 优点

  • 无须全局锁住所有节点,事务并发高;

3.2.1 缺点

  • 事务传递和回滚需要业务具备幂等性;
  • 若正在处理的事务节点宕机,会出现事务无法继续传递也无法回退;
  • 无中心节点,监控事务执行的中间状态;

猜你喜欢

转载自blog.csdn.net/fs3296/article/details/105694320