0%

分布式事务-面试宝典

CAP理论

CAP理论

  • 一致性:在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性,等同于所有节点访问同一份最新的数据副本。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
  • 可用性:每次请求都能获取到正确的响应,但是不保证获取的数据为最新数据。
  • 分区容错性:分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。

CAP 理论是一个已经经过证实的理论,指出在一个分布式系统中最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

BASE理论

Base理论

  • 基本可用:在分布式系统出现故障,允许损失部分可用性(服务降级、页面降级)。
  • 软状态:允许分布式系统出现中间状态。而且中间状态不影响系统的可用性。这里的中间状态是指不同的 data replication(数据备份节点)之间的数据更新可以出现延时的最终一致性。
  • 最终一致性:data replications 经过一段时间达到一致性。

BASE 理论是对 CAP 中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致性(CAP的一致性就是强一致性),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

分布式事务什么场景会产生?

  • 单体项目多数据源情况下(跨数据库实例产生分布式事务)
  • soa架构和微服务架构下(跨服务产生分布式事务)

分布式事务相关协议有哪些?

  • 2PC:分为两个阶段,准备阶段、提交阶段
  • 3PC:分为三个阶段,准备阶段、预提交阶段、提交阶段

描述下2PC

2PC处理流程

2PC,两阶段性提交协议:

  • 准备阶段(Prepare phase):事务协调者给每个事务参与者发送Prepare消息,每个参与者在本地执行事务操作,但在执行完成后不会提交本地事务,而是先向协调者反馈事务能否处理成功。
  • 提交阶段(commit phase):事务协调者根据反馈消息,选择回滚事物或提交事物。如果事务协调者接受到事务参与者执行失败或超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Conmmit)消息

2PC存在的问题:

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

描述下3PC

3PC处理流程

3PC,三阶段性提交协议,是基于2PC的,添加了一个阶段,并添加超时机制和:

  • 准备阶段(CanCommit):事务协调者询问事务参与者是否可以完成事务,在此阶段只是询问,防止某些事务参与者不可用情况下导致所有事务参与者都阻塞(不执行事务操作)。
  • 预提交阶段(PreCommit):在准备阶段所有的事务参与者都返回可以执行操作时,事务协调者要求每个事务参与者预提交此操作,并反馈是否可以提交。(执行事务操作,但不提交,只是反馈是否可以成功提交)
  • 提交阶段(DoCommit):事务协调者根据反馈消息,选择回滚事物或提交事物。如果每个事务参与者在预提交阶段返回准备成功,那么进行提交事。否则,进行回滚事物,释放资源。
  • 超时机制:如果在预提交阶段超时,则中断事务,事务回滚;如果提交阶段超时,则事务参与者提交事物。

3PC优点:

  • 降低了阻塞范围,在等待超时后协调者或参与者会中断事务
  • 避免了协调者单点问题,阶段3中协调者出现问题时,参与者会继续提交事务。

3PC缺点:数据不一致问题依然存在,即在参与者收到PreCommit请求后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。

描述下2PC与3PC,它们的区别有哪些?

增加了一个询问阶段,询问阶段可以确保尽可能早的发现无法执行操作而需要中止的行为,但是它并不能发现所有的这种行为,只会减少这种情况的发生在准备阶段以后,协调者和参与者执行的任务中都增加了超时,一旦超时,协调者和参与者都继续提交事务,默认为成功,这也是根据概率统计上超时后默认成功的正确性最大。

三阶段提交协议与两阶段提交协议相比,具有如上的优点,但是一旦发生超时,系统仍然会发生不一致,只不过这种情况很少见罢了,好处就是至少不会阻塞导致永远锁定资源。

描述下TCC

TCC处理流程图

TCC 是业务层面的分布式事务,分为三个阶段:

  • Try阶段:是做业务检查以及资源预留(锁定)。此阶段仅是一个初步操作,需要和后续的Confirm阶段一起才能真正构成一个完整的业务逻辑。
  • Confirm阶段:是做确认提交。Try阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用TCC则 认为 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的出错了,需引入重试机制或人工处理。Confirm阶段需要保证幂等性。
  • Cancel阶段:是做资源释放。Try阶段执行错误,取消执行Confirm阶段,调用Cancel阶段把Try阶段的操作撤销(回滚)了。通常情况下,Cancel阶段也是一定成功的。若Cancel阶段真的出错了,需引入重试机制或人工处理。Cancel阶段需要保证幂等性。

TCC和2PC/3PC很像,不过TCC的事务控制都是业务代码层面的,而2PC/3PC则是资源层面的。

TCC又可以被称为两阶段补偿事务,第一阶段try只是预留资源,第二阶段要明确的告诉服务提供者,这个资源你到底要不要,对应第二阶段的confirm/cancel,用来清除第一阶段的影响,所以叫补偿型事务。

分布式事务解决方案有哪些?

  • XA:传统数据库实现的2PC
  • 补偿机制TCC:补偿机制,是业务层面的分布式事务,可以认为是个2阶段性补偿事务
  • 本地消息表:异步确保最终一致性
  • 消息事务:基于MQ实现最终一致性
  • 最大努力通知性:也是基于MQ实现最终一致性

Seata

Seata模块组件

Seata模块组件
Seata 中有三大模块,分别是 TM、RM 和 TC。

  • TC (Transaction Coordinator):事务协调者;它是独立的中间件,需要独立部署运行。它维护全局和分支事务的状态,驱动全局事务提交或回滚。
  • TM (Transaction Manager):事务管理器;定义全局事务的范围:开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager):资源管理器;管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

Seata执行流程
在 Seata 中,分布式事务的执行流程:

  • TM 开启分布式事务(TM 向 TC 注册全局事务记录);
  • 按业务场景,编排数据库、服务等事务内资源(RM 向 TC 汇报资源准备状态 );
  • TM 结束分布式事务,事务一阶段结束(TM 通知 TC 提交/回滚分布式事务);
  • TC 汇总事务信息,决定分布式事务是提交还是回滚;
  • TC 通知所有 RM 提交/回滚 资源,事务二阶段结束。

AT模式

AT模式是两阶段提交协议(2PC)的演变:

  • 阶段1:将业务数据和回滚日志记录在同一个本地事务提交,释放本地锁和连接资源(不阻塞)
  • 阶段2:
    • 分支事务全部完成,触发全局提交,不需要同步协调处理(只需要异步清除回滚日志)
    • 分支事务发来回滚请求,触发全局回滚,RM通过回滚日志完成分支事务的回滚。

AT模式主要流程:

  • TM请求TC,开启一个全局事务,全局事务创建成功并生成唯一的XID
  • RM向TC注册事务分支,并且执行本地事务逻辑,TC将事务分支纳入XID对应全局事务的管辖
  • XID通过服务调用链,传递到其他服务中(其他RM)
  • 当RM分支事务执行全部完成或有RM分支事务执行异常,TM向TC发起针对XID的全局事务提交或回滚
  • TC调度XID下管辖的全部RM分支事务完成提交或回滚请求。

核心概念:

  • 每个RM使用DataSourceProxy连接数据库,其目的是使用ConnectionProxy,使用数据源和数据连接代理的目 的就是在第一阶段将undo_log和业务数据放在一个本地事务提交,这样就保存了只要有业务操作就一定有 undo_log。
  • 在第一阶段undo_log中存放了数据修改前和修改后的值,为事务回滚作好准备,所以第一阶段完成就已经将分 支事务提交,也就释放了锁资源。
  • TM开启全局事务开始,将XID全局事务id放在事务上下文中,通过feign调用也将XID传入下游分支事务,每个 分支事务将自己的Branch ID分支事务ID与XID关联
  • 第二阶段全局事务提交,TC会通知各各分支参与者提交分支事务,在第一阶段就已经提交了分支事务,这里各 各参与者只需要删除undo_log即可,并且可以异步执行,第二阶段很快可以完成。
  • 第二阶段全局事务回滚,TC会通知各各分支参与者回滚分支事务,通过 XID 和 Branch ID 找到相应的回滚日 志,通过回滚日志生成反向的 SQL 并执行,以完成分支事务回滚到之前的状态,如果回滚失败则会重试回滚操作