Bully算法是一种协调者(主节点)竞选算法,主要思想是集群中的每个成员都可以声明它是主节点并通知其他节点。其他节点可以选择接受这个声明或者拒绝并进入主节点竞争。被其他所有节点接受的节点才能成为主节点。节点按照一些属性(比如进程ID)来判断应该接受谁胜出。Mongo早期的版本便是采用bully进行主节点选取。
算法流程
在很多实际的应用中,用来判断节点胜出的条件都会不一致,可以根据具体的环境选择。算法定义的时候给出的例子是以最大的可用进程ID为主节点。
算法有三种消息:
1) 选举消息(Election Message)
2) 应答消息(Answer(Alive) Message)
3) 选举成功消息(Coordinator(Victory) Message )
当一个进程P从故障中恢复过来,或者接受到主节点失效的信息时,操作如下:
1) 如果进程P有最大的进程ID,向其他进程广播选举成功消息.否则向进程号比自己大的进程发送选举消息。
2) 如果进程P发送选举消息之后,没有接收到应答,就会向其他的节点广播选举成功消息,并成为主节点。
3) 如果进程P收到比它进程ID大的进程的Answer Message,选举失败,等待接收其他进程的Victory Message。
4) 如果进程P收到比它进程ID小的进程的Election Message时,向该进程发送一个Answer Message。并启动选举进程,向比他更高的进程发送Election Message。
5) 如果进程P收到Victory Message,会把发送这条消息的节点当成主节点。
算法实现
- 最初集群有5个节点,节点5是一个公认的协调者。
- 假设节点5挂了,并且节点2和节点3同时发现了这一情况。两个节点开始竞选并发送竞选消息给ID更大的节点。
- 节点4淘汰了节点2和3,节点3淘汰了节点2。
- 这时候节点1察觉了节点5失效并向所有ID更大的节点发送了竞选信息。
- 节点2、3和4都淘汰了节点1。
- 节点4发送竞选信息给节点5。
- 节点5没有响应,所以节点4宣布自己当选并向其他节点通告了这一消息