一、思路图展示
二、思路解析
我们都知道Zookeeper的节点有两种类型,分别是持久节点和临时节点。临时节点有个特性,就是如果注册这个节点的机器失去连接(通常是宕机),那么这个节点会被zookeeper删除。选主过程就是利用这个特性,在服务器启动的时候,去zookeeper特定的一个目录下注册一个临时节点(这个节点作为master,谁注册了这个节点谁就是master),注册的时候,如果发现该节点已经存在,则说明已经有别的服务器注册了(也就是有别的服务器已经抢主成功),那么当前服务器只能放弃抢主,作为从机存在。同时,抢主失败的当前服务器需要订阅该临时节点的删除事件,以便该节点删除时(也就是注册该节点的服务器宕机了或者网络断了之类的)进行再次抢主操作。选主的过程,其实就是简单的争抢在Zookeeper注册临时节点的操作,谁注册了约定的临时节点,谁就是master。所有服务器同时会在servers节点下注册一个临时节点(保存自己的基本信息),以便于应用程序读取当前可用的服务器列表。
三、如何使用
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.9.0</version>
</dependency>
通过以上分析我们不难看出,其实想要实现这个简单的选举过程其实是很难的,那么我们下面将借助Curator来实现想要的功能。
public class MasterSelectTest {
public static void main(String[] args) throws Exception {
String masterPath = "/master_path";
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181").sessionTimeoutMs(5000).connectionTimeoutMs(10000).retryPolicy(retryPolicy).namespace("text").build();
client.start();
/**
* 该实例封装了所有Master选举相关的逻辑,包括所有和Zookeeper服务器交互的过程,其中Master_select代表一个Master选举的一个
* 根节点,表明本次Master选举都是在该节点下进行的。
* 在创建LeaderSelector实例的时候,还会传入一个监听器:LeaderSelectorListenerAdapter。这需要开发人员自行实现。Curator
* 会在成功获取Master权利时候回调该监听器。
*/
LeaderSelector leaderSelector = new LeaderSelector(client, master_path, new LeaderSelectorListener() {
@Override
public void stateChanged(CuratorFramework client, ConnectionState stat) {
}
/**
* 成为Master角色
* 完成Master操作,释放Master权利
* 成为Master角色
*/
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
System.out.println("成为Master");
Thread.sleep(3000);
List<String> path = client.getChildren().forPath(masterPath);
System.out.println(path);
System.out.println("完成Master操作,释放Master权利");
}
});
leaderSelector.autoRequeue();
leaderSelector.start();
}
}