1.3 Zookeeper的架构
Zookeeper本身就时一个文件存储系统:Zookeeper内部存储着大量的znode,每一个znode节点都可以有多个子节点,每一个znode都可以单独的存储数据。
- 持久的znode:永久的保存在Zookeeper
- 持久有序的znode:永久的保存在Zookeeper。添加节点时,自动在节点名称后追加一个有序的序号。
- 临时的znode:客户端和Zookeeper服务断开连接后,当前znode自动删除。
- 临时有序的znode:客户端和Zookeeper服务断开连接后,当前znode自动删除。添加节点时,自动在节点名称后追加一个有序的序号。
Zookeeper提供的监听通知机制:客户端可以监听Zookeeper服务中的znode,在znode改变时,Zookeeper会通知所有监听的客户端。
1.4 Zookeeper常用命令
- 查询:
- 创建:
- create [-s] [-e] znode znode数据:创建节点,-s代表有序节点,-e代表临时节点。
- 修改:
- set znode znode数据:修改znode的数据,zxid数据越新,zxid越大。
- 删除:
- delete znode:删除空节点
- rmr znode:删节点,跑路。(rmr看版本,有的版本是deleteall)
1.5 Zookeeper集群的架构&投票机制
Zookeeper集群架构:
- Zookeeper的集群是有Leader的。
- Leader宕机后,Zookeeper集群不会对外提供功能。
- Zookeeper内部会存在投票机制,重新选举一个Leader。
- Leader可以执行读写的操作。
- Slave可以执行读的操作。
Zookeeper集群节点的解决:
- Leader:
- 执行处理读和写的操作。
- Leader是唯一可以处理写操作的, 并且在执行写操作时,会根据一个FIFO的队列来保证写数据的顺序性。
- 其他节点的唯一调度者。
- Follower:
- 执行读操作。
- 在执行写操作时,进行投票。
- 在重新选举Leader时,会参与投票。
- Observer:
- 执行读操作。
- Looking:
- 在Zookeeper节点刚刚启动时,寻找Leader。
Zookeeper集群的选举策略:
- 选举数据最新的节点,根据数据的zxid判断。
- 如果zxid相同,根据myid决定Leader。
1.6 搭建Zookeeper集群
# 当前3.4.14的版本, 不需要指定;2181,如果采用最新zookeeper,需要添加;2181
version: "3.1"
services:
zk1:
image: 10.0.134.175:5000/zookeeper:3.4.14
container_name: zk1
restart: always
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zk1:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888
zk2:
image: 10.0.134.175:5000/zookeeper:3.4.14
container_name: zk2
restart: always
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zk1:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888
zk3:
image: 10.0.134.175:5000/zookeeper:3.4.14
container_name: zk3
restart: always
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zk1:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888
1.7 Java操作Zookeeper
导入依赖
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.14</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.2.0</version> </dependency>
Java连接Zookeeper
public static CuratorFramework cf(){ //1. 指定重试策略 3秒重试一次,一共重试2次. RetryPolicy retry = new ExponentialBackoffRetry(1000,2);
//2. 成功构建出链接Zookeeper的对象 CuratorFramework cf = CuratorFrameworkFactory.builder() .connectString("10.0.131.23:2181,10.0.131.23:2182,10.0.131.23:2183") .retryPolicy(retry) .build(); //3. 开启cf cf.start(); //4. 返回 return cf; }
Java操作Zookeeper
public class Demo1 {
@Test
public void getChildren() throws Exception {
CuratorFramework cf = ZkUtil.cf();List znodeList = cf.getChildren().forPath("/");
for (String s : znodeList) {
System.out.println(s);
}cf.close();
}@Test
public void create() throws Exception {
CuratorFramework cf = ZkUtil.cf();cf.create().withMode(CreateMode.PERSISTENT).forPath("/qf",“哈哈哈”.getBytes());
cf.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/qf2",“嘿嘿嘿”.getBytes());
cf.create().withMode(CreateMode.EPHEMERAL).forPath("/qf3",“看不见我”.getBytes());
cf.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/qf4",“看不见我”.getBytes());
cf.close();
}@Test
public void getData() throws Exception {
CuratorFramework cf = ZkUtil.cf();byte[] bytes = cf.getData().forPath("/qf");
System.out.println(new String(bytes,“UTF-8”));cf.close();
}@Test public void setData() throws Exception { CuratorFramework cf = ZkUtil.cf(); cf.setData().forPath("/qf","嘻嘻嘻".getBytes()); cf.delete().deletingChildrenIfNeeded().forPath("/qf20000000002"); Stat stat = cf.checkExists().forPath("/cluster"); System.out.println(stat); cf.close(); } }
Zookeeper的监听通知机制
@Test public void listener() throws Exception { CuratorFramework cf = ZkUtil.cf();
NodeCache nodeCache = new NodeCache(cf,"/qf");
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
// 在监听的节点改变后,获取节点信息
byte[] data = nodeCache.getCurrentData().getData();
String path = nodeCache.getCurrentData().getPath();
Stat stat = nodeCache.getCurrentData().getStat();
System.out.println(“监听的是:” + path + ",现在数据为: " + new String(data,“UTF-8”) + ",当前节点状态信息: " + stat );
}
});// !!!开始监听!!!
nodeCache.start();
System.out.println(“开始监听!!!”);System.in.read();
cf.close();
}