1、基于xa的2pc、 3pc(数据库):2pc的问题:
- 执行阶段所有表的行全部被锁,有1个慢的全慢,
- 有1个rm挂了,tm接收不到回复,在超时之前所有的rm阻塞住
- commit通知下发时,中途tm挂了并且某个rm也挂了,后续的rm通知不到,数据不一致;
rm没有接收到,或者接收到之后没有执行成功,导致不一致
3pc的解决方案:最大差别-- rm自动提交,解除锁定
- 先有个canCommit的询问(不加锁),排除有单个rm过于慢的情况,避免少数rm阻塞多数
- 执行时有个超时的机制,rm不回复时tm直接设置状态为超时
- Tm是超时时,通知所有rm回滚,通知不到和rm接收到之后没有执行成功也会不一致,
- Rm也有个超时的机制,执行后超时接收不到commit,直接本地进行commit(可能导致不一致)
2、TCC:需要改造业务逻辑,手动实现 try的锁定的功能。对业务侵入很强。
3、saga:默认执行成功,在需要的时候,再回调cancel。已经提交的事务,不保证隔离性。
4、seata(数据库):对于update insert delete自动生成回滚的sql,需要时进行回滚,但是不保证数据的强一致性,回滚时会导致脏读(回滚和提交是2个本地的事务)
5、lcn(数据库,本质是3pc):发起方最后成功,触发各个阶段的真正提交。不会脏读,性能介于seata和2阶段之间。但是发起方挂了,会导致 数据不一致(可能性小,而且真的是这种情况,也算是可以接受)
- seata和lcn大致的实现思路是一致的,但是回滚的机制不一样。
- lcn是采取代理数据源的模式,再根据发起方执行本地事务的结果进行回滚或者提交
- seata采取的是根据undo_log日志表,进行逆向生成sql语句,来解决回滚
- lcn能够保证强一致性(避免读未提交,但是执行的阶段是锁表的),但可能发生死锁的现象
- seata能保证最终一致性,但可能造成脏读