PBFT共识算法

1 篇文章 0 订阅
1 篇文章 0 订阅

PBFT共识算法

概述
Practical Byzantine Fault Tolerance: PBFT,是联盟币的共识算法的基础。实现了在有限个节点的情况下的拜占庭问题,有3f+1的容错性,并同时保证一定的性能。

容错率
raft算法的的容错只支持容错故障节点,不支持容错作恶节点,所以容错率高,过半节点正常即可
PBFT算法可以容忍小于1/3个无效或者恶意节点
作恶节点:除了可以故意对集群的其它节点的请求无响应之外,还可以故意发送错误的数据,或者给不同的其它节点发送不同的数据,使整个集群的节点最终无法达成共识,这种节点就是作恶节点。
角色
Primary节点和普通节点,PBFT系统的Primary是轮流当选的,这和zab、raft不一样

主节点 p = v mod |R|
p:主节点编号
v:视图编号
|R|节点个数

Primary角色分析

Primary节点的作用:

正常工作时,接收客户端的事务请求,验证request身份后,为该请求设置编号,广播pre-prepare消息
新Primary当选时,根据自己收集的View-Change消息,发送View-New信息,让其它节点同步数据
Primary与所有的其它节点维系心跳
Primary节点地位和follower节点一样,并没有什么特权

1.如果Primary宕机,会因为心跳超时,而触发重新选举,保证系统运行稳定
2.如果Primary恶意发送错误编号的消息,那么会在后续的操作中,被follower察觉,因为 prepare和commit阶段都是会进行广播的,一旦不一致,view-change
3.如果Primary不发送接收到的request,client在超时未回复时,会重发request到所有的replica,小弟们发现primary竟然私藏消息,view-change
4.如果Primary节点篡改消息,因为有Request里面有data和client的签名,所以primary无法篡改消息,其它replica会先验证消息的合法性,否则丢弃,view-change
综上所述,限制了权限的Primary节点,如果宕机、或者不发生消息、或者发送错误编号的消息、或者篡改消息,都会被其它节点感知,并触发view-change。

PBFT工作正常的详细流程

客户端发起请求–>转发请求到primary–>primary生成proposal–>primary广播proposal–>所有节点复制proposal并广播–>复制过半节点完成–>广播commit节点–>commit过半节点完成–>应用状态机–>反馈客户端–>客户端统计f+1个反馈消息–>交易完成

1.系统根据机器编号顺序轮流选举出一个primary,primary初始化时发出View-new消息,同步所有节点的数据
2.Client发起请求转发给primary,primary验证通过后,广播这个请求,发起pre-prepare消息给所有的follower节点,并且自己也保存这个request
3.所有的follower收到pre-prepare消息后,第一步是进行校验,包括数据的顺序是否正确,操作的先后有序性,以及交易是否有效比如签名。(防止客户端造假或者primary节点篡改造假)
4.follower验证正确之后,写到自己的磁盘里,然后广播Prepare消息,并且自己也进入Prepare阶段
5.所有节点统计针对某个Request的Prepare消息,当统计结果超过2f节点时,表明大部分节点已经完成了持久化,则自己进入commit阶段
6.广播 commit 消息,并且统计收到的commit 消息的数量,当超过2f节点都发出commit的消息时
7.该节点完成commit阶段,写入数据(该操作已经完成2/3共识了),运用自己的状态机,更新 stable checkpoint,缓存该客户端最后一次的请求,并且反馈给客户端
8.当客户端统计反馈的节点超过f个时,表示交易已经被大部分节点确认了,交易成功。如果超时还不成功,则向所有的replica广播这个request
解释:

1.为什么客户端收到f+1个确认时,交易就成功了?
因为默认问题节点为f,那么f+1个确认节点中,肯定有1个是诚实的节点,只要有1个诚实的确认消息,则交易成功,因为1个诚实的消息必须是2f+1个节点都commit操作成功了,才可能有这个1个最终确认消息的。所以为了提升交易处理的速度,只要有f+1个确认反馈,就可以表示交易成功。

客户端Client发起请求

1.客户端 c 通过向副本多播一条<REQUEST,o,t,c>到系统中
2.副本对Request进行身份验证
3.验证成功,则接受请求并将其添加到它们的日志中,请求执行使用request中的时间戳进行排序执行
4.副本直接将请求的回复发送给客户端
5.客户端在接受结果 r 之前,等待一个来自不同副本的有 f + 1 个带有有效 MACs 的以及相同的 t 和 r 的 weak certificate
6.如果客户端没有足够迅速的收到一个 reply certificate,则会重新发送请求。如果请求已被处理,则副本只是重新发送回复;副本记住他们发送给每个客户端的最后一个回复消息以 启用此重传
客户端请求消息:客户端直接向Primary节点发起一个请求 : 消息的格式<REQUEST, o, t, c>

o: 请求的具体操作,operation
t: 请求时客户端追加的时间戳,time,这里面追加的是client的时间戳,会在后面的时 候,客户端的请求做时间戳排序,结合请求编号一起,保证消息的有序性(不仅仅是写 操作,还有读写操作)
c:客户端标识,clientID,其中 c + t 就是requestID
REQUEST: 包含消息内容m,以及消息摘要d(m)。客户端对请求进行签名。
服务端在执行request时会进行签名验证,因为PBFT应用的是联盟链,而不是私链,所以要对操作者的身份进行校验,比如A发起一笔转账,则服务端需要check是不是A发起的转账,防止盗刷

服务端回复消息:<REPLY, v, t, c, i, r>

REPLY,消息类型为回复客户端
v,当前view
t,c 哪个client的时间戳为t的回复(而不是通过zxid,是通过时间戳,相当于 requestID)
i 当前node编号
r 操作结果,还必须有server i的签名,客户端要验证的,防止网络拦截和欺诈

消息

消息的类型(pre-prepare、prepare、commit)

View(类似于term)

n(类似于index)

d(交易的详细信息)

m(交易的签名)

i(节点的编号)

checkpoint :节点参数,该节点最新的proposal编号

stable checkpoint:系统参数,该系统中,最新的超过2f节点commit过了的proposal的编号。可以减少内存的占用,已经2f+1确认过的操作,就最终确认了,后续不需要操作了,可以从内存中移除了。

重新选举 viewChange

当普通节点感知到primary异常的时候,触发viewchange,重新选举必须要有2f+1个节点都confirm(VIEW-CHANGE)了,发起重选才生效,一旦超过2f节点都发起VIEW-CHANGE消息,则选举结束,p =v+1 mod |R|节点当选为new Primary。并且new primary会根据自己统计的VIEW-CHANGE的内容,生成并广播NEW-VIEW消息,其它节点验证之后,开始新的view

<VIEW-CHANGE, v+1, n, C, P, i>消息

v+1 :新的view编号
n是最新的stable checkpoint的编号
C是2f+1验证过的CheckPoint消息集合
P是当前副本节点未完成的请求的PRE-PREPARE和PREPARE消息集合
新的主节点就是 newPrimary = v + 1 mod |R|。当newPrimary收到2f个有效的VIEW- CHANGE消息后,向其他节点广播NEW-VIEW消息
<NEW-VIEW, v+1, V, O>

V是有效的VIEW-CHANGE消息集合
O是主节点重新发起的未经完成的PRE-PREPARE消息集合

未完成的PRE-PREPARE消息集合的生成逻辑:

1.选取V中最小的stable checkpoint编号min-s,选取V中prepare消息的最大编号max-s。
2.在min-s和max-s之间,如果存在P消息集合,则创建<<PRE-PREPARE, v+1, n, d>, m>消息。否则创建一个空的PRE-PREPARE消息,即:<<PRE-PREPARE, v+1, n, d(null)>, m(null)>, m(null)空消息,d(null)空消息摘要。
副本节点收到主节点的NEW-VIEW消息,验证有效性(各个replica都统计view-change的个数),有效的话,进入v+1状态,并且开始O中的PRE-PREPARE消息处理流程。

特殊情况:

那么如果一半的节点和primary网络分区了,那也无法发起重选。
同时primary也执行不了新的操作,因为新的消息有一半节点收不到,整个集群陷入瘫痪状态。所以primary也应该和zab一样,具备自我检测超时,超过一定个数的ack缺失时,触发重新选举。

Raft Vs PBFT

1.Raft系统中leader拥有最高权限,follower如果和leader数据不一致,那么必须删除自己的数据,保持和leader一致

2.PBFT中,Primary向我发送命令时,当我认为老大的命令是有问题时,我会拒绝执行。并且很有可能会触发view-change。就算我认为老大的命令是对的,我还会问下团队的其它成员老大的命令是否是对的,只有大多数人 (2f+1) 都认为老大的命令是对的时候,我才会去执行命令

PBFT的特点

1.客户端事务请求的严格有序性
request里面包含了时间戳,request在服务端执行的时候,按照时间戳进行排序执行。而zab协议、raft协议都是按照先到先执行的有序性(服务端),但是PBFT却能按照Client的有序性。即使网络问题,先发起的请求晚于后发起的请求抵达服务端,服务端也不会打乱执行的顺序,PBFT是更严格的操作有序性。这也提高了系统的复杂度。

2.性能尚可
PBFT 算法通信复杂度 o(n^2),因为系统在尝试达成状态共识时,涉及到N个几点都需要广播N-1个其它节点。而在没有作恶节点的zab、raft系统中,通信复杂度 O(N)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值