本文作者:旺德,阿里云数据库高级开发工程师

事务的概念在这篇文章中描述过,在分布式系统中,读写位于多个节点的数据,如果依旧想保证ACID特性,就必须实现分布式事务。而其实现关键则是适当的提交协议,目前最简洁,且使用最广泛的无疑是两阶段提交协议(2PC)。

1.实现分布式事务关键组件

单机系统通过事务管理器(transaction manager,TM)实现本地事务。分布式系统中,需要协调多个节点的事务管理器,共同提交成功或失败,因此需要事务协调者(transaction coordinator,TC)。一个分布式事务管理器,可以粗略地划分为这两个子系统。这两个子系统根据自己在事务执行中扮演的角色,也可称之为参与者协调者

本地事务管理器负责本机事务并发控制和异常恢复等功能,事务协调者负责开启事务,将事务划分为多个子事务分发到相应的节点执行,并协调事务完成(一起提交成功或失败)。在实现中,TM和TC可以实现在同一个进程中,也可以部署在不同的节点。

2.经典两阶段提交协议

两阶段提交的流程比较简单。当分布式事务T执行完成,即事务执行的各节点都告知协调者TC,事务已经执行完成,TC便开启两阶段提交流程。

Phase 1 Prepare:1.TC写本地日志,并持久化。TC向所有参与者发送Prepare T消息。

2.各参与者TM收到Prepare T消息,根据自身情况,决定是否提交事务。

  • 如果决定提交,TM写日志并持久化,向TC发送Ready T消息。
  • 如果决定不提交,TM写日志并持久化,向TC发送Abort T消息,本地也进入事务abort流程。

Phase 2 Commit :1.当TC收到所有节点的回应,或者等待超时,决定事务commit或abort。

  • 如果所有参与者回应Ready T,则TC先写日志并持久化,再向所有参与者发送Commit T消息。
  • 如果收到至少一个参与者Abort T回应,或者在超时时间内有参与者未回应,则TC先写日志,再向所有参与者发送Abort T消息。

2.参与者收到TC的消息后,写或日志并持久化。

两阶段提交协议可以保证分布式事务执行的一个关键点:参与者在向协调者发生Ready T消息前,随时都可以自己决定是否abort,一旦这个消息发送,那么这个事务就进入ready状态,commit和abort完全由协调者控制。Ready T消息本质上是参与者向协调者发送的一个郑重的、不可逆的承诺。为了保证这一个承诺,参与者需要在发送Ready T消息前将所有必要的信息持久化,否则如果参与者在发送Ready T后异常宕机,重启后可能无法遵守以上承诺。在第二阶段,当协调者写了或日志,整个事务的命运就被决定了,不会再发生变化了。

为了优化2PC性能,减少关键路径的持久化和RPC次数是关键,一种对经典2PC的优化思路如下:

协调者无状态,不再持久化日志,但是为了方便宕机重启后恢复事务状态,需要向每个参与者发送事务的参与者名单并持久化。这样即使协调者宕机,参与者也可以方便地询问其他参与者事务状态了。该思路相当于参与者在协调者宕机时,自己担当起协调者询问事务状态的任务。

只要所有参与者prepare成功,事务一定会成功提交。因此为了减少提交延时,协调者可以在收到所有参与者prepare成功后就返回客户端成功,但如此,读请求可能会因为提交未完成而等待,从而增大读请求的延时。反过来,如果协调者确认所有参与者都提交成功才返回客户端成功,提交延时比较长,但会减少读请求延时。

3.两阶段提交协议异常处理

两阶段提交协议的正常流程较为简单,但它还需要考虑分布式系统中各种异常问题(节点失败,网络分区等)。

1.如果协调者检测到参与者失败:

  • 如果参与者在发送Ready T前失败,则协调者认为该节点事务Abort,并开始abort流程。
  • 如果参与者在发送Ready T后失败,证明参与者本地事务已经持久化,协调者忽视参与者失败,继续事务流程。

2.如果参与者在事务提交过程中失败,其恢复过程,需要根据参与者日志内容,决定本地事务状态。

  • 如果日志中包含日志,证明事务已经成功提交,REDO(T)。
  • 如果日志中包含日志,证明事务已经失败,UNDO(T)。
  • 如果日志中包含日志,参与者P需向其它节点咨询当前事务状态。
  • 如果协调者正常,则向告知参与者P,事务已经commit或是abort,参与者依此REDO(T)或UNDO(T)。
  • 如果协调者异常,则向其它参与者询问事务状态。
  • 如果其他参与者收到信息,并已知事务是commit还是abort状态,需回复参与者P事务状态。
  • 如果所有的参与者现在都不知道该事务的状态(事务上下文销毁了,或者自己也处于未决状态),那么该事务处于暂时既不能commit也不能abort。需要定期向其它节点问询事务状态,直到得到答案。(这是2PC最不想遇到的一个场景)
  • 如果日志中不包含上述几种日志,说明该参与者在向协调者发送Ready T消息前就失败了。由于协调者没有收到参与者的回应,会超时Abort,因此该参与者在恢复过程中,遇到这种情况也需要abort。

3.如果协调者在事务提交过程中失败。参与者需要根据全局事务状态(通过与其它参与者通信)决定本地行为。

(事务状态已经形成决议:)

  • 如果至少有一个参与者中事务T已经提交(参与者包含日志),说明T必须要提交。
  • 如果至少有一个参与者中事务T已经Abort(参与者包含日志),说明T必须要Abort。

(事务状态未形成决议:)

  • 如果至少有一个参与者没有进入Ready状态(参与者不包含日志)。说明全局还未就提交与否达成协议。有两种选择:(1)等待协调者恢复。(2)参与者自行abort。为了减少资源占用时间,选择后者居多。
  • 如果所有参与者都进入了Ready状态,且都没有或日志(事实上,即使有这些日志,查日志也是一种比较费的操作,还需要考虑日志回收的问题),这种情况下,参与者谁都不知道现在事务的状态,只能死等协调者恢复。(又到了这个最不想遇到的场景)

当参与者均进入ready状态,等待协调者的下一步指令,协调者在这个时候出现异常,那么参与者将一直持有系统资源,如果基于锁实现的并发控制,还会一直持有锁,导致其他事务等待。这种情况如果持续较旧,会对系统产生巨大的影响。因此2PC最大的问题就是协调者失败,可能会导致事务阻塞,未决事务的最终状态,只能等待协调者恢复后才确定。同时在这种情况下,参与者宕机重启,回放到这类未决事务,也会因为死等而block recovery流程。

4.缓解2PC blocking思路

三阶段提交是两阶段提交的延伸,目的是解决2PC block的问题,但是也引入了其它问题。它的解决方式是为参与者引入timeout机制,如果参与者成功PreCommit后,一直收不到协调者最后的DoCommit请求,等待超时自动提交,显然这样会引入一致性问题,例如,协调者收到一个参与者PreCommit失败,打算发abort请求给其它参与者时宕机,显然此时该分布式事务应该失败,但一些参与者可能因为超时而提交。

为了解决这个问题,3PC多引进了一个阶段,就是第一个阶段CanCommit阶段,协调者询问所有参与者是否可以提交,参与者如果状态正常,就会回应可以提交,但此时并不会占用任何系统资源。如果协调者及时收到了所有参与者ok的回应,便会认为各个参与者正常,之后的提交应该不会失败。但是实质上,仍有小概率失败的可能:某参与者PreCommit失败后,协调者和参与者都宕机,其它参与者超时自动提交,产生不一致。

因此3PC还有一个关键优化是协调者宕机后,迅速找到一个继任者,继续未完的流程,尽量保证不会出现参与者超时提交的现象。但是如果出现诸如网络分区等异常,新的协调者联系不上参与者,还是会产生一致性问题。

3PC通过牺牲一定的C(onsistency)来提高A(vailability),并且增加了网络开销,这些都是OLTP系统很难接受的,所以基本没有系统会采用。

但是协调者高可用,确实可以使block的时间大幅减少,基于诸如Paxos/Raft的一致性协议的高可用方案,可以让多个节点就commit/abort达成一致后,再去通知参与者,当协调者出现异常,可以迅速选出新的协调者,推进事务至完成。

与基础事务管理器的通信失败 存货申请_干货必读!细说分布式事务两阶段提交...相关推荐

  1. 与基础事务管理器的通信失败 存货申请_图文并茂讲解分布式事务的实现原理...

    事务是数据库系统中非常有趣也非常重要的概念,它是数据库管理系统执行过程中的一个逻辑单元,它能够保证一个事务中的所有操作要么全部执行,要么全不执行:在 SOA 与微服务架构大行其道的今天,在分布式的多个 ...

  2. 与基础事务管理器的通信失败 存货申请_金九银十跳槽季,恶补分布式事务

    随着微服务架构在各个企业的渗透,大家都在纷纷的将技术架构转型,从单体式应用变成微服务架构式,从单机部署变分布式部署,我们的应用也变成了分布式应用.在分布式应用中,一切就变得复杂了,如何保障数据的一致性 ...

  3. 关于TransactionScope出错:“与基础事务管理器的通信失败”的解决方法

    异常信息: System.Transactions.TransactionManagerCommunicationException: 与基础事务管理器的通信失败. ---> System.Ru ...

  4. 【转】关于TransactionScope出错:“与基础事务管理器的通信失败”的解决方法

    异常信息: System.Transactions.TransactionManagerCommunicationException: 与基础事务管理器的通信失败. ---> System.Ru ...

  5. 已禁用对分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具启用 DTC 以便在 MSDTC 安全配置中进行网络访问。...

    [记得server 跟 client 机器都要这样配置] 已禁用对分布式事务管理器(MSDTC)的网络访问.请使用组件服务管理工具启用 DTC 以便在 MSDTC 安全配置中进行网络访问. 已禁用对分 ...

  6. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究[转]

    1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...

  7. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规 ...

  8. 关于分布式事务 两阶段提交 一阶段提交 Best Efforts 1PC模式和事务补偿机制的研究

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规 ...

  9. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究...

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规 ...

最新文章

  1. docker安装Zabbix
  2. 现代浏览器的工作原理
  3. Linux的内存理解
  4. android 反色 java_Android小米,魅族6.0状态栏不能反色解决方法
  5. [转]“UPA 中国”北京行业聚会笔录
  6. steelray project viewer
  7. android EditText获取光标位置并安插字符删除字符
  8. SpringBoot2.1.5(3)----开发第一个应用
  9. app能不能跳转外部h5_利用条件编译在app端使用h5+(网页跳转 实例)
  10. 有些人,理他就输了!
  11. java unicode编码转换中文_Java实现 中文转换成Unicode编码 和 Unicode编码转换成中文...
  12. 天气实况、天气预报、免费天气接口、空气质量各类天气数据、生活指数、气候数据雷达云图等值面...
  13. 如何使用PDF转换器将PDF转换成图片
  14. 工作学习总结-angular中的安全导航符?.和ts中的非空断言操作符!.
  15. WUST-CTF2020(武汉科技大学第一届WUST-CTF网络安全竞赛)WP
  16. P3755 [CQOI2017]老C的任务
  17. 智能井盖被纳入《城市综合管廊运营服务规范》国标,喜大普奔
  18. MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC
  19. lisp语言绘制路灯_LISP语言在AD道路设计方案中各种应用
  20. 【MATLAB】绘制阶梯图、枝干图

热门文章

  1. Activity简介
  2. Digits of Factorial LightOJ - 1045(数学题?)
  3. hdu1202解题报告
  4. MySQL 四种链接
  5. 深入理解l内核v4l2框架之video for linux 2(转载)
  6. C++ 类的成员函数指针 ( function/bind )
  7. ajax 在php中一个运用
  8. oracle、sqlserver创建表、删除表、创建索引的sql
  9. jenkins:集成sonar代码扫描+发送邮件
  10. 深入css布局 (3)完结 — margin问题与格式化上下文