分布式事务种类介绍
一、2PC 二阶段提交
1.算法思路
参与者将本身事务的执行情况发送给事务协调者,由事务协调者判断事务调用链是否执行提交操作还是回滚操作
2.提交步骤
1.准备阶段
1.1 事务协调者向所有的事务参与者询问是否可以执行提交操作,并开始等待各事务参与者的执行回应!
1.2 事务参与者回应事务协调者的请求,并执行本地的事务日志操作,等待事务协调者的通知!
2.提交阶段
2.1 事务协调者收到参与者的失败消息或者超时消息,则通知所有事务参与者执行回滚操作!若全部成功则通知所有的事务参与者执行提交操作!
2.2 释放事务操作所占用的所有锁资源!
3.缺陷
- 阻塞问题
1.1 所有的事务操作都处于同步阻塞状态,即所有的是事务参与者都必须等待事务协调者的消息,收不到消息则处于持续阻塞状态!
- 单点故障
2.1 当事务协调者服务宕机活出现其他故障后,所有的事务都处于挂起阻塞状态!(虽然在协调者挂掉之后能够选举出新的协调者,但是他仍不能解决各参与者的锁定状态!)
3.数据不一致性
3.1 网络是不可靠的,当二阶段进行中,由事务协调者发送给参与者的事务操作信息,因为网络原因,部分事务参与者没有收到,则会出现,部分事务无法进行事务操作,从而造成事务的不一致性!
3.2 当事务协调者挂了,唯一接收这条消息的参与者也挂了!那么当新的协调者被选举出来之后,也无法知道事务是否已经进行操作!
二、3PC 三阶段提交
相对于二阶段提交,三阶段提交在一阶段和二阶段中增加了一步准备阶段,以确保事务在提交时,所有节点的状态是一致的!
1. canCommit阶段 询问阶段
这一阶段对比二阶段提交的第一阶段,即事务协调者去询问各事务参与者:“你们是否可以执行本次事务,即参与者对自身状态的检查”,若参与者能够执行则回应 YES反之NO。
2.preCommit阶段 预提交阶段
根据一阶段返回的状态信息 YES AND NO 此时事务协调者会想参与者发送预提交或预回滚请求。参与者收到后开始执行事务操作,想本地写入事务日志,但是不执行提交或回滚命令!操作完成后向协调者发送ACK命令,等待下一步指令!
3. DoCommit 提交阶段
当收到所有参与者都发送的ACK命令后,向参与者发送提交或回滚请求!
4. 相对二阶段提交所做的优化
相比较2PC而言,3PC对于协调者和参与者都设置了超时时间,而2PC只有协调者才拥有超时机制。
主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。
另外,通过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的。但是3PC依然没有完全解决数据不一致的问题。
三、补偿事务(TCC)
TCC(Try-Confirm-Cancel)又称补偿事务。其核心思想是:"针对每个操作都要注册一个与其对应的确认和补偿(撤销操作)"。它分为三个操作:
- Try阶段:主要是对业务系统做检测及资源预留。
- Confirm阶段:确认执行业务操作。
- Cancel阶段:取消执行业务操作。
1.Try: 尝试执行业务
• 完成所有业务检查(一致性) • 预留必须业务资源(准隔离性)
2.Confirm:确认执行业务
• 真正执行业务 • 不作任何业务检查 • 只使用Try阶段预留的业务资源 • Confirm操作要满足幂等性
3.Cancel: 取消执行业务
• 释放Try阶段预留的业务资源 • Cancel操作要满足幂等性
4.TCC与2PC协议比较
• 位于业务服务层而非资源层 • 没有单独的准备(Prepare)阶段, Try操作兼备资源操作与准备能力 • Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度) • 较高开发成本
5. 缺陷
tcc事务补偿性对业务代码的侵入性过高,开发成本大!需要开发人员在业务层手动提供提交操作以及混滚操作!所以对开发人员要求也比较高!