分布式事务

1 2PC

  • 两阶段提交协议。它引入了一个事务协调者角色,来管理各个参与者
    • 请求提交阶段
      • 协调器向所有参与者发送事务请求,询问是否可以执行事务,然后各个参与者响应Yes或者No
    • 提交阶段
      • 基于第一阶段的投票结果进行决策
        • 当所有参与者同意提交,协调者才会通知各个参与者提交事务。
        • 否则协调者通知各个参与者取消事务。
      • 参与者接收到协调者发来的消息执行 本地commit或者 Rollback.
  • 优点
    • 利用数据库自身的功能进行本地事务的提交和回滚,也就是提交和回滚实际不需要我们实现。
      • 如mysql XA规范实现。
  • 不足
    • 提交协议是阻塞协议,如果事务协调器宕机,某些参与者将无法解决他们的事务问题
      • 同步阻塞
        • 基于数据库实现会锁住资源。
        • 不基于数据库实现,也可能要持数据库资源。
      • 单点故障
        • 事务协调者挂了,整个事务就执行不下去了。
          • 如 参与者发生完准备命令之后挂了,每个本地资源都会处于锁定状态。
      • 数据不一致问题
        • 网络抖动,导致某些参与者无法收到协调者的请求,而某些收到了,导致数据不一致。
  • XA 规范
    • 重做日志(redo log)
      • 每当有操作执行前,在数据真正更改前,会先把相关操作写入 redo 日志
    • 回滚日志(undo log)
      • 记录事务开始前数据的状态
    • 二进制日志(binlog)
      • 记录了所有的 DDL 和 DML 语句,除了数据查询语句 select、show 等,还包含语句所执行的消耗时间

2 3PC

  • 过程
    • 提交请求阶段
      • 协调器向所有参与者发送事务请求,询问是否可以CanCommit,然后各个参与者响应Yes或者No
    • 预提交
      • 协调者从所有参与者反馈都是Yes响应
        • 发送预提交请求
          • 向参与者发送预提交请求
        • 事务预提交
          • 参与者接收请求,会执行事务操作。
        • 响应反馈
          • 参与者成功执行了事务操作,返回Ack响应
      • 协调者从所有参与者反有一个No反应,或者超时
        • 发送中断请求
          • 协调者向所有参与者发送中断请求
        • 中断事务
          • 参与者收到中断请求,执行事务中断。
    • 提交( 只要预提交成功, 则一定要保证 真实提交成功,即使协调器下一阶段不可用,一般是通过重试补偿的策略)两种情况
      • 执行提交
        • 发送提交请求
          • 所有参与者返回Ack响应后,进入提交阶段,协调者向所有参与者发送提交请求。
          • 超时提交 如果参与者 超时没有收到提交请求,也进行提交。
        • 事务提交
          • 参与者接受到提交请求后,执行真正事务提交,完成事务释放资源。
        • 响应反馈
          • 事务提交后,参与者向协调者发送Ack响应。
        • 完成事务
          • 协调者接受到所有参与者Ack响应完成事务。
      • 中断事务
        • 协调者 预提交 没有收到参与者Ack 响应(非ack或者超市),执行中断。
  • 如何解决2pc同步阻塞问题
    • 协调者和参与者都引入了超时机制
  • 对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
      • 成功 按响应结果 来回滚或者提交。
      • 失败 事务补偿。
2 补偿出现
  • 自动补偿

  • 手动补偿

  • 场景

    • 服务挂了
      • 执行完事务挂了
      • 没有执行事务挂了
      • lcn 记录开始执行业务之前 事务信息。
  • 记录发起方信息。

5 基于消息补偿的最终一致性

  • 基于消息队列的最终一致性就是一种异步事务机制,在业务中广泛应用
  • 基于消息补偿的一致性主要有本地消息表和第三方可靠消息队列等
    • 本地消息表
      • 将分布式事务拆分成本地事务进行处理,通过消息日志的方式来异步执行
      • 本地消息表是一种业务耦合的设计
        • 消息生产方需要额外建一个事务消息表,并记录消息发送状态
        • 消息消费方需要处理这个消息,并完成自己的业务逻辑
        • 有一个异步机制来定期扫描未完成的消息,确保最终一致性
        • 两个系统通知 可以用zookeeper, 或者接口。
  • image.png
    • 如 下单服务与库存服务
      • 系统收到下单请求,订单业务存储订单库,并同时存储该订单对应的消息数据,放入同一个事务处理
      • 库存服务 通过消息中间件收到库存更新消息,调整库存业务,同时返回业务处理结果。
      • 订单服务收到处理结果后,将本地消息表的数据删除或者设置为完成。
      • 设置异步任务,定时扫描本地消息表,发现有未完成的任务重试,保证最终一致性。
  • 缺点
    • 依赖 数据库消息表。所以并发不能太大。

6 可靠消息最终一致性。

  • image.png

7 最大努力通知方案

  • 系统 A 本地事务执行完之后,发送个消息到 MQ;
  • 这里会有个专门消费 MQ 的最大努力通知服务,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口;
  • 是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。

8 你们公司是如何处理分布式事务的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容