Zookeeper 会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统
zookeeper基于目录监听机制来选主,多个客户端节点都可以来对zookeeper上某个目录节点进行监听和注册,但只有其中一个能够注册上,谁能注册上谁就是主节点,主节点会保持着和zookeeper目录节点的长连接,只要该连接不断,那么该客户端节点就一直是主节点,其他客户端节点都会监听者zookeeper的该目录节点,一旦主节点宕机,会立即从其他客户端节点中选出一个新的主节点,也就是说:如果当前master宕机,会立即选出一个新的master。
zookeeper的使用:
1、pom引入相关依赖
<!-- zookeeper 客户端 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.13.0</version> </dependency>
其中:Curator 提供了LeaderSelector用来判断是否主节点
2、创建测试类SelectMasterTest
package com.cookie; /** * @author cxq * @version 1.0 * @date 2020/7/10 17:35 * @desc */ import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.leader.LeaderSelector; import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter; import org.apache.curator.retry.ExponentialBackoffRetry; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class SelectMasterTest { private String selectMasterZookeeper="192.168.200.129:2181"; //可以放很多节点 Map<String, Boolean> masterMap = new HashMap<String, Boolean>(); /** * 选主 * @param leaderPath zookeeper目录节点 */ public void selectMaster (String leaderPath) { CuratorFramework client = CuratorFrameworkFactory.builder(). connectString(selectMasterZookeeper) .sessionTimeoutMs(5000) //超时时间 .retryPolicy(new ExponentialBackoffRetry(1000, 3)) //连接不上重试三次 .build(); client.start(); //争抢注册节点 @SuppressWarnings("resource") LeaderSelector selector = new LeaderSelector(client, leaderPath, new LeaderSelectorListenerAdapter() { @Override public void takeLeadership(CuratorFramework client) throws Exception { //如果争抢到当前注册节点 masterMap.put(leaderPath, true); while (true) { //抢占当前节点 TimeUnit.SECONDS.sleep(3); } } }); masterMap.put(leaderPath, false); selector.autoRequeue(); selector.start(); } public boolean checkMaster (String leaderPath) { Boolean isMaster = masterMap.get(leaderPath); return isMaster == null ? false : isMaster; } public static void main(String[] args) throws InterruptedException { String leaderPath = "/master"; SelectMasterTest selectMaster = new SelectMasterTest(); selectMaster.selectMaster(leaderPath); TimeUnit.SECONDS.sleep(1); while(true) { if(selectMaster.checkMaster(leaderPath)){ System.out.println(" 节点1 主节点 "); }else { System.out.println(" 节点1 从节点 "); } TimeUnit.SECONDS.sleep(6); } } }
3、测试
3.1、启动三次main方法模拟三个客户端节点,查看每个节点的输出情况,预计只有一个能够注册为主节点,其他两个是从节点。
3.2、停掉主节点,查看控制台看剩余两个节点是否有新的主节点产生。
主节点
从节点
断开主节点,其他节点争抢注册主节点