2pc事务和3pc事务区别详解
2pc也叫2段式事务
3pc也叫3 段式事务
网上资料一大堆,基本都没说清楚区别在哪里。
先说 2 段式 :
第一阶段: 就是 执行 sql ,但是 没有提交,并且 各自执行到 可以提交(事务没提交)的 时候,会告诉 协调者 ,自己已经可以提交了。
第二阶段:如果全部的本地事务都 告诉写条者 以后,如果全都 都可以提交,那么就执行提交,如果有一个不 能提交,那就全部回滚。
问题:
同步阻塞:第一阶段第二阶段 是同一个事务,提交之前都锁定资源,而且还要等待别人 一起提交, 锁定的比较久,但是这个 问题 3阶段也会有。不依赖 3pc 也会有事务的超时回滚时间。
单点故障:指的是 单协调节点故障,所有分布式事务都没办法提交了。( 我觉得也不存在, 大不了吧 协调者上做个高可用( 比如 LCN 事务的 TM ) )
2pc:只有一次投票,就是在提交之前,这次投票结果如果 是 全通过,那么久通知每一个事务 提交,通知 事务提交的这个过程,可能有的事务节点没收到。然后他就阻塞,等到超时,然后回滚,数据就不一致了。
3pc:
3pc 使用超时机制( 值得一提的是 数据库事务贝莱就有超时机制 ),并且 吧2pc 的 第一个阶段分成了2 个(也可以理解成 commit 分成了2 次确认)。
3pc: 有2 次投票
第一次:can 阶段,如果 投票权通过,会 通知 所有节点进入 pre 阶段,同理通知的过程可能会失败,部分通知成功,部分失败, 然后 pre 阶段不会提交的 。没收到通知的 超时以后回滚(这个超不是数据库的超时,是3pc 的超时机制)。
协调者没有收到所有的相应(没收到消息的那个肯定没有相应了) ,那么 协调者 再次通知所有的 取消。一起回滚,数据一致。如果都不出问题。都正常相应 pre完成。
第二次:上面 都都相应以后,如果都是 yes ,那么久进入 commit 阶段。如果部分失败,那么 依旧 通知所有节点事务回滚。
commit阶段:能有协调者收到 都是 yes,注意,这时候只有协调至知道应该commit,别的节点都处于告诉 协调者 pre阶段 自己同意了( 类似2pc 的 commit的通知 分成2 次确认,理解为已经收到一次了, ),如果在收到 第二次,那立即提交。
重点来了,如果 第二次确认收不到,但是收到过一次 pre 的确认,第二次因为网络或者协调者 通知了部分节点,自己挂了,那么超时 以后也会提交。
在说活 preCommit 阶段敢了啥 ?
其实它啥都没干,有些文章说这个谢了 undo 和 redo 日志。这个 其实 写哪里无所无,如果写在 canCommit 我觉得更好,pre 阶段应该尽快完成,尽量少做事情,只做简单的2 次确认。2 次确认 我们认为是这正常的 提交, 一次确认 ,后 立即commit 给了回滚的余地 ,一次确认后如果超时然就自己提交而不是回滚,是从大概率上来说 保证数据的一致性。
分析:2pc 第一阶段以后---> 协调者收集 结果 ————》通知提交 ,在 通知提交的时候 可能 部分 没有通知到,部分提交了,导致数据不一致
3pc 第阶段----》协调者收集结果--->通知进入 pre------> 协调者收集结果------ > 通知提交 多了一次pre 在pre阶段可以回滚机会,并且在如果 通知 commit 阶段 部分 没有收到,也会 在超时也厚自己提交。 但是 超时自己提交也有问题,这时候 可能 协调者想发出的 是 取消事务的 通知。( pre 阶段 杀都没做,只是一个 预确认的过程,一般不会所以可以认为 基本不会 取消 )。 能出问题 只有一种情况 pre 取消,并且 commit 的时候 节点有超时。 这样算下来 概率 就比 commit 超时的概率小很多了。 这就是 3pc 解决的问题。
不管是 2pc 还是 3pc 都不能保证 100% 的 数据一致性。 2pc 要求协调者通知 commit 阶段 不会出问题。 3cp 要求 pre 取消的时候,协调者通知 commit 不会出问题。 2pc 和 3pc 都是一个事务锁定指定等提交。 锁定时间都长。 性能比较低。要求效率比较高的时候,都有一定限制。
和 TCC 事务相比,TCC 也是2 段式提交,但是 2 段 都2 个事务,3 个方法,效率比 2pc 和 3pc 高,TCC 也有自己的缺点,一个操作要写3 个方法。 2pc ,3pc 写起来就容易很多。
TX-lcn 的lcn 模式 其实就是 2pc 的 一个变种 , TX-lcn 的 TM 就是 协调者,并且 TM 支持 高可用,然后 如果 吧 协调信息写到 一个 TM共享的地方。 就能应对 协调者的单点故障了。
TCC 也不能100% 保证 数据一致性,TCC 要求 才 try 的阶段 冻结,预留资源然后提交事务,cancel 阶段 幂等的处理 预留冻结资源的回滚,comform 阶段 也要幂等,并且因为 前面 已经预留了资源,所以不做资源检查 ( 检查了也没用,如果检查了资源 不够,说明 try 写的有问题,是逻辑问题抛出异常 也没用 ),并且 理想的 认为 comform 只会执行成功。不会失败。 虽然有补偿机制( 如果 comform 保存,通过 切面日志 参数 重做一次 comform ),但是如果是 try 写错了,资源没留够重试 100 次都没用,如果是 网络,抢锁啥 的, 可以重试的时候完成。
所以TCC 一致性的 保证是 ,comform 不抛出异常,并且正常执行( 理论上 留了 资源 就应该正常执行 逻辑错误带了 的数据不一致,任何一致性框架都解决不了, 比如 传统事务 张三 减100 ,李四你加了 200,逻辑写错了不是框架能决定的 )。
posted on 2020-03-19 17:51 zhangyukun 阅读(2755) 评论(0) 编辑 收藏 举报