读TiDB原理部分,知道其分布式事务是参考的Google percolator。而percolator是一种2PC的优化。

分布式事务解决的是什么问题呢?

假设一个场景,一个电商网站,用户在购买商品时,需要两步操作1)创建订单,2)扣减库存。我们通常希望这两步是事务的,要么同时成功,要么同时失败。如果订单创建成功,库存扣减失败,会导致超卖。如果订单创建失败但扣减了库存呢,会导致少卖。

怎么解决这个问题呢?

如果订单表和商品表在MySQL同一个逻辑DB里面,可以使用MySQL的单机事务来保证。

如果在不同DB呢?

一种折中的做法,分别在两张表上开事务A、B,两事务都执行完后,同时commit,我们将重要的事务放在前面commit;这样如果A事务失败,则AB同时回滚。但如果A成功commit,B失败,就存在数据不一致的问题。

上面我们让AB等待同时完成后提高,一定程度降低了这种不一致发生的概率。但不是个完善的解决方案。

下面介绍的2PC,为解决这个问题。

首先2PC中有一个协调者节点,多个参与者节点(不同的数据库表)。

【一】协调者协议流程如下:

1. 开启一个事务,写本地日志begin_transaction,进行wait状态

2. 向所有参与者节点发送prepare消息,并等待参与者节点对prepare消息的响应

a. 若任何一个节点返回vote-abort消息,则写本地日志global-abort,  行向所有参与者节点发送global-abort消息,进入ABORT状态

b.若收到所有参与者节点返回的vote-commit消息,本地日志写global-commit日志,并向所有参与者节点发送golobal-commit消息,进入COMMIT状态】

3.等待参与者节点的global-commit或global-abort消息的回复,若所有节点都回复,则写日志end_transication,并完成事务。

【二】参与者协议流程如下:

1.开启事物,写本地日志init,进入INIT状态

2.等待协调者的prepare消息

a.若可以进行本次事务,则写本地日志ready,进入READY状态,并向协调者节点发送vote-commit消息等待回复

b.若收到回复global-abort,写本地日志abort,进入ABORT状态,并向协调者节点发送回复

c.若收到global-commit消息,写本地日志commit,进入COMMIT状态,向协调者发送回复

3.若参与者无法进行本次事务

a.写本地日志abort,进入abort状态,并向协调节点发送vote-abort消息。可以对后序收到的global-abort消息进行响应

4.即使流程结束,但任何时候收到协调者发送的global-abort或global-commit消息,也发送一个相应的回复。

** 以上操作都是先写日志,再进行处理

接下来讨论一下异常处理:

【协调者节点宕机恢复】

先看一下协调节点几种可能日志记录:begin_transiaction, global-commit或global-abort, end_transication

协调者宕机恢复后,先让到事务其最新日志,若是begin_transiaction,表示协调者处于WAIT状态,此时或者已经发送过prepare消息,也可能没有发过。但可以确认,一定没有发送过global-commit或global-abort消息。此时只需要重发prepare消息,即使参与者已经收到并回复过prepare消息,此时只需重新发一条即可。不影响一致性。

如果日志中最后是global-commit或global-abort日志。说明宕机前处于COMMIT或ABORT状态,此时协调者只需向参与者再发一次global-commit或global-abort消息,继续2PC流程。

【参与者节点宕机恢复】

如果日志处于init状态,表示还未对本事务做出选择,继续等待prepare消息即可。

如果处于ready状态,说明已经收到了prepare消息,但是否已经做出回复 不消息可知;所以重发vote-commit消息即可。注意这里是发送的vote-commit而不是vote-abort,因为只有本次事务可以提交,才会到ready状态。

如果日志最后是commit或abort状态,则表示已经收到了global-commit或global-abort消息,但不能确定是否已经发送过了确认消息。这时候只需要等待新的 global-commit或global-abort消息,并进行回复即可。因为协调者节点会不断重发消息。

分布式系统中,错误一般分为两块,超时和其它错误,其中超时是最难处理的错误。接下来讨论超时的问题。

协议的异常,体现在等待消息的超时上面。

【一,协调者在WAIT状态超时】

一般有两种原因,1.协调者与某个参与者之间的网络断开。2.某个参与者宕机,这种超时,可以选择放弃整个事务。因为WAIT状态下,协调者一定未发送来global-abort或global-commit消息,因此只要向所有参与者发送global-abort停止事务就可以,不影响协议正确性。

【二,协调者在COMMIT或ABORT状态超时】

此时,等待参与者对global-commit或global-abort的响应消息超时。这种情况下协调者只能不断重发global-commit或global-abort消息,直到所有参与者都响应。

2PC对这种情况没有很好的容错,只能阻塞在这里不断重试。其中任何结点的超时,或者协调者本身的网络问题,都会导致2PC完成不了。

【三,参与者INIT状态超时】

此时还没收到prepare消息,直接abort即可。但可能导致原先可以提交的事务不能成功完成。

【三,参与者READY状态超时】

READY状态,代表参与者收到prepare消息,并回复了vote-commit消息。此时参与者不能再改变自己的选择,只能不断重发vote-commit,直到收到global-abort或global-commit消息,继续下面流程。这里可以对应到协调者不断重发global-commit或global-abort消息,同样没有很好的容错机制。整个流程阻塞在这里,对于参与者而言,协议状态处于未知,即不能提交本节点事务,也不能放弃本节点事务。(如果提交了,实际协调者发送了global-abort,则在本节点提交,其它节点未提交,导致数据不一致。如果放弃了,则实际协调者发送了global-commit,则本节点放弃,其它节点提交了,同样导致数据不一致。)

实际上,2PC的有很多缺点:

1)容错很差,以上超时分析可知。

2)性能很差,一次通信涉及到4次消息交互,慢节点对整个协议性能影响很大。

3)可用性差,协调者单点

2PC(Two Phase Commitment Protocol)原理的更多相关文章

  1. nginx phase handler的原理和选择

    nginx phase handler的原理和选择 PHASE HANDLER的种类 nginx在接收并解析完请求行.请求头之后.就会依次调用各个phase handler. phase handle ...

  2. 《大型网站系统与JAVA中间件实践》读书笔记-数据访问层

    数据访问层 5.1.2数据库垂直/水平拆分的困难 随着网站业务的快速发展,数据量和访问量不断上升,数据库的压力越来越大. 更换更好的硬件(Scale Up)是一种解决方案,而且在我们能付得起硬件费用并 ...

  3. zookeeper(2) zookeeper的核心原理

    zookeeper 的前世今生 分布式系统的很多难题,都是由于缺少协调机制造成的.在分布式协调这块做得比较好的,有 Google 的 Chubby 以及 Apache 的 Zookeeper. Goo ...

  4. Zookeeper核心原理

    Zookeeper 的核心原理 Zookeeper 的由来 各个节点的数据一致性 怎么保证任务只在一个节点执行 如果orderserver1挂了,其他节点如何发现并接替 存在共享资源,互斥性.安全性 ...

  5. 分布式事务中的2PC和3PC

    分布式事务 分布式事务是指会涉及到操作多个数据库的事务.其实就是将对同一库事务的概念扩大到了对多个库的事务. 分布式事务中需要注意的是分布式系统中存在的一致性问题: CAP原则:在一个分布式系统中,C ...

  6. mysql小白系列_01 原理

    1.什么是MVCC?有什么作用? Multi-Version Concurrency Conrol 多版本并发控为解决数据库并发读写可能会出现不一致数据的情况,需要实现数据库的并发访问控制,写时复制产 ...

  7. 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法

    搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...

  8. 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)

    在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...

  9. MSSQL-并发控制-1-Transaction

         MSSQL并发控制原先打算分为两个部分写:隔离级别及锁,写的过程中,发现需要提及下事务的相关内容,故加多一篇博文,共3篇.         如果转载,请注明博文来源: www.cnblogs ...

随机推荐

  1. python----数据驱动@ddt.file_data结合yaml文件的使用

    一.创建yaml文件1. 安装yaml模块 pip install pyyaml2. 新建yaml文件 右键任意文件夹-->New-->File,输入文件名并以.yaml或.yml结尾 二 ...

  2. No X11 DISPLAY variable was set

    在命令行调用图形化界面时报错 “No X11 DISPLAY variable was set” 首先使用xclock命令查看是否能调出时钟,如果不行,使用如下命令: 打开xmanager – pas ...

  3. linux图像界面连接-xdm

    有两种方法可以激活 --:修改/etc/gdm/custom.conf文件在 [security]字段下增加AllowRemoteRoot=true [xdmcp]字段下增加Enable=true - ...

  4. Java内存溢出优化性能优化

    高性能应用构成了现代网络的支柱.LinkedIn有许多内部高吞吐量服务来满足每秒数千次的用户请求.要优化用户体验,低延迟地响应这些请求非常重要. 比如说,用户经常用到的一个功能是了解动态信息——不断更 ...

  5. js中时间戳与日期格式的相互转换

    1. 将时间戳转换成日期格式: function timestampToTime(timestamp) { var date = new Date(timestamp * 1000);//时间戳为10 ...

  6. 修改create-react-app支持多入口

    使用Facebook官方脚手架create-react-app创建React应用,默认只能生成一个SPA,入口是index.html.虽然,SPA的页面切换可以使用前台路由框架方便(比如React-R ...

  7. 常用类-API文档-Integer

    package IntegerTest;import java.util.Base64.Decoder; public class test01 { /** * 包装类的基本数据类型 * int =& ...

  8. Tensorflow实战系列之二:

    还没想好,可能是人脸检测或者物体检测,或者加上动态检测~~

  9. ecplise导入项目报错而文件不报错

    第一步 确认项目的jdk和tomcat版本,在Java Build Path的Libraries中查看包是否有报错,按照本机环境进行配置 第二步 检查 Java Compiler中的jdk版本,和ec ...

  10. tensorFlow入门实践(三)初识AlexNet实现结构

    参考黄文坚<TensorFlow实战>一书,完成AlexNet的整体实现并展望其训练和预测过程. import tensorflow as tf batch_size = 32 num_b ...