一、拜占庭将军问题
古代,拜占庭的各地的将军去打仗,比如有10个,必须相互通信,达成共识才能一起出发,否则战役失败。
问题1、有个将军会叛变,在有将军叛变的情况下,如何达成共识。
问题2、互相通信的信道必须是安全的,在不安全的信道中通讯,达成共识很困难的。
已经证明:在背叛者为f,将军总数>3f时,可达成共识。3f+1<=n---->(n-1)/3
容错节点:应为硬件或者网络问题,节点无响应。
作恶节点:除了无响应,还可以发除错误的信息,误导其他人。
raft 可容忍的错误节点数 f = (n-1)/2,
设节点总数为n,错误节点为f,根据共识定理,只有比f多1个就可以既f+1,f+f+1 = n
2f+1=n-->f = (n-1)/2 综上所述,作恶节点个数最多为(n-1)/2个,系统可达成共识。
PBFT可容忍的非正确节点的个数为f =(n-1)/3,
1、情况1、假设节点总数为n,作恶节点为f,错误节点个数为f,作恶节点被发现后,会被系统剔除,那么完好节点只要比错误的节点多1个,既f+1就可以了。那么f+f+f+1 = n-->3f+1=n ----> f=(n-1)/3
2、情况2、作恶节点与错误节点个数相同,同raft。
基本流程:
1、客户端给主节点发送情况,
2、主节点将请求广播给其他节点,其他节点做三阶段处理。
3、节点处理完成后,落盘,返回给客户端。
4、客户端收到f+1个正确消息后,代表共识结束。
三阶段处理:
pre-pre、promise、commit
消息类型
v是主节点选举的第几轮,1,2。。。等等
n是客户端发过来的请求的编号
d是消息内容的摘要
m是消息的内容
主节点收到消息会向其他节点发送pre-prepare消息。开始三阶段处理
1、非主节点收到pre-prepare消息,判断接受不接受。不接受的逻辑,与第一次收到的消息相比较,是V,n相同,但d和M不同,及不是这个消息。或者请求编号不在高低水位之间。
2、如果接受pre-prepare消息,则想其他节点广播发送promise消息,其他节点也做同样的事情,如果1个节点收到超过2f+1个promise消息,则进入commit阶段。
3、节点会将向外广播commit消息,其他节点也在做同样的操作。当收到2f+1个commit消息时,则认为大多数节点都commit了,这时候就会落盘,向客户端发送正确消息。
View change(视图改变)
更换主节点,当主节点挂了,或者其他从节点认为主节点作恶,就会触发view change。
过程分view-change,view-change-ack,new-view
当主节点挂了,从节点想其他节点发出view-change消息,其中编号最小的节点会成为主节点,当新主节点收到2f+1个节点的view-change消息,就认为大家都同一它成为新节点。那他就会发出new-view消息,接着处理上个视图没处理完的请求。
垃圾回收
checkpoint和stable checkpoint和高低水位
checkpoint当前节点处理的最新请求序号号。
stable checkpoint 大部分节点2f+1个节点已经共识完成的请求序列号。
stable checkpoint是为了减少数据的占用空间,它之前的请求都可以删除掉。每个节点不用再存所有的请求了,节省了节点的空间。
节点i会给其他节点发送
n是当前节点的请求序列号。
d是当前状态的一个摘要。
当收到2f+1个节点的回复时,就认识大多数人都处理到这个请求序列号了,那么就会形成stable checkpoint。
如果收到i节点消息的其他节点,没有处理到这个请求序列号,那么就不会返回消息。
高低水位
低水位为上一次的stable checkpoint,高水位为低水位+L(L为我们设定的值)。
当节点i的处理请求序列号超过高水位,就等待,不处理了,等待stable checkpoint变化后,再继续处理。
raft和PBFT的时间复杂度。
raft的复杂度O(n),共识分为日志记录,提交数据2部分,都是主节点给从节点发送数据,从节点之间是不需要沟通的,从节点回复接受或者不接受。
日志记录阶段,请求数n-1。提交数据阶段,请求数n-1。总的是2n-2。
PBFT的时间复杂度O(n),的pre-pepare阶段,主节点发送给所有从节点,请求数为n-1,
promise阶段,每个从节点给每个其他节点发送,请求数为n*(n-1)
commit阶段,每个从节点给每个其他节点发送,请求数也没n*(n-1)
raft不会质疑主节点,pbft会质疑主节点。