当前位置:数据分析 > 什么是分布式事务以及解决方案是什么?

什么是分布式事务以及解决方案是什么?

  • 发布:2023-10-08 11:01

当单个数据库表的数据达到千万级时,就需要考虑分库分表,那么原来的一库就会变成多库。例如,如果一个操作同时操作01数据库和02数据库,并且必须保证数据的一致性,则必须使用分布式事务。 ​ 什么是分布式事务? 答:就是说一个大操作是由不同的小操作组成的。这些小操作分布在不同的服务器上。分布式事务需要保证这些小操作要么全部成功,要么全部失败。分布式事务本质上是为了保证不同数据库中数据的一致性。 是什么导致了分布式事务? 1 数据库分库和分表 当单个数据库表的数据达到千万级时,就需要考虑分库分表,那么原来的一库就会变成多库。例如,如果一个操作同时操作01数据库和02数据库,并且必须保证数据的一致性,则必须使用分布式事务。 2 应用SOA 所谓SOA就是面向服务的业务。例如,在电商平台下订单,会调用库存服务扣除库存,调用订单服务更新订单数据。然后设计订单数据库和库存数据库。为了保证数据的一致性,需要分布式事务。 总结:其实以上两种场景最终都是分布式事务,需要操作多个数据库并保证数据一致性。 分布式事务解决方案 1. 两阶段提交(2PC) XA是Tuxedo提出的分布式事务协议。 XA大致分为两部分:事务管理器和本地资源管理器。其中,本地资源管理器往往是通过数据库来实现的。例如Oracle、Mysql等数据库都实现了XA接口,事务管理器作为全局调度器,负责各个本地资源的提交和回滚。 XA实现分布式事务的原理如下: 总结 两阶段提交看起来确实能够提供原子操作,但是它有几个缺点: 同步阻塞问题:执行过程中,所有参与节点都是事务阻塞。当参与者占用公共资源时,其他第三方节点访问公共资源时必须被阻止。 单点故障:由于(事务管理器)协调器的重要性,一旦协调器发生故障。 (本地资源管理器)参与者将被永远阻止。尤其是在第二阶段,如果协调者发生故障,所有参与者仍然处于锁定事务资源的状态,无法继续完成事务操作。 (如果协调者挂了,可以重新选举一个协调者,但这并不能解决因为协调者挂掉而导致参与者被阻塞的问题)数据不一致:在两阶段提交的第二阶段,协调者向参与者发送commit请求时,本地网络异常或者协调者在发送commit请求的过程中出现故障,导致只有部分参与者收到提交请求。提交请求。这部分参与者收到提交请求后,就会执行提交操作。但其他未收到提交请求的机器无法进行事务提交。从而导致整个分布式系统出现数据不一致的情况。 第二阶段无法解决的问题:参与者发送commit消息后宕机,唯一收到消息的协调者也同时宕机。那么即使协调者通过选举协议产生了新的协调者,这个交易的状态也是不确定的,没有人知道这个交易是否已经提交。 2. 三阶段提交(3PC) 3PC实际上是在2PC的基础上增加了CanCommit阶段,它是2PC的一个变种,并引入了超时机制。一旦事务参与者未能收到协调者的提交请求,就会自动执行本地提交,相对有效地解决了协调者的单点故障问题。但性能和数据一致性问题并没有得到根本解决。 3PC分为三个阶段:CanCommit、PreCommit、DoCommit CanCommit阶段 这与2PC的准备阶段非常相似。协调者向参与者发送提交请求,参与者如果可以提交则返回 Yes 响应,否则返回 No 响应。 事务查询:协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的回应 响应反馈:参与者收到CanCommit请求后,正常情况下,如果认为交易可以顺利执行,就会返回Yes响应,并进入准备状态。否则返回否 预提交阶段 协调者根据参与者的响应来决定是否可以执行事务的PreCommit操作。根据响应,有两种可能性: 如果协调者收到所有参与者的“是”响应,则交易将被执行。 发送PreCommit请求:协调者向参与者发送PreCommit请求,进入Prepared阶段。 事务预提交:参与者收到PreCommit请求后,将执行事务操作,并将undo和redo信息记录到事务日志中。 响应反馈:如果参与者成功执行交易操作,则返回ACK响应,并开始等待最终指令。如果任何参与者向协调器发送“否”响应,或者等待超时,或者协调器没有收到参与者的响应,则事务将中断。 发送中止请求:协调者向所有参与者发送中止请求。 中断事务:参与者收到协调者的中止请求后(或者超时后,尚未收到协调者的请求),执行事务被中断。 提交阶段 实际的交易提交是在这个阶段进行的,也可以分为以下两种情况: 执行提交 发送提交请求:当协调者收到参与者发送的ACK响应时,将从预提交状态进入提交状态。并向所有参与者发送 doCommit 请求。 交易提交:参与者收到doCommit请求后,进行正式的交易提交,并在完成交易提交后释放所有交易资源。 响应反馈:事务提交后,向协调器发送ACK响应。 完成交易:协调者收到所有参与者的ACK响应后,交易完成。 中断事务 如果协调者没有收到参与者发送的ACK响应(接收者可能还没有发送ACK响应,或者响应可能已经超时),那么就会执行中断事务。 发送中止请求:协调者向所有参与者发送中止请求 事务回滚:参与者收到abort请求后,使用阶段2记录的undo信息执行事务回滚操作,并在回滚完成后释放所有事务资源。 反馈结果:参与者完成事务回滚后,向协调者发送ACK消息。 中断事务:协调者收到参与者反馈的ACK消息后,执行事务的中断。 示意图如下: 总结 与2PC相比,3PC为协调者和参与者都设置了超时机制,而2PC中只有协调者有超时机制。这个优化解决了参与者长时间无法与协调节点通信时无法释放资源的问题,因为参与者本身有超时机制,超时后会自动进行本地提交来释放资源。这种机制也减少了整个交易的阻塞时间和范围。但数据一致性问题依然没有解决,即参与者收到PreCommit请求后等待最终指令。如果此时协调者无法与参与者正常通信,参与者将继续提交交易,导致数据不一致。 3. 报酬事项(TCC) TCC(Try-Confirm-Cancel)也称为补偿交易。它其实和2PC、3PC是一样的,只是分布式事务的一种实现方案。它分为三个操作: 尝试阶段:主要测试业务系统,预留资源。 确认阶段:确认业务操作的执行。取消阶段:取消业务操作的执行。 TCC事务的处理流程与2PC两阶段提交类似,但2PC通常是在DB层面,而TCC本质上是应用层面的2PC,需要通过业务逻辑来实现。它的优点是允许应用程序定义数据库操作的粒度,减少锁冲突和提交吞吐量。 然而,它对应用程序的侵入性很大。业务逻辑的每个分支都需要实现try、confirm、cancel这三个操作。 TCC原理图如下: 4.消息事务+最终一致性 所谓消息事务,就是基于消息中间件的两阶段提交。它本质上是中间件的一种特殊用途。它将本地事务和消息发送放在分布式事务中,以保证要么本地操作成功,要么消息发送到外部。成功,或者都失败,开源的RocketMQ支持该功能,具体原理如下: 请按如下方式进行: 服务A向消息中间件发送初步消息。 消息中间件保存准备好的消息并返回成功。 服务 A 执行本地事务。 服务A向消息中间件发送提交消息,服务B收到消息后执行本地事务。 基于消息中间件的两阶段提交常用于高并发场景,将分布式事务拆分为消息事务(服务A的本地操作+消息发送)+服务B的本地操作,其中服务B的操作由messages驱动,只要消息交易成功,那么服务A一定成功,消息一定发送出去。此时服务B就会收到消息,进行本地操作。如果本地操作失败,消息将重新投递,直到服务B成功。这样就变相实现了A和B之间的分布式事务。 上述步骤可能会出现异常。现在我们来分析一下: 第1步出现错误:整个事务失败,服务A的本地操作不会被执行。 步骤2出现错误:整个事务失败,服务A的本地操作不会被执行。 步骤 3:错误:需要回滚初步消息。服务A实现了消息中间件的回调接口。消息中间件会不断执行回调接口来检查服务A的事务执行是否成功。如果失败,初步消息将被回滚。 第四步:错误:此时服务A本地事务成功,但消息中间件不需要回滚。事实上,通过回调接口,消息中间件可以检查服务A是否执行成功。此时,服务不需要发送提交消息。 ,消息中间件可以自行提交消息来完成整个消息事务。

相关文章

最新资讯