Zookeeper 的 Leader 选举是保证其高可用性和一致性的核心机制之一。在 Zookeeper 集群中,Leader 负责处理写请求和协调其他节点(Followers)。Zookeeper 采用了一个称为 ZAB(Zookeeper Atomic Broadcast)协议的算法来进行 Leader 选举和日志复制。
Zookeeper Leader 选举流程
-
启动和状态检测:
- 每个 Zookeeper 节点(Server)在启动时都会进行自检,并尝试连接到其他节点。
- 节点会尝试与其他节点通信,以检测它们的状态。
-
发送投票:
- 每个节点都会向其他节点发送投票,表示自己希望成为 Leader。
- 投票信息包括节点的 ID 和最新的事务 ID(ZXID)。
-
接收投票:
- 节点接收到其他节点的投票后,会比较投票中的 ZXID 和节点 ID。
- 节点会选择 ZXID 最大的投票作为新的投票目标。如果 ZXID 相同,则选择节点 ID 较大的节点。
-
统计投票:
- 节点会统计收到的投票数量。
- 如果某个节点收到的投票数超过集群中节点总数的一半,则该节点被选为 Leader。
-
通知结果:
- 当某个节点确认自己成为 Leader 后,会通知其他节点。
- 其他节点接收到通知后,会更新自己的状态,成为 Follower。
代码示例
以下是一个使用 Apache Curator 实现 Leader 选举的示例代码。
添加 Maven 依赖
在 pom.xml 中添加 Curator 客户端的依赖:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.2.0</version>
</dependency>
Leader 选举代码示例
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.framework.recipes.leader.LeaderLatch;
import org.apache.curator.framework.recipes.leader.LeaderLatchListener;
public class ZookeeperLeaderElectionExample {
private static final String ZK_ADDRESS = "zoo1:2181,zoo2:2181,zoo3:2181";
private static final String LEADER_PATH = "/leader_latch_path";
private CuratorFramework client;
private LeaderLatch leaderLatch;
public ZookeeperLeaderElectionExample() {
client = CuratorFrameworkFactory.newClient(ZK_ADDRESS, new ExponentialBackoffRetry(1000, 3));
client.start();
leaderLatch = new LeaderLatch(client, LEADER_PATH);
}
public void start() throws Exception {
leaderLatch.addListener(new LeaderLatchListener() {
@Override
public void isLeader() {
System.out.println("I am the leader now!");
// 执行成为 Leader 后的操作
}
@Override
public void notLeader() {
System.out.println("I am not the leader.");
// 执行失去 Leader 后的操作
}
});
leaderLatch.start();
}
public void close() throws Exception {
leaderLatch.close();
client.close();
}
public static void main(String[] args) throws Exception {
ZookeeperLeaderElectionExample example = new ZookeeperLeaderElectionExample();
example.start();
// 示例运行一段时间后关闭
Thread.sleep(60000);
example.close();
}
}
详细解释
-
启动和状态检测:
- 每个 Zookeeper 节点在启动时会尝试与其他节点通信,以检测它们的状态。
- 在代码中,使用
CuratorFrameworkFactory.newClient创建一个 Curator 客户端实例,并调用client.start()启动客户端。
-
发送投票:
- 每个节点会向其他节点发送投票,表示自己希望成为 Leader。
- 在代码中,使用
LeaderLatch类实现 Leader 选举。创建LeaderLatch实例,并传入 Zookeeper 客户端和 Leader 选举的路径。
-
接收投票:
- 节点接收到其他节点的投票后,会比较投票中的 ZXID 和节点 ID。
- 在代码中,通过
LeaderLatch.addListener添加 Leader 选举监听器,监听选举结果。
-
统计投票:
- 节点会统计收到的投票数量。如果某个节点收到的投票数超过集群中节点总数的一半,则该节点被选为 Leader。
- 在代码中,当节点成为 Leader 时,会调用
isLeader方法;当节点失去 Leader 身份时,会调用notLeader方法。
-
通知结果:
- 当某个节点确认自己成为 Leader 后,会通知其他节点。其他节点接收到通知后,会更新自己的状态,成为 Follower。
- 在代码中,通过打印日志的方式通知选举结果。
总结
Zookeeper 的 Leader 选举流程通过多数派机制和 ZAB 协议来确保高可用性和一致性。通过合理配置 Zookeeper 集群和使用 Curator 客户端库,可以实现高效的 Leader 选举。以上代码示例展示了如何使用 Apache Curator 实现 Leader 选举,并通过监听器机制处理选举结果。这些措施能够确保 Zookeeper 集群在面对网络分区或节点故障时仍能保持稳定和一致。