2PC(Two Phase Commitment Protocol)原理
读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)原理的更多相关文章
- nginx phase handler的原理和选择
nginx phase handler的原理和选择 PHASE HANDLER的种类 nginx在接收并解析完请求行.请求头之后.就会依次调用各个phase handler. phase handle ...
- 《大型网站系统与JAVA中间件实践》读书笔记-数据访问层
数据访问层 5.1.2数据库垂直/水平拆分的困难 随着网站业务的快速发展,数据量和访问量不断上升,数据库的压力越来越大. 更换更好的硬件(Scale Up)是一种解决方案,而且在我们能付得起硬件费用并 ...
- zookeeper(2) zookeeper的核心原理
zookeeper 的前世今生 分布式系统的很多难题,都是由于缺少协调机制造成的.在分布式协调这块做得比较好的,有 Google 的 Chubby 以及 Apache 的 Zookeeper. Goo ...
- Zookeeper核心原理
Zookeeper 的核心原理 Zookeeper 的由来 各个节点的数据一致性 怎么保证任务只在一个节点执行 如果orderserver1挂了,其他节点如何发现并接替 存在共享资源,互斥性.安全性 ...
- 分布式事务中的2PC和3PC
分布式事务 分布式事务是指会涉及到操作多个数据库的事务.其实就是将对同一库事务的概念扩大到了对多个库的事务. 分布式事务中需要注意的是分布式系统中存在的一致性问题: CAP原则:在一个分布式系统中,C ...
- mysql小白系列_01 原理
1.什么是MVCC?有什么作用? Multi-Version Concurrency Conrol 多版本并发控为解决数据库并发读写可能会出现不一致数据的情况,需要实现数据库的并发访问控制,写时复制产 ...
- 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法
搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...
- 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)
在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...
- MSSQL-并发控制-1-Transaction
MSSQL并发控制原先打算分为两个部分写:隔离级别及锁,写的过程中,发现需要提及下事务的相关内容,故加多一篇博文,共3篇. 如果转载,请注明博文来源: www.cnblogs ...
随机推荐
- element-ui <el-input> 注册keyup事件,即键盘enter.
<template> <!-- 需求:keyup事件一般用在input中,在input框中输入内容,用户点击键盘的enter,执行搜索 --> <div class=&q ...
- 探索 | “中医+AI”会诊电力设备故障
在 AlphaGo 成功挑战围棋世界冠军后,人工智能(AI)“深度学习”家喻户晓.电力企业有机会着眼自身战略,利用落地的 AI 技术和应用聚焦业务流程优化.效率提升以及对全新机遇的发掘.本文针对设备故 ...
- 开发部署项目时出现:java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: PermGen space 错误: 原文地址:http://www.cnblogs.com/shihujiang/archive/2012/06 ...
- 关于warning: suggest parentheses around assignment used as truth value [-Wparentheses]|的解决方法
今天,在调试的时候一直出现warning: suggest parentheses around assignment used as truth value 代码如下: if(startTime== ...
- riakKV 配置
安装好riakKV之后, 我们需要将 riak.conf 文件中的 nodename修改为本机的 IP 地址. nodename = xx@xxx.xxx.xx.xx listener.http.in ...
- Python-接口自动化(六)
接口基础知识(六) (七)接口 1.接口:外部系统与本系统之间以及系统内部的各个子系统间,以约定标准提供的服务,包括对外提供的接口/对外提供的接口. 不同的请求协议:http webservice ...
- java8中optional和.stream().map()
使用optional的好处:是一个可以包含或不可以包含非空值的容器对象,更加友好的处理程序中的空对象. Optional<T>有方法 isPresent() 和 get() 是用来检查其包 ...
- 网络拓扑_华三H3C的路由器+交换机
最近在弄公司网络,目前的拓扑图长这样:点击查看网络拓扑图 华三的路由器和交换机都可以通过Console口进行配置,如下: 用SecureCRT.或者putty.或者windows的超级终端,打开ser ...
- Android : Camera之CHI API
一.CAM CHI API功能介绍: CHI API建立在Google HAL3的灵活性基础之上,目的是将Camera2/HAL3接口分离出来用于使用相机功能,它是一个灵活的图像处理驱动程序(摄像头硬 ...
- Git实操
使用git首先要理解工作区(working).暂存区(stage或者index).和版本库(repo区),很多命令都是和这三个概念相关的. git init 初始化git仓库,会生成默认的.git文件 ...