# Zookerper选举原理

作为一个分布式应用程序协调服务，在大型网站中，其本身也是集群部署的，安装zookeeper的时候最好是单数节点，因为要选举。Zookeeper的leader节点是集群工作的核心，用来更新并保证leader和server具有相同的系统状态，Follower服务器是Leader的跟随者，用于接收客户端的请求并向客户端返回结果，在选举过程中参与投票。对于客户端来说，每个zookeeper都是一样的。

Zk的选举算法有两种：一种是基于basic paxos实现的，另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos（快速选举算法）。

## 一、投票包含的信息

* Sid：被推举leader的服务器id；
* Zxid：被推举leader服务器的事务id，数据越新，zxid越大；
* electionEpoch：逻辑时钟，用来判断多个投票是否在同一轮选举周期中，该值在服务端是一个自增序列，每次进入新一轮的投票后，都会对该值进行加1操作；
* peerEpoch：被推举的Leader的epoch；
* server状态：
  * Looking（选举状态）
  * Leading（领导者状态，表明当前server是leader）
  * Following（跟随者状态，表明当前server是Follower）
  * Observing（观察者状态、表明当前server是Observer，不会参加投票）。

## 二、选举步骤

当系统启动或者leader崩溃后，就会开始leader的选举。

1. 状态变更。服务器启动的时候每个server的状态是Looking，如果是leader挂掉后进入选举，那么余下的非Observer的Server就会将自己的服务器状态变更为Looking，然后开始进入Leader的选举状态；
2. 发起投票。每个server会产生一个（sid，zxid）的投票，系统初始化的时候zxid都是0，如果是运行期间，每个server的zxid可能都不同，这取决于最后一次更新的数据。将投票发送给集群中的所有机器；
3. 接收并检查投票。server收到投票后，会先检查是否是本轮投票，是否来自looking状态的server；
4. 处理投票。对自己的投票和接收到的投票进行PK：
   * 先检查zxid，较大的优先为leader；
   * 如果zxid一样，sid较大的为leader；

     根据PK结果更新自己的投票，再次发送自己的投票；
5. 统计投票。每次投票后，服务器统计投票信息，如果有过半机器接收到相同的投票，那么leader产生，如果否，那么进行下一轮投票；
6. 改变server状态。一旦确定了Leader，server会更新自己的状态为Following或者是Leading。选举结束。

**补充说明：**

1. 为了能够相互投票，每两台服务器之间都会建立网络连接，为避免重复建立TCP连接，zk的server只允许sid大于自己的服务器与自己建立连接，否则断开当前连接，并主动和对方建立连接。

> 参考：
>
> <https://www.cnblogs.com/felixzh/p/5869212.html>
>
> <https://www.cnblogs.com/leesf456/p/6107600.html>
>
> <https://www.cnblogs.com/ASPNET2008/p/6421571.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/web-zhong-jian-jian-xue-xi/zookeeper-xuan-ju-yuan-li.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
