Commit c5df5775 authored by Hugo's avatar Hugo

update

parent 730ce2f2
# pbft共识
# pbft共识
......@@ -17,22 +17,25 @@ pbft全称(Practical Byzantine Fault Tolerance)意为实用拜占庭容错算法
## 算法详细步骤
本算法分为三个阶段:pre-prepare、prepare 和 commit和三个谓词(predicate)prepared、committed和committed-local.Pre-prepare和Prepare保证同一个view中的请求有序,Prepare和Committe保证不同view中的请求被有序地执行。
1. 当primary节点收到请求时,则开始pre-prepare阶段:primary对收到的请求标记序号n(n是按序增长的),把pre-prepare消息进行广播,并把此消息记入自己的log中。消息格式为<PRE-PREPARE,v,n,m>,v是primary节点当前的视图号,n是这个请求的序号,m是请求。
1. 当primary节点收到请求时,则开始pre-prepare阶段:primary对收到的请求标记序号n(n是按序增长的),把pre-prepare消息进行广播,并把此消息记入自己的log中。消息格式为<PRE-PREPARE,v,n,m>,v是primary节点当前的视图号,n是这个请求的序号,m是请求。
Backup节点收到<PRE-PREPARE,v,n,m>消息时进行检查,如果满足:
(1) v与自己的视图号相同,
(2) n在[h,H]之间,
- (1) v与自己的视图号相同
- (2) n在[h,H]之间
则接受此<PRE-PREPARE,v,n,m>消息。
2. prepare阶段
如果一个backup节点i接受<PRE-PREPARE,v,n,m>消息,它就广播一个prepare消息(消息格式为<PREPARE,v,n,d,i>,其中d是m的digest)到其他所有节点,并把<PRE-PREPARE,v,n,m>消息和<PREPARE,v,n,d,i>消息都记入自己的log中,这进入prepare阶段。
- 我们定义谓词prepared(m,v,n,i)为true,当且仅当一个节点i记入其log中:请求m,针对在视图v序号为n的消息m的PRE-PREPARE,2f个来自不同节点且与PRE-PREPARE匹配的<PREPARE,v,n,d,i>消息(匹配的条件是要有相同的v和相同的n和d)。
3. commit阶段
如果一个节点i的谓词prepared为true,则广播commit消息到每一节点,这就进入了确认阶段。所有节点在一定前提(签名正确,视图v与当前的v一致,序号n在h与H之间)下接受commit消息(消息格式为<COMMIT,v,n,d,i>)并记入log中。
- 我们定义谓词committed为true当且仅当f+1个非故障节点(non-faulty)中的任意副本i的谓词prepared为真.
- 定义谓词committed-local当且仅当该节点谓词prepared为真,并且接受了2f+1个(可能包括他自己)来自不同节点的与PRE-PREPARE匹配的<COMMIT,v,n,d,i>消息(匹配条件是要有相同的n、相同的v、相同的d)。
2. prepare阶段
如果一个backup节点i接受<PRE-PREPARE,v,n,m>消息,就进入prepare阶段,并广播一个prepare消息(消息格式为<PREPARE,v,n,d,i>,其中d是m的digest)到其他所有节点,并把<PRE-PREPARE,v,n,m>消息和<PREPARE,v,n,d,i>消息都记入自己的log中。
- 我们定义谓词prepared(m,v,n,i)为true,当且仅当一个节点i在其log中记录:
1. 请求m
2. 针对在视图v序号为n的消息m的PRE-PREPARE
3. 2f个来自不同节点且与PRE-PREPARE匹配的<PREPARE,v,n,d,i>消息(匹配的条件是要有相同的v和相同的n和d)
3. commit阶段
如果一个节点i的谓词prepared为true,则广播commit消息到每一节点,就进入了确认阶段。所有节点在一定前提(签名正确,视图v与当前的v一致,序号n在h与H之间)下接受commit消息(消息格式为<COMMIT,v,n,d,i>)并记入log中。
- 我们定义谓词committed为true当且仅当f+1个非故障节点(non-faulty)中的任意副本i的谓词prepared为真.
- 定义谓词committed-local当且仅当该节点谓词prepared为真,并且接受了2f+1个(可能包括他自己)来自不同节点的与PRE-PREPARE匹配的<COMMIT,v,n,d,i>消息(匹配条件是要有相同的n、相同的v、相同的d)。
## 垃圾回收
为了保持安全条件,消息必须保存在节点的日志中,直到它知道它们所关注的请求已由至少f + 1个非故障节点执行,并且它可以在视图更改(view change)时向其他人证明这一点。此外,如果某节点错过了所有非故障副本丢弃的消息,则需要通过传输全部或部分服务状态来更新这个节点。因此,节点也需要一些证明状态正确的证据。但节点的日志不能无限制地增长,当到达某一时刻,节点要删除一些老旧的log。又不能执行过一个请求后就把相关的log立刻删除,这样是不安全的.
为了保持安全条件,消息必须保存在节点的日志中,直到它知道它们所关注的请求已由至少f + 1个非故障节点执行,并且它可以在视图更改(view change)时向其他人证明这一点。此外,如果某节点错过了所有非故障副本丢弃的消息,则需要通过传输全部或部分服务状态来更新这个节点。因此,节点也需要一些证明状态正确的证据。但节点的日志不能无限制地增长,当到达某一时刻,节点要删除一些老旧的log。又不能执行过一个请求后就把相关的log立刻删除,这样是不安全的.
检查点(checkpoint):当一个节点收到一个request的序号为n,而n能被一个整数K(例如100)整除时,我们把此时的这个状态叫做checkpoint,处理改消息的时机是完成reply之后。
......@@ -53,26 +56,24 @@ Backup节点收到<PRE-PREPARE,v,n,m>消息时进行检查,如果满足:
## 视图切换(view change)
视图变更协议在主节点失效的时候仍然保证系统的活性。视图变更可以由超时触发,以防止备份节点无期限地等待请求的执行。如果一个备份节点收到有效请求,但是还没有执行它,我们就说它在等待一个请求。当备份节点接收到一个请求但是定时器还未运行,那么它就启动定时器;当它不再等待执行请求就把定时器停止,但是如果它正等待执行其他请求时就要重启定时器。如果定时器超时,则触发view change。
视图变更协议在主节点失效的时候仍然保证系统的活性。视图变更可以由超时触发,以防止备份节点无期限地等待请求的执行。如果一个备份节点收到有效请求(此请求由于客户端一直没有收到应答而把请求广播到所有节点)时,如果定时器没有启动,就启动一个定时器;当它不再等待执行请求就停止定时器,但是如果它正等待执行其他请求(即客户端发送的请求和它正在执行请求不同)时就要重启定时器。如果定时器超时,则触发view change。
![视图切换](./resources/viewchange.png)
过程如下:
1. 当一个backup节点i的timer超时,i停止接收消息(但仍然接收checkpoint、view change和new view消息),并广播一个view change消息,消息格式为<VIEW-CHANGE,v+1,n,s,C,P,i>,n是节点i中上一个stable checkpoint(s) 对应的序号,C是s的证据(2f+1个有效的checkpoint消息),P是i中每一个序号大于n的请求所对应的prepared为true的log(证据)的集合。
2. 如果v+1对应的新primary节点收到2f+1个来自不同节点(包含自己)的<VIEW-CHANGE,v+1,n,s,C,P,i>消息,它就广播new view消息到所有其他节点,消息格式为<NEW-VIEW,v+1,V,O>,V是包含接收到的其他节点的view change消息和自己发送(或将要发送)的view change消息的集合.O是pre-prepare消息(不带请求m)的集合.
- O通过下面的方法计算得到:
1. primary确定pre-prepare消息的序号范围从V中上一个stable checkpoint对应的序号min-s,到V中的prepared为true的证据中的最大的序号max-s.
- O通过下面的方法计算得到:
1. pre-prepare消息的序号范围是V中上一个stable checkpoint对应的序号min-s,到V中的prepared为true的证据中的最大的序号max-s之间.
2. primary对每一个序号为n(第一点中确定的范围)的请求创建一个新的且视图号为v+1的pre-prepare消息.此时有两种情况:
- 在V中,存在序号为n的prepared的证据.
- 不存在这样的prepared证据.
第一种情况下O是primary创建的针对每个n的新<PRE-PREPARE,v+1,n,d>消息.
第二中情况下O是primary创建的一个<PRE-PREPARE,v+1,n,null>消息,null是一种指定的“null”请求(此请求不做任何操作)的digest,并把此消息记入log.
如果min-s大于primary上一个stable checkpoint对应的序号,那么primary将stable checkpoint的消息保存到log,从而更新自己的stable checkpoint。此时,primary节点进入view为v+1阶段,并可以接收视图号为v+1的消息.
- 在V中,存在序号为n的prepared的证据.------>O是primary创建的针对每个n的新<PRE-PREPARE,v+1,n,d>消息.
- 不存在这样的prepared证据.------>O是primary创建的一个<PRE-PREPARE,v+1,n,null>消息,null是一种指定的“null”请求(此请求不做任何操作)的digest,并把此消息记入log.
> 如果min-s大于primary上一个stable checkpoint对应的序号,那么primary将stable checkpoint的消息保存到log,从而更新自己的stable checkpoint。此时,primary节点进入view为v+1阶段,并可以接收视图号为v+1的消息.
3. backup节点通过如下验证来决定是否接受new view消息:
- 正确的签名信息
- 其包含的view change消息(也就是V)对v+1是否有效.
- 通过类似于主节点创建O的方法计算验证O的正确性.
4. 接下来的操作就是重做从min-s到max-s序号之间的prepare流程,但是为避免重新执行客户端的请求(通过使用他们存储的发送给每个客户端的最后回复的信息).
4. 接下来的操作就是重做从min-s到max-s序号之间的prepare流程,但是可以使用他们存储的发送给每个客户端的最后回复的信息来避免重新执行客户端的请求.
5. 如果一个节点丢失了一些请求消息m或者一个stable checkpoint(由于这些没有在new-view消息中发送)可以从其他节点获取缺少的信息.例如,节点i可以从任何一个在V中证明了checkpoint 消息正确性的节点处获取缺少的checkpoint state s.由于f+1个节点是正确的,节点i将总能获得s或稍后认证的stable checkpoint。
### 代码中的不同
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment