分布式事务及解决方案

分布式事务

指事务的参与者, 支持事务的服务器, 资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上. 为了保证不同数据库的数据一致性

强一致性

任何一次读都能读到某个数据的最近一次写的数据. 在任意时刻, 所有节点中的数据是一致的

弱一致性

数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到

最终一致性

不保证在任意时刻任意时间点上的同一份数据都是相同的,但随着时间迁移, 不同节点上的同一份数据总是在向趋同的方向编号, 在一段时间后, 节点间的数据最终会达到一致状态

CAP

一致性 C

在分布式系统中的所有数据备份, 在同一时间访问的数据相同

可用性 A

在集群中部分节点故障后,集群整体是否还能响应客户端的请求, 是否具有高可用性

分区容错性 P

系统如果不能再时限内达成数据一致性, 就意味着发送了分区情况, 需要在 CA之间做出选择

总结

要么 CP, 要么 AP, 如果在分布式系统中数据无副本, 那么系统必然满足强一致性条件,因为只有一份数据,不会出现数据不一致情况. 如果发生了网络分区或者宕机情况,必然导致某些数据不可访问, 此时可用性条件就无法满足

BASE 理论

指基本可用, 软状态, 最终一致性
核心思想是即便无法做到强一致性, 也应该采用适合的方式保证最终一致性

柔性事物

在分布式场景下基于 BASE 理论的事务, 用来达到最终一致性. 需要依赖一些特性, 在今天的方案中不一定都要满足. 单都不满足就不可能做柔性事务

幂等操作

指任意多次执行所产生的结果均与执行一次的结果相同.

分布式事务解决方案

两阶段提交 (2PC)

分两步提交. 存在一个辅助协调各个本地资源管理器的事务管理器.
本地资源管理器一般由数据库实现. 事务管理器在第一阶段的时候询问各个资源是否都就绪, 如果受到每个资源的回复都是 yes, 则在第二阶段提交事务, 如果其中任意一个资源回复的是 no, 则回滚事务

在这里插入图片描述

在这里插入图片描述

大致流程

第一阶段 : 事务管理器向所有本地资源管理器发起请求, 询问是否是就绪状态, 所有参与者都将本事务能否成功的信息反馈给协调者

第二阶段 : 事务管理器根据所有本地资源管理器的反馈,通知所有本地资源管理器, 步调一致的在所有分支上提交或者回滚

存在问题

  • 同步阻塞 : 当参与者与事务者存在占用公共资源的情况下,其他事务参与者只能阻塞等待资源释放
  • 单点故障: 一旦事务管理器出现故障, 整个系统就不可用
  • 数据不一致: 在二阶段, 如果事务管理器只发送了部分提交信息,此时网络异常, 那么只有部分参与者接收到提交消息,导致系统数据不一致
  • 不确定性: 当事务管理器发送提交消息之后, 并且此时只有一个参与者收到了提交消息,那么当该参与者与事务管理器同时宕机之后, 重新选举的事务管理器无法确定该条消息是否提交成功

三阶段提交 (3PC)

在事务管理器和参与者中都引入超时机制, 并把两阶段提交协议的第一阶段分成了两步, 询问, 然后在锁定资源, 最后提交

在这里插入图片描述

大致流程

第一阶段 : 协调者想参与者发送提交请求, 参与者如果可以提交就返回 Yes响应 否则返回 No响应

第二阶段: 如果响应 Yes, 协调者发送预提交请求并进入预备状态, 参与者接收到预提交请求后,会执行事务操作, 并将 undo 和 redo信息记录到事务日志中. 如果参与者成功执行事务操作后,返回 ACK 响应, 等待最终指令
如果有一个参与者响应 No 或者等待超时之后, 那么就发送执行事务的中断的请求

第三阶段: 进行真正的事务提交, 协调者没有接收到参与者发送的ACK 响应(可能没有发送或者响应超时),就进行中断事务.

存在问题

相对应 2PC , 三阶段主要解决单点故障问题, 减少阻塞, 因为有超时机制,默认执行提交操作, 不会一直处于阻塞状态. 但也会导致数据一致性问题. 网络原因, 协调者发送的中断请求没有及时响应或者被参与者接收到, 那么参与者在超时等待后的自动执行提交操作, 这样就会与接收到中断事务的参与者之间存在数据不一致的情况

二阶段和三阶段提交都无法彻底解决分布式数据一致性问题

TCC (Try Confirm Cancel)

大致流程

Try 阶段: 尝试执行, 完成所有业务检查, 锁定必须业务资源

Confirm 阶段: 确认执行真正执行业务, 不做任何业务检查, 只是用 Try 阶段锁定的业务资源, Confirm 操作满足幂等性. 失败后需要进行重试

Cancel 阶段: 取消执行, 释放 Try 阶段锁定的业务资源, 处理幂等性操作和异常处理方案

相比 2PC 解决的问题

  • 解决了协调者单点问题. 由主业务放发起并完成这个业务,管理器引入集群
  • 同步阻塞: 引入超时, 超时后进行补偿, 不会锁定整个资源
  • 数据一致性, 有了补偿机制

存在问题

基于 TCC 分布式事务, 会将原来只需要一个接口就可以实现的逻辑拆分为 Try, Confirm, Cancel 三个接口, 代码实现复杂度较高

本地消息表

大致流程

在这里插入图片描述

  1. 当系统A被其他系统调用发生数据库表更改操作时, 首先会更新数据库的业务表, 其次会往相同数据库的消息表中插入一条数据, 在同一个事物中发生
  2. 系统A通过定时任务将消息表中的消息发送至mq, 带确认消息发送给消费方后再将消息删除
  3. 系统B消费 mq 中的消息, 处理业务逻辑, 如果本地事物处理失败, 会继续在 mq 中的消息进行重试, 如果业务上的失败, 可以通知系统A进行回滚操作

实现条件

  • 消费者与生产者的接口都要支持幂等性
  • 生产者需要额外的创建消息表
  • 需要提供补偿逻辑, 如果消费者业务失败, 需要生产者支持回滚操作

容错机制

  • 步骤 1 失败时, 事务直接回滚
  • 步骤 2, 3 写入 消费mq 失败时会进行重试
  • 步骤 3 业务失败系统 B 向系统 A 发送事务回滚操作

可靠消息最终一致性 (只有 RocketMQ 实现)

大致流程

在这里插入图片描述

  1. A系统先向 mq 发送一条 prepare消息, 如果发送失败, 则直接取消操作
  2. 如果消息发送成功, 则执行本地事物
  3. MQ 会定期轮询所有 prepare 消息调用系统A提供的接口查询消息的处理情况. 如果该prepare消息本地事物处理成功, 则重新发送 confirm 消息, 否则直接回滚该消息
  4. B系统定期消费MQ中的 confirm 消息, 执行本地事物,并发送 ACK 消息, 如果 B 系统中的本地事物失败, 会一直不断重试, 如果业务失败, 则向A系统发起回滚请求

与本地消息表区别

去掉了本地消息表, 其次本地消息表依赖消息表重试写入 MQ 这一步改为由 MQ轮询 prepare 消息状态来重试或者回滚

尽最大努力通知

最简单的一种柔性事务, 适用于以下最终一致性时间敏感度低的业务, 且被动方处理结果不影响主动方的处理结果

大致流程

  1. 系统A本地事物执行完之后, 发送这个消息到MQ
  2. 此处有专门消费MQ的服务, 并调用系统B的接口
  3. 要是系统B执行成功就OK, 如果执行失败了,那么最大努力通知服务就定时尝试重新调用系统B接口,达到指定次数后就放弃
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值