1 2PC
- 两阶段提交协议。它引入了一个事务协调者角色,来管理各个参与者
- 请求提交阶段
- 协调器向所有参与者发送事务请求,询问是否可以执行事务,然后各个参与者响应Yes/No
- 提交阶段
- 协调器向所有参与者 发出提交指令, 参与者 提交失败/超时 则回滚
- 请求提交阶段
- 优点
- 利用数据库自身的功能进行本地事务的提交和回滚,也就是提交和回滚实际不需要我们实现。
- 如mysql XA规范实现。
- 利用数据库自身的功能进行本地事务的提交和回滚,也就是提交和回滚实际不需要我们实现。
- 不足
- 提交协议是阻塞协议,如果事务协调器宕机,某些参与者将无法解决他们的事务问题
- 同步阻塞
- 基于数据库实现会锁住资源。
- 不基于数据库实现,也可能要持数据库资源。
- 单点故障
- 事务协调者挂了,整个事务就执行不下去了。
- 如 参与者发生完准备命令之后挂了,每个本地资源都会处于锁定状态。
- 事务协调者挂了,整个事务就执行不下去了。
- 数据不一致问题
- 网络抖动,导致某些参与者无法收到协调者的请求,而某些收到了,导致数据不一致。
- 同步阻塞
- 提交协议是阻塞协议,如果事务协调器宕机,某些参与者将无法解决他们的事务问题
2 3PC
-
3PC 的引入是为了解决 2PC 同步阻塞和减少数据不一致的情况。 三阶段
- 提交请求阶段
- 预提交 都确认预提交,进入三阶段
- 提交 只要预提交成功, 则一定要保证 真实提交成功,即使协调器下一阶段不可用,一般是通过重试补偿的策略
-
不足
- 绝大部分情况下肯定是正常的,所以每次都多了一个交互阶段就很不划算
3 TCC
- TCC 就是一种业务层面或者是应用层的两阶段提交
- TCC 分为指代 Try、Confirm、Cancel 分为两个阶段
- 第一阶段 try 完成业务检查(一致性)、预留业务资源(准隔离性)。
- 第二阶段
- Confirm 不做任何业务检查,仅仅使用预留的资源执行业务操作,如果失败会一直重试
- Cancel 取消执行业务操作,释放预留的资源,如果失败会一直重试
- 一个事务的所有服务都需要提供这三个方法 可以根据表字段去设计
//尝试方法
function try(){
//记录日志
todo save A 转出了 100 元
todo save B 转入了 100 元
//执行转账
update amount set balacne = balacne-100 where id = 1
update amount set balacne = balacne+100 where id = 2
}
//确认方法
function confirm(){
//清理日志
clean save A 转出了 100 元
clean save B 转出了 100 元
}
//取消方法
function cancle(){
//加载日志
load log A
load log B
//退钱
update amount set balacne = balacne+100 where id = 1
update amount set balacne = balacne-100 where id = 2
}
- 特点
- 对代码的嵌入性高,要求每个业务需要写三种步骤的操作
- 对有无本地事务控制都可以支持使用面广
- 数据一致性控制几乎完全由开发者控制,对业务开发难度要求高
- 注意点
- 幂等问题,
- 网络超时,会重复调用参与方的 confirm/cancel 方法
- 异常事务的补偿执行 try 的重复执行。
- 空回滚问题
- try方法由于网络问题超时一直没有返回,事务管理器会发出Cancel命令 执行了cancel方法。
- 解决:事务表 try方法成功执行后,会插入一条记录,标记分支事务 init 状态 表示 try执行成功。
- cancel时 查询状态。
- 悬挂问题
- try方法由于网络问题超时,导致cancel先执行,然后再执行try方法。
- 解决:空回滚 插入一条条记录,标记分支事务 rollbacked 状态。
- try 开始执行的时候 首先尝试插入状态为 init 的分支事务
- 如果失败表示当前分支事务的记录已经存在,try无需执行。
- 幂等问题,
4 lcn 选取
- 支持 TCC,TXC,LCN 三种模式
- 协调控制流程
- image.png
- 三个角色, 发起方,参与方,txManager
- 发起方 调用 txManager 创建事务组
- 发起方 假如执行自己业务, 再调用参与方A,参与方A 执行自己事务,加入到事务组
- 参与方A 出现异常, 不需要加入事务组,发起方捕获异常,通知事务回滚。
- 发起方 知道 是提交事务还是回滚事务。 通知 txManager
- txManager 通知每个事务参与者,并且每个参与者都响应给了txManager
- txManager 响应给 发起方。
4.1 TXC 逆向sql
-
第一阶段 执行sql的时候, 拦截并解析,查询出要受影响的数据。记录下来
-
第二阶段
- 提交 将记录的数据删除
- 回滚 通过 记录的sql和影响的数据 创建逆向sql 并执行。
- 流程 image.png
-
特点
- 代码的嵌入性低
- 限于对支持SQL方式的模块支持
- 不会占用数据库的连接资源,但中间状态可见
4.2 Lcn模式
- 流程 image.png
-
特点
- 对代码的嵌入性为低。
- 仅限于本地存在连接对象且可通过连接对象控制事务的模块
- 事务提交与回滚是由本地事务方控制,对于数据一致性上有较高的保障
- 缺陷在于代理的连接需要随事务发起方一共释放连接,增加了连接占用的时间, 会锁住资源。
-
负载问题
- 如 A 服务分别掉B服务集群 one tow 方法。 当负载到不同的 实例 导致出现两个事务, 下面代码 行锁 锁住资源导致 资源占用 导致窒息失败而回滚事务。
void one(id){
execute => update demo set state = 1 where id = {id} ;
}
void two(id){
execute => update demo set state = 2 where id = {id} ;
}
4.3 lcn 对一些问题的解决。
1 超时机制
- 参与者 执行完业务,启动定时任务,到了时间 txManager 没有通知参与者
- 主动请求 txManager
- 成功 按响应结果 来回滚或者提交。
- 失败 事务补偿。
- 主动请求 txManager
2 补偿出现
-
自动补偿
-
手动补偿
-
场景
- 服务挂了
- 执行完事务挂了
- 没有执行事务挂了
- lcn 记录开始执行业务之前 事务信息。
- 服务挂了
-
记录发起方信息。
网友评论