3.1.2 选举机制(面试 重点)
3.1.3 ZK 集群启动停止脚本
1)在 hadoop102 的/home/atguigu/bin 目录下创建脚本
[atguigu@hadoop102 bin]$ vim zk.sh
在脚本中编写如下内容
#!/bin/bash case $1 in "start"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 启动 ------------ ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start" done };; "stop"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 停止 ------------ ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop" done };; "status"){ for i in hadoop102 hadoop103 hadoop104 do echo ---------- zookeeper $i 状态 ------------ ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status" done };; esac
2)增加脚本执行权限
[atguigu@hadoop102 bin]$ chmod u+x zk.sh
3)Zookeeper 集群启动脚本
[atguigu@hadoop102 module]$ zk.sh start
4)Zookeeper 集群停止脚本
[atguigu@hadoop102 module]$ zk.sh stop
3.2 客户端 命令行 操作
3.2.1 命令行语法
1) 启动客户端
[atguigu@hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh -server hadoop102:2181
2) 显示所有操作命令
[zk: hadoop102:2181(CONNECTED) 1] help
3.2.2 znode 节点数据信息
1) 查看当前znode 中所包含的内容
[zk: hadoop102:2181(CONNECTED) 0] ls /
[zookeeper]
2) 查看当前节点详细 数据
[zk: hadoop102:2181(CONNECTED) 5] ls -s /
[zookeeper]cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
(1)czxid:创建节点的事务 zxid
每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。事务 ID 是 ZooKeeper 中所有修改总的次序。每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前发生。
(2)ctime:znode 被创建的毫秒数(从 1970 年开始)
(3)mzxid:znode 最后更新的事务 zxid
(4)mtime:znode 最后修改的毫秒数(从 1970 年开始)
(5)pZxid:znode 最后更新的子节点 zxid
(6)cversion:znode 子节点变化号,znode 子节点修改次数
(7)dataversion:znode 数据变化号
(8)aclVersion:znode 访问控制列表的变化号
(9)ephemeralOwner:如果是临时节点,这个是 znode 拥有者的 session id。如果不是
临时节点则是 0。
(10)dataLength:znode 的数据长度
(11)numChildren:znode 子节点数量
3.2.3 节点类型 (持久/ 短暂/ 有序号/)
1) 分别创建2 个普通节点 (永久节点 + 不带序号)
注意:创建节点时,要赋值
2) 获得节点的值
[zk: localhost:2181(CONNECTED) 5] get -s /sanguo diaochan
3) 创建带序号的节点 (永久节点 + 带序号)
(1)先创建一个普通的根节点/sanguo/weiguo
(2)创建带序号的节点
如果原来没有序号节点,序号从 0 开始依次递增。如果原节点下已有 2 个节点,则再排序时从 2 开始,以此类推。
4) 创建短暂节点 (短暂节点 + 不带序号 or 带序号)
(1)创建短暂的不带序号的节点
(2)创建短暂的带序号的节点
(3)在当前客户端是能查看到的
(4)退出当前客户端然后再重启客户端
[zk: localhost:2181(CONNECTED) 12] quit [atguigu@hadoop104 zookeeper-3.5.7]$ bin/zkCli.sh
(5)再次查看根目录下短暂节点已经删除
5) 修改节点数据值
3.2.4 监听器原理
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
1) 节点的值变化监听
(1)在 hadoop104 主机上注册监听/sanguo 节点数据变化
[zk: localhost:2181(CONNECTED) 26] get -w /sanguo
(2)在 hadoop103 主机上修改/sanguo 节点的数据
[zk: localhost:2181(CONNECTED) 1] set /sanguo "xisi"
(3)观察 hadoop104 主机收到数据变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged
path:/sanguo
注意:在hadoop103再多次修改/sanguo的值,hadoop104上不会再收到监听。因为注册一次,只能监听一次。想再次监听,需要再次注册。
2) 节点的子节点变化监听(路径变化)
(1)在 hadoop104 主机上注册监听/sanguo 节点的子节点变化
[zk: localhost:2181(CONNECTED) 1] ls -w /sanguo [shuguo, weiguo]
(2)在 hadoop103 主机/sanguo 节点上创建子节点
[zk: localhost:2181(CONNECTED) 2] create /sanguo/jin "simayi" Created /sanguo/jin
(3)观察 hadoop104 主机收到子节点变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged
path:/sanguo
注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册。
3.2.5 节点删除与查看 看
1) 删除节点
[zk: localhost:2181(CONNECTED) 4] delete /sanguo/jin
2) 递归删除节点
[zk: localhost:2181(CONNECTED) 15] deleteall /sanguo/shuguo
3) 查看节点状态
[zk: localhost:2181(CONNECTED) 17] stat /sanguo
cZxid = 0x100000003
ctime = Wed Aug 29 00:03:23 CST 2018
mZxid = 0x100000011
mtime = Wed Aug 29 00:21:23 CST 2018
pZxid = 0x100000014
cversion = 9
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1
3.3 客户端 API 操作
前提:保证 hadoop102、hadoop103、hadoop104 服务器上 Zookeeper 集群服务端启动。
3.3.1 IDEA 环境 搭建
1) 创建一个 工程:zookeeper
2) 添加pom 文件
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.1</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.5.7</version> </dependency>
3) ) 拷贝log4j.properties 文件到项目根目录
需要在项目的 src/main/resources 目录下,新建一个文件,命名为“log4j.properties”,在文件中填入。
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
4 )创建包名com.rg.zk
5 )创建类名称zkClient
3.3.2 创建 ZooKeeper 客户端
public class zkClient { //注意逗号后面不能有空格. private String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181"; private int sessionTimeout = 5000; private ZooKeeper zkClient; @Before public void init() throws IOException { /** * connectString:要连接的Zookeeper的客户端. * sessionTimeout:超时时间 * Watcher:监听器 */ zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { System.out.println("--------------------------------"); //这里意思就是你只要执行zk的api指令,就会走监听器重写的方法,最后加一个延迟,主线程睡眠但是监听器还在 //本质:是让监听器线程一直存在着... //再次启动监听... List <String> children = null; try { children = zkClient.getChildren("/", true); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } for (String child : children) { System.out.println(child); } System.out.println("--------------------------------"); } }); } }
3.3.3 创建子节点
//创建节点 @Test public void create() throws KeeperException, InterruptedException { /** * 参数 1:要创建的节点的路径; * 参数 2:节点数据 ; * 参数 3:节点权限 ; * 参数 4:节点的类型 */ String nodeCreated = zkClient.create("/atguigu", "ss.avi".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); }