pbft流程深层分析和解释(转)
<1>pbft五阶段请求解释
Request pre-prepare prepare commit 执行并reply
(1)pre-prepare阶段:
主节点收到客户端请求,给请求编号,并发送pre-pre类型信息给其他从节点。
从1节点收到pre-pre类型信息,如果同意这个请求的编号,如果同意就进入prepare阶段
(2)Prepare阶段:
从1节点同意主节点请求的编号,将发送prepare类型消息给主节点和其他两个从节点。如果不发,表示不同意。
图:从1节点发prepare信息给其他节点
从1节点如果收到另外两个从节点都发出的同意主节点分配的编号的prepare类型的消息,则表示从1节点的状态为prepared,该节点会拥有一个prepared认证证书。
为了防止viewchange导致主节点给请求分配的编号失效,引入commit阶段。
(3)commit阶段
从1节点进入prepared状态后,将发送一条COMMIT类型信息给其它所有节点告诉他们它有一个prepared认证证书了。
图:从1节点发commit类型信息给其他节点
如果从1节点收到2f+1条commit信息,证明从1节点已经进入commited状态。
只通过这一个节点,我们就能认为客户端的请求在需要的节点中都到达了prepared状态,每一个需要的节点都同意了主节点分配的编号。当一个请求在某个节点中到达commited状态后,该请求就会被该节点执行。
问:为什么要有commit阶段?
答:commit阶段用来确保其他节点都已经收到足够多的信息来达成共识了。Commit阶段并没有像prepare阶段发送同意不同意请求,只检测有没有收到足够多的commit类型信息。
相当于是正常情况下,4个节点中,如果每个节点都同意了请求,并且收到另外三个节点的同意信息。
所以如果从1节点正常情况下达到了commited阶段,确保了实际收集的信息相当于是:
节点 收到同意编号数
主节点 4
从1 4
从2 4
从3 4
这时从1节点可以放心执行客户端的请求,写入新区块了,因为其他节点都已经收到足够多的信息来达成共识了。
如果从1节点达到了prepared阶段,实际每个节点收集到的信息可能是:
节点 收到同意编号数
主节点 2
从1 4
从2 1
从3 1
这时其他节点并不能确保已经收到足够多的同意信息,从数据验证的角度是不应该写入新区块的。这才是问题的关键。这时如果发生view change,会丢弃prepare阶段的请求。
问:如果在commit阶段view change,会导致达成不了共识吗?会导致之前的view下的请求编号丢失吗?
答:如果commit阶段viewchange,会保留之前commit阶段的请求,不会达成不了共识,也不会丢失请求编号。
解释:prepare阶段和commit阶段用来确保那些已经达到commit状态的请求即使在发生viewchange后在新的view里依然保持原有的序列不变,比如一开始在view 0中,共有req 0, req 1, req2三个请求依次进入了commit阶段,假设没有坏节点,那么这四个replicas即将要依次执行者三条请求并返回给Client。但这时主节点问题导致view change的发生,view 0 变成 view 1,在新的view里,原本的req 0, req1, req2三条请求的序列被保留,作数。那些处于pre-prepare和prepare阶段的请求在view change发生后,在新的view里都将被遗弃,不作数。
这个意思其实是:
如果每个节点都进入了commit阶段(这里要强调的是每个节点都进入这个commit阶段才算是整体进入了commit阶段),这时即使view change,也会保留之前的view里进入commit阶段的请求信息,view change会继续之前的commit阶段请求,不会再重新进入pre-prepare和prepare阶段。
问:为什么fabric0.6和1.0都要共识交易的顺序?0.6是pbft实现,1.0是order负责排序。每笔交易的顺序为什么需要共识?不能按照时间顺序存在一个队列里顺序执行就可以了吗?
答:考虑两种情况,有可能会导致每个节点收到的顺序不一样。
第一类:节点收到的顺序和单个客户端发起的顺序不一样
假如客户端发起请求的正确顺序:123
4个节点收到的顺序有可能是:
情况1
主节点:123
从节点1:123
从节点2:132
从节点3:123
情况2
主节点:132
从节点1:123
从节点2:123
从节点3:123
第二类:多个客户端同时发起请求,每个节点收到的顺序不一样的可能性增大
这样共识出来的结果,有可能未必是每个客户端的正确顺序。比如a发起请求1,b发起请求2. 1和2是有关系的。但是a到集群的时间很长,b到集群的时间很慢,导致集群收到的请求都是21,这样共识出来的结果是21,而不是实际应该的12,遇到这种情况,要有机制能判断是错误的,丢弃这样的请求,并返回错误信息。这种情况可以举个例子:
如果初始状态为a:10,b:0,c:0,a转b10元为请求1,b转c10元为请求2,正确请求顺序为12,如果集群达成共识的请求的为21,这样就会和正确请求顺序产生差异。丢弃2的请求。因为b这时并没有10元可以转给c。如果初始状态为a:10,b:10,c:0,集群达成共识的请求为21也可以正常执行。因为b最初已经有10元,可以转给c。请求之间有强依赖的另一例子就是特定物权的转移,因为那件物品只有一个,任意一方没有拥有这件物品时,是无法转给对方的。
而利用pbft算法,情况1和2都能共识出正确顺序结果应该为123。主节点为错误请求时,会导致view change变成情况1的情况,情况1能共识出123为大多数节点认可的结果。
扩展:
为什么不能直接用每个客户端的时间作为请求的排序,因为每个客户端的时间可以任意更改的,如果大家都更改到不一样的时间,这样的请求的顺序是错误的。如果去统一的时间戳服务去取时间,又会多了一个中心化节点。所以google spanner分布式数据库就在全球统一的时间戳服务这个点去入手解决一致性请求顺序的问题。
注:Google Spanner是个可扩展,多版本,全球分布式还支持同步复制的数据库。他是Google的第一个可以全球扩展并且支持外部一致的事务。Spanner能做到这些,离不开一个用GPS和原子钟实现的时间API。这个API能将数据中心之间的时间同步精确到10ms以内。因此有几个给力的功能:无锁读事务,原子schema修改,读历史数据无block。
<2>Checkpoint和高低水位:
分布式系统的复杂性在于要考虑到各种各样的意外和蓄意破坏,你要制定出一套有效的法律来约束这个系统里可能发生的一切行为,并没有完美的分布式系统存在。
当replica执行完请求时,需要把之前记录的该请求的信息清除掉。但是不能这样轻易的去清除,其中包含的prepared certificate可能会在后面用得上。所以要有种机制来保证何时可以清除。
其实很简单,每执行完一条请求,该节点会再一次发出广播,就是否可以清除信息在全网达成一致。更好的方案是,我们一连执行了K条请求,在第K条请求执行完时,向全网发起广播,告诉大家它已经将这K条执行完毕,要是大家反馈说这K条我们也执行完毕了,那就可以删除这K条的信息了,接下来再执行K条,完成后再发起一次广播,即每隔K条发起一次全网共识,这个概念叫checkpoint,每隔K条去征求一下大家的意见,要是获得了大多数的认同(a quorum certificate with 2 f + 1 CHECKPOINT messages (including itsown)),就形成了一个 stablecheckpoint(记录在第K条的编号),我们也说该replica拥有了一个stablecertificate就可以删除这K条请求的信息了(即删除k之前的请求)。
这是理想的情况,实际上当replica i向全网发出checkpoint共识后,其他节点可能并没有那么快也执行完这K条请求,所以replica i不会立即得到响应,它还要继续自己的步伐,那这个checkpoint在它那里就不是stable的。那这个步伐快的replica可能会越来越快,可能会把大家拉的越来越远,这时我们来看一下上面提到的高低水位的作用。对该replica来说,它的低水位h等于它上一个stable checkpoint的编号,高水位H=h+L,L是我们指定的数值,它一般是checkpoint周期K的常数倍(这个常数是比较小的,比如2倍),这样即使该replica步伐很快,它处理的请求编号达到高水位H后也得停一停自己的脚步,直到它的stable checkpoint发生变化,它才能继续向前。
注:主节点是坏的,它在给请求编号时故意选择了一个很大的编号,以至于超出了序号的范围,所以我们需要设置一个低水位(low water mark)h和高水位(high water mark)H,让主节点分配的编号在h和H之间,不能肆意分配。
例子:
假设低水位h为,0,高水位H为100,L为100.checkpoint为50,上个stablecheckpoint为150.表示集群每隔50个请求就全网共识下大家确认的请求的情况。
如果节点A已经确认到编号为250了,其他节点才确认到编号为180,则节点A需要等待。直到其他节点确认的编号大于200.于是使得stable checkpoint从150变成200后,节点A才能继续确认编号250以后的请求。
通信次数分析:
pbft算法:
本质需要两个大阶段,一个是准备,一个是确认。进入prepared阶段,需要n^2次 ,进入commited阶段也需要n^2次,所以总次数为2n^2,o(n)为 n^2。
优点:容错算法,如果主节点为作恶节点也能检查出来。
缺点:需要确认和通信的次数较多。
raft算法:
在选好主节点的情况下,其他从节点相当于是被动的复制,所以需要通信次数为n次即可。o(n)为 =n。
优点:容易理解,通信次数比较少。
缺点:如果主节点为作恶节点,无法检查出来。
注:n为节点数,一次通信包括请求和响应
pbft流程深层分析和解释(转)的更多相关文章
- Ecshop的购物流程代码分析详细说明
Ecshop的购物流程代码分析详细说明 (2012-07-30 10:41:12) 转载▼ 标签: 购物车 结算中心 商品价格 ecshop ecshop购物流程 杂谈 分类: ECSHOP研究院 同 ...
- ElasticSearch评分分析 explian 解释和一些查询理解
ElasticSearch评分分析 explian 解释和一些查询理解 按照es-ik分析器安装了ik分词器.创建索引:PUT /index_ik_test.索引包含2个字段:content和nick ...
- Openfire注册流程代码分析
Openfire注册流程代码分析 一.客户端/服务端注册用户流程 经过主机连接消息确认后,客户端共发送俩条XML完成注册过程.服务器返回两条XML. 注:IQ消息节点用于处理用户的注册.好友.分组.获 ...
- Linux Kernel文件系统写I/O流程代码分析(二)bdi_writeback
Linux Kernel文件系统写I/O流程代码分析(二)bdi_writeback 上一篇# Linux Kernel文件系统写I/O流程代码分析(一),我们看到Buffered IO,写操作写入到 ...
- Linux Kernel文件系统写I/O流程代码分析(一)
Linux Kernel文件系统写I/O流程代码分析(一) 在Linux VFS机制简析(二)这篇博客上介绍了struct address_space_operations里底层文件系统需要实现的操作 ...
- DB2 锁问题分析与解释
DB2 锁问题分析与解释 DB2 应用中常常会遇到锁超时与死锁现象,那么这样的现象产生的原因是什么呢.本文以试验的形式模拟锁等待.锁超时.死锁现象.并给出这些现象的根本原因. 试验环境: DB2 v9 ...
- Flink 源码解析 —— Standalone Session Cluster 启动流程深度分析之 Job Manager 启动
Job Manager 启动 https://t.zsxq.com/AurR3rN 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac ...
- Flink 源码解析 —— Standalone Session Cluster 启动流程深度分析之 Task Manager 启动
Task Manager 启动 https://t.zsxq.com/qjEUFau 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Ma ...
- [精] UBOOT2017+FIT 启动流程详尽分析
开发环境:Nanopi-neo-plus2 软件版本:uboot-2017 软件版本:linux-4.14 买这个板子有一段时间了,并没有全身心的投入在上面,有时间了的话就搞一搞, 这篇随笔算是对这个 ...
随机推荐
- 字符编码-ASCII,GB2312,GBK,GB18030
ASCII ASCII,GB2312,GBK,GB18030依次增加,向下兼容. 手机只需要支持GB2312 电脑中文windows只支持GBK 发展历程 如果你使用编译器是python2.0版本,默 ...
- [UE4]模拟网络延迟和丢包
进入游戏界面,按下键盘的“~”键,打开控制台界面,输入net会自动列出跟网络相关的命令 1.Net pktLag=,模拟延迟,单位是毫秒 2.Net PktLagVariance=300,在模拟延迟的 ...
- [UE4]枚举Enum和Switch Enum
- [UE4]更新UI的三种方式
一.函数绑定 二.属性绑定 只会列出匹配的数据类型. 三.事件驱动更新 啦啦啦啦啦 结论:函数和属性绑定的原理都是每帧都去调用绑定的函数/属性,效率比较低下,一般不推荐使用.事件驱动更新的效率最好,性 ...
- VMware虚拟机上配置nginx后,本机无法访问问题(转载)
转自:http://www.server110.com/nginx/201407/10794.html 把nginx装在CentOS上,用本机访问虚拟机的时候却出现了不能访问的问题,查了资料以后,原来 ...
- AMQP & JMS对比(转载)
AMQP & JMS对比 原文地址:https://blog.csdn.net/hpttlook/article/details/23391967 初次接触消息队列时,在网上搜索,总是会提到如 ...
- Webbrowser指定IE内核版本(更改注册表)
如果电脑上安装了IE8或者之后版本的IE浏览器,Webbrowser控件会使用IE7兼容模式来显示网页内容.解决方法是在注册表中为你的进程指定引用IE的版本号. 比如我的程序叫做a.exe 对于32位 ...
- IIS 禁止回收
在IIS中找到这个站点所用的程序池,点击“高级设置...” 在打开的列表中更改以下设置: 回收 ——固定时间间隔(分钟) 改为 0 ——虚拟/专用内存限制(KB) 改为 0 进程模型 ——闲置超时(分 ...
- Android轮询器,RxJava Interval;
基于RxJava实现轮询器,配合Retrofit处理网络请求轮询很好用,其它的一些轮询也都可以使用像Bannre图之类的: implementation 'io.reactivex.rxjava2:r ...
- CF235C Cyclical Quest(SAM)
/* 统计串的出现次数显然可以在自动机上匹配出来即可 但是每次都挨个匹配的话会时间爆炸 那么考虑我们把串复制一份, 然后一起在后缀自动机上跑, 当我们匹配长度大于该串长度的时候强行失配即可 可能会有旋 ...