Consensus algorithms allow a collection of machines to work as a coherent group that can survive the failures of some of its members.算法
- 私链:传统分布式系统里的共识算法(相较于区块链这个概念),好比 zookeeper 的 zab 协议,paxos, raft。私链是不考虑集群中存在做恶节点,只考虑由于系统或者网络缘由致使的故障节点。
- 联盟链:须要考虑集群中存在故障节点,还须要考虑集群中存在做恶节点。对于联盟链,每一个新加入的节点都是须要验证和审核的。好比 pbft 算法
- 公链:须要考虑网络中存在故障节点,还须要考虑做恶节点,这一点和联盟链是相似的。和联盟链最大的区别就是,公链中的节点能够很自由的加入或者退出,不须要严格的验证和审核。好比pow.pos,dpos,ripple
- paxos是一类协议的统称
- basic paxos
- multi-paxos 强化了leader
- raft 会有点像multi-paxos
两个paper安全
- 小论文《In Search of an Understandable Consensus Algorithm》
- 大论文[《CONSENSUS: BRIDGING THEORY AND PRACTICE》]
一些实现的开源项目,etcd, tidb/tikv, consulbash
Raft算法由leader节点来处理一致性问题。leader节点接收来自客户端的请求日志数据,而后同步到集群中其它节点进行复制,当日志已经同步到超过半数以上节点的时候,leader节点再通知集群中其它节点哪些日志已经被复制成功,能够提交到raft状态机中执行。app
经过以上方式,Raft算法将要解决的一致性问题分为了如下几个子问题。分布式
节点刚启动,进入follower状态,同时建立一个超时时间在150-300毫秒之间的选举超时定时器。
follower状态节点主循环:
若是收到leader节点心跳:
心跳标志位置1
若是选举超时到期:
没有收到leader节点心跳:
任期号term+1,换到candidate状态。
若是收到leader节点心跳:
心跳标志位置空
若是收到选举消息:
若是当前没有给任何节点投票过 或者 消息的任期号大于当前任期号:
投票给该节点
不然:
拒绝投票给该节点
candidate状态节点主循环:
向集群中其余节点发送RequestVote请求,请求中带上当前任期号term
收到AppendEntries消息:
若是该消息的任期号 >= 本节点任期号term:
说明已经有leader,切换到follower状态
不然:
拒绝该消息
收到其余节点应答RequestVote消息:
若是数量超过集群半数以上,切换到leader状态
若是选举超时到期:
term+1,进行下一次的选举
复制代码
发起选举时,follower将递增它的任期号而后切换到candidate状态。而后经过向集群中其它节点发送RequestVote RPC请求来发起一次新的选举。一个节点将保持在该任期内的candidate状态下,直到如下状况之一发生。区块链
该candidate节点赢得选举,即收到超过半数以上集群中其它节点的投票。 另外一个节点成为了leader。 选举超时到来时没有任何一个节点成为leader。spa
日志复制的流程大致以下:
每一个客户端的请求都会被重定向发送给leader,这些请求最后都会被输入到raft算法状态机中去执行。
leader在收到这些请求以后,会首先在本身的日志中添加一条新的日志条目。
在本地添加完日志以后,leader将向集群中其余节点发送AppendEntries RPC请求同步这个日志条目,当这个日志条目被成功复制以后(什么是成功复制,下面会谈到),leader节点将会将这条日志输入到raft状态机中,而后应答客户端。
committedIndex >= appliedIndex
复制代码
Raft算法保持着如下两个属性,这两个属性共同做用知足前面提到的日志匹配(LogMatch)属性:日志
- 领导人彻底原则:若是一个日志条目在一个给定任期内被提交,那么这个条目必定会出如今全部任期号更大的领导人中
- broadcastTime << electionTimeout << MTBF