ZooKeeperZooKeeper Java API
- org.apache.zookeeper.Zookeeper
Zookeeper 是在Java中客户端主类,负责建立与zookeeper集群的会话,并提供方法进行操作。 - org.apache.zookeeper.Watcher
Watcher接口表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)。 - process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理。
基本使用
建立java maven项目,引入maven pom坐标。
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.9</version>
</dependency>
java代码
public static void main(String[] args) throws Exception {// 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher)ZooKeeper zk = new ZooKeeper("node-1:2181,node-2:2181", 30000, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("事件类型为:" + event.getType());System.out.println("事件发生的路径:" + event.getPath());System.out.println("通知状态为:" +event.getState());}});zk.create("/myGirls", "性感的".getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);zk.close();
更多操作示例
public static void main(String[] args) throws Exception {// 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher)ZooKeeper zk = new ZooKeeper("node-21:2181,node-22:2181", 30000, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("事件类型为:" + event.getType());System.out.println("事件发生的路径:" + event.getPath());System.out.println("通知状态为:" +event.getState());}});// 创建一个目录节点zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); // 创建一个子目录节点zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); System.out.println(new String(zk.getData("/testRootPath",false,null))); // 取出子目录节点列表System.out.println(zk.getChildren("/testRootPath",true)); // 修改子目录节点数据zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1); System.out.println("目录节点状态:["+zk.exists("/testRootPath",true)+"]"); // 创建另外一个子目录节点zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo",true,null))); // 删除子目录节点zk.delete("/testRootPath/testChildPathTwo",-1); zk.delete("/testRootPath/testChildPathOne",-1); // 删除父目录节点zk.delete("/testRootPath",-1);zk.close();
}
ZooKeeper选举机制
zookeeper默认的算法是FastLeaderElection,采用投票数大于半数则胜出的逻辑。
概念
- 服务器ID
比如有三台服务器,编号分别是1,2,3。
编号越大在选择算法中的权重越大。 - 选举状态
LOOKING,竞选状态。
FOLLOWING,随从状态,同步leader状态,参与投票。
OBSERVING,观察状态,同步leader状态,不参与投票。
LEADING,领导者状态。 - 数据ID
服务器中存放的最新数据version。
值越大说明数据越新,在选举算法中数据越新权重越大。 - 逻辑时钟
也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。
全新集群选举
假设目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
- 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking。
- 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
- 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
- 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
- 服务器5启动,后面的逻辑同服务器4成为小弟。
非全新集群选举
对于运行正常的zookeeper集群,中途有机器down掉,需要重新选举时,选举过程就需要加入数据ID、服务器ID和逻辑时钟。
- 数据ID:数据新的version就大,数据每次更新都会更新version。
- 服务器ID:就是我们配置的myid中的值,每个机器一个。
- 逻辑时钟:这个值从0开始递增,每次选举对应一个值。 如果在同一次选举中,这个值是一致的。
这样选举的标准就变成:
1、逻辑时钟小的选举结果被忽略,重新投票;
2、统一逻辑时钟后,数据id大的胜出;
3、数据id相同的情况下,服务器id大的胜出;
根据这个规则选出leader。
ZooKeeperZooKeeper Java API
- org.apache.zookeeper.Zookeeper
Zookeeper 是在Java中客户端主类,负责建立与zookeeper集群的会话,并提供方法进行操作。 - org.apache.zookeeper.Watcher
Watcher接口表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)。 - process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理。
基本使用
建立java maven项目,引入maven pom坐标。
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.9</version>
</dependency>
java代码
public static void main(String[] args) throws Exception {// 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher)ZooKeeper zk = new ZooKeeper("node-1:2181,node-2:2181", 30000, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("事件类型为:" + event.getType());System.out.println("事件发生的路径:" + event.getPath());System.out.println("通知状态为:" +event.getState());}});zk.create("/myGirls", "性感的".getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);zk.close();
更多操作示例
public static void main(String[] args) throws Exception {// 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher)ZooKeeper zk = new ZooKeeper("node-21:2181,node-22:2181", 30000, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("事件类型为:" + event.getType());System.out.println("事件发生的路径:" + event.getPath());System.out.println("通知状态为:" +event.getState());}});// 创建一个目录节点zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); // 创建一个子目录节点zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); System.out.println(new String(zk.getData("/testRootPath",false,null))); // 取出子目录节点列表System.out.println(zk.getChildren("/testRootPath",true)); // 修改子目录节点数据zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1); System.out.println("目录节点状态:["+zk.exists("/testRootPath",true)+"]"); // 创建另外一个子目录节点zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo",true,null))); // 删除子目录节点zk.delete("/testRootPath/testChildPathTwo",-1); zk.delete("/testRootPath/testChildPathOne",-1); // 删除父目录节点zk.delete("/testRootPath",-1);zk.close();
}
ZooKeeper选举机制
zookeeper默认的算法是FastLeaderElection,采用投票数大于半数则胜出的逻辑。
概念
- 服务器ID
比如有三台服务器,编号分别是1,2,3。
编号越大在选择算法中的权重越大。 - 选举状态
LOOKING,竞选状态。
FOLLOWING,随从状态,同步leader状态,参与投票。
OBSERVING,观察状态,同步leader状态,不参与投票。
LEADING,领导者状态。 - 数据ID
服务器中存放的最新数据version。
值越大说明数据越新,在选举算法中数据越新权重越大。 - 逻辑时钟
也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。
全新集群选举
假设目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
- 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking。
- 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
- 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
- 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
- 服务器5启动,后面的逻辑同服务器4成为小弟。
非全新集群选举
对于运行正常的zookeeper集群,中途有机器down掉,需要重新选举时,选举过程就需要加入数据ID、服务器ID和逻辑时钟。
- 数据ID:数据新的version就大,数据每次更新都会更新version。
- 服务器ID:就是我们配置的myid中的值,每个机器一个。
- 逻辑时钟:这个值从0开始递增,每次选举对应一个值。 如果在同一次选举中,这个值是一致的。
这样选举的标准就变成:
1、逻辑时钟小的选举结果被忽略,重新投票;
2、统一逻辑时钟后,数据id大的胜出;
3、数据id相同的情况下,服务器id大的胜出;
根据这个规则选出leader。
发布评论