🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 二阶段提交(基于xa协议的2pc) 基于xa协议的二阶段提交方案(mysql5.7以上支持) 由一个**事务管理器(TM全局事务管理) 和RM 资源管理器** 组成,分为**预提交阶段和提交执行阶段** * TM: Transaction Manager **事务管理器** (全局事务管理):作为**协调者**,负责各个本地资源的提交和回滚 * RM: Resource Manager **资源管理器** (数据库、服务) : 是分布式事务的**参与者**, 通常由数据库实现 **预提交阶段:**事务管理器向每个资源管理器发送准备消息,所有参与者都会执行请求中的事务操作,只记录日志信息但不提交,并将能否成功的信息反馈给事务管理器 **提交执行阶段:**事务管理器根据准备阶段的反馈结果向每个资源管理器发送消息,资源管理器执行**提交或者回滚操作** ### 优点 利用数据库本身的事务,提高了数据强一致性的概率,实现成本较低 ### 缺点 1. 单点问题: 事务管理器唯一, 整个系统都处于停滞状态。 2. 同步阻塞效率低: 准备阶段会把资源占用并阻塞,性能差 3. 数据不一致: 第二阶段如果有某个资源管理器失败,是无法自动回滚的,会出现数据不一致。 ## TCC事务 事务补偿 核心思想是:针对每个操作,都要注册一个与其**对应的确认和补偿**(撤销)操作。 **try阶段:**尝试去执行,完成所有业务的一致性检查,预留必须的业务资源。 **Confirm阶段:**该阶段对业务进行确认提交,不做任何检查,因为try阶段已经检查过了,默认Confirm阶段是不会出错的。若Confirm阶段真的出错了,需引入重试机制或人工处理。 **Cancel 阶段:**若业务执行失败,则进入该阶段,它会释放try阶段占用的所有业务资源,并回滚Confirm阶段执行的所有操作。 TCC 分布式事务模型包括三部分:**主业务服务、从业务服务、业务活动管理器**。 * 主业务服务:主业务服务负责发起并完成整个业务活动。 * 从业务服务:从业务服务是整个业务活动的参与方,实现Try、Confirm、Cancel操作,供主业务服务调用。 * 业务活动管理器:业务活动管理器管理控制整个业务活动,包括记录事务状态,调用从业务服务的 Confirm 操作,调用从业务服务的 Cancel 操作等。 ### 优点 * 业务活动管理器也可以做集群,不像xa的事务管理器是单点 * 没有像xa里准备阶段阻塞资源的问题,效率相对较高 ### 缺点 * 相当于把数据库的事务使用业务代码的形式进行开发,应用侵入性强,开发成本高 ## Tcc详细介绍 下面再拿用户下单购买礼物作为例子来模拟TCC实现分布式事务的过程: 假设用户A余额为100金币,拥有的礼物为5朵。A花了10个金币,下订单,购买10朵玫瑰。余额、订单、礼物都在不同数据库。 ### TCC的Try阶段: * 生成一条订单记录,订单状态为待确认。 * 将用户A的账户金币中余额更新为90,冻结金币为10(预留业务资源) * 将用户的礼物数量为5,预增加数量为10。 * Try成功之后,便进入Confirm阶段 * Try过程发生任何异常,均进入Cancel阶段 ### TCC的Confirm阶段: * 订单状态更新为已支付 * 更新用户余额为90,可冻结为0 * 用户礼物数量更新为15,预增加为0 * Confirm过程发生任何异常,均进入Cancel阶段 * Confirm过程执行成功,则该事务结束 ### TCC的Cancel阶段: * 修改订单状态为已取消 * 更新用户余额回100 * 更新用户礼物数量为5 ## Xa和tcc区别 都是强一致性 XA是数据库(资源)层面的分布式事务,在两阶段提交的整个过程中,一直会持有资源的锁。 TCC是业务层面的分布式事务,不会一直持有资源的锁。 ## 基于分布式消息的最终一致性方案 将需要分布式处理的事务通过消息或者日志的方式异步执行,消息或日志可以存到本地文件、数据库或消息队列中,再通过业务规则进行失败重试。 1.A系统先发送消息到mq,如果这个prepared消息发送失败那么就直接取消操作别执行了 2.如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚消息 3.如果发送了确认消息,那么此时B系统会接收到确认消息,然后执行本地的事务 4.mq会自动定时轮询所有消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认消息?那是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,别确认消息发送失败了。 5.这个方案里,要是系统B的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如B系统本地回滚后,想办法通知系统A也回滚;或者是发送报警由人工来手工回滚和补偿