ZooKeeper-znode概念与使用
可以将ZK看作一个具有高可用性特征的文件系统。这个文件系统中没有文件和目录,而是统一使用节点(znode)的概念,称为znode。znode既可以作为保存数据的容器(如同文件),也可以作为保存其他znode的容器(如同目录)。所有的znode构成了一个层次化的命名空间,一种自然的建立组成员列表的方式就是利用这种层次结构,创建一个以组名为节点名的znode作为父节点,然后以组成员名(服务器名)为节点名来创建作为子节点的znode。
创建组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | package com.zhen.zookeeper.createGroup; import java.io.IOException; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; /** * @author FengZhen * @date 2018年10月13日 * 创建组 */ public class CreateGroup implements Watcher{ private static final int SESSION_TIMEOUT = 5000; private ZooKeeper zk; private CountDownLatch connectedSignal = new CountDownLatch(1); public void connect(String hosts) throws IOException, InterruptedException { /** * hosts:ZooKeeper服务的主机地址(可指定端口,默认是2181) * SESSION_TIMEOUT:以毫秒为单位的会话超时参数(此处为5秒) * this:Watcher对象的实例。Watcher对象接收来自于ZooKeeper的回调,以获得各种事件的通知。 */ zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this ); connectedSignal.await(); } /** * 当客户端已经与ZK建立连接后,Watcher的process方法会被调用 * 参数是一个用于表示该连接的事件。 */ public void process(WatchedEvent event ) { //连接事件 if ( event .getState() == KeeperState.SyncConnected) { /** * 通过调用CountDownLatch的countDown方法来递减它的计数器。 * 锁存器(latch)被创建时带有一个值为1的计数器,用于表示在它释放所有等待线程之前需要发生的事件数。 * 在调用一次countDown方法之后,计数器的值变为0,则await方法返回。 */ connectedSignal.countDown(); } } public void create(String groupName) throws KeeperException, InterruptedException { String path = "/" + groupName; /** * 用ZK的create方法创建一个新的ZK的znode * path:路径(用字符串表示) * null:znode的内容(字节数组,此处为空值) * Ids.OPEN_ACL_UNSAFE:访问控制列表(简称ACL,此处为完全开放的ACL,允许任何客户端对znode进行读写) * CreateMode.PERSISTENT:znode类型 * znode类型可以分为两种:1.短暂的(ephemeral) 2.持久的(persistent) * 创建znode的客户端断开连接时,无论客户端是明确断开还是因为任何原因而终止,短暂znode都会被ZK服务删除。持久znode不会被删除。 * create方法的返回值是ZK所创建的节点路径 */ String createdPath = zk.create(path, null , Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System. out .println( "Created " + createdPath); } public void close() throws InterruptedException { zk.close(); } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { String hosts = "localhost:2181" ; String groupName = "zoo" ; CreateGroup createGroup = new CreateGroup(); createGroup.connect(hosts); createGroup.create(groupName); createGroup.close(); } } |
提供一个连接类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package com.zhen.zookeeper; import java.io.IOException; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.Watcher.Event.KeeperState; /** * @author FengZhen * @date 2018年10月13日 * 等待与ZK建立连接 */ public class ConnectionWatcher implements Watcher{ private static final int SESSION_TIMEOUT = 5000; protected ZooKeeper zk; private CountDownLatch connectedSignal = new CountDownLatch(1); public void connect(String hosts) throws IOException, InterruptedException { /** * hosts:ZooKeeper服务的主机地址(可指定端口,默认是2181) * SESSION_TIMEOUT:以毫秒为单位的会话超时参数(此处为5秒) * this:Watcher对象的实例。Watcher对象接收来自于ZooKeeper的回调,以获得各种事件的通知。 */ zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this ); connectedSignal.await(); } /** * 当客户端已经与ZK建立连接后,Watcher的process方法会被调用 * 参数是一个用于表示该连接的事件。 */ public void process(WatchedEvent event ) { //连接事件 if ( event .getState() == KeeperState.SyncConnected) { /** * 通过调用CountDownLatch的countDown方法来递减它的计数器。 * 锁存器(latch)被创建时带有一个值为1的计数器,用于表示在它释放所有等待线程之前需要发生的事件数。 * 在调用一次countDown方法之后,计数器的值变为0,则await方法返回。 */ connectedSignal.countDown(); } } public void close() throws InterruptedException { zk.close(); } } |
加入组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | package com.zhen.zookeeper.joinGroup; import java.io.IOException; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs.Ids; import com.zhen.zookeeper.ConnectionWatcher; /** * @author FengZhen * @date 2018年10月13日 * 加入组-注册组成员 */ public class JoinGroup extends ConnectionWatcher{ public void join (String groupName, String memberName) throws KeeperException, InterruptedException { String path = "/" + groupName + "/" + memberName; //创建短暂znode作为组znode的子节点 String createdPath = zk.create(path, null , Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System. out .println( "Created " + createdPath); } public static void main(String[] args) throws IOException, InterruptedException, KeeperException { String hosts = "localhost:2181" ; String groupName = "zoo" ; String memberName = "member1" ; JoinGroup joinGroup = new JoinGroup(); joinGroup.connect(hosts); joinGroup. join (groupName, memberName); Thread.sleep(Long.MAX_VALUE); } /** * echo dump | nc localhost 2181 SessionTracker dump: Session Sets (3): 0 expire at Sat Oct 13 15:57:48 CST 2018: 0 expire at Sat Oct 13 15:57:50 CST 2018: 1 expire at Sat Oct 13 15:57:52 CST 2018: 0x166594274c90001 ephemeral nodes dump: Sessions with Ephemerals (1): 0x166594274c90001: /zoo/member1 */ } |
列出组成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | package com.zhen.zookeeper.listGroup; import java.io.IOException; import java.util.List; import org.apache.zookeeper.KeeperException; import com.zhen.zookeeper.ConnectionWatcher; /** * @author FengZhen * @date 2018年10月13日 * 列出组成员 */ public class ListGroup extends ConnectionWatcher{ public void list(String groupName) { String path = "/" + groupName; try { /** * 输出一个znode的子节点列表 * path:该znode的路径 * false:观察标志 * 如果在一个znode上设置了观察标志,那么一旦该znode的状态改变,关联的观察(Watcher)会被触发。 * 虽然此处没有使用观察,但在查看一个znode的子节点时,通过设置观察可以让应用程序接收到组成员加入、退出和组被删除的有关通知 */ List<String> children = zk.getChildren(path, false ); if (children.isEmpty()) { System. out .printf( "No members in group %s\n" , groupName); System.exit(1); } for (String child : children) { System. out .println(child); } } catch (KeeperException e) { System. out .printf( "Group %s does not exist\n" , groupName); System.exit(1); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException, InterruptedException { String hosts = "localhost:2181" ; String groupName = "zoo" ; ListGroup listGroup = new ListGroup(); listGroup.connect(hosts); listGroup.list(groupName); listGroup.close(); } /** * 也可使用命令行工具 * ./zkCli.sh -server localhost:2181 ls /zoo * Connecting to localhost:2181 2018-10-13 16:26:10,856 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT 2018-10-13 16:26:10,860 [myid:] - INFO [main:Environment@100] - Client environment:host.name=192.168.1.109 2018-10-13 16:26:10,860 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.8.0_162 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../build/classes:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../build/lib/*.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../conf: 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/Users/FengZhen/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:. 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/var/folders/tr/vc5hfpsd2c56s7m9wh93401h0000gn/T/ 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:java.compiler=<NA> 2018-10-13 16:26:10,863 [myid:] - INFO [main:Environment@100] - Client environment:os.name=Mac OS X 2018-10-13 16:26:10,864 [myid:] - INFO [main:Environment@100] - Client environment:os.arch=x86_64 2018-10-13 16:26:10,864 [myid:] - INFO [main:Environment@100] - Client environment:os.version=10.13.4 2018-10-13 16:26:10,864 [myid:] - INFO [main:Environment@100] - Client environment:user.name=FengZhen 2018-10-13 16:26:10,864 [myid:] - INFO [main:Environment@100] - Client environment:user.home=/Users/FengZhen 2018-10-13 16:26:10,864 [myid:] - INFO [main:Environment@100] - Client environment:user.dir=/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin 2018-10-13 16:26:10,865 [myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@799f7e29 2018-10-13 16:26:10,898 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error) 2018-10-13 16:26:11,014 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session 2018-10-13 16:26:11,024 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x166594274c90006, negotiated timeout = 30000 WATCHER:: WatchedEvent state:SyncConnected type:None path:null [member1] */ } |
删除组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | package com.zhen.zookeeper.deleteGroup; import java.io.IOException; import java.util.List; import org.apache.zookeeper.KeeperException; import com.zhen.zookeeper.ConnectionWatcher; /** * @author FengZhen * @date 2018年10月13日 * 删除组 * */ public class DeleteGroup extends ConnectionWatcher{ public void delete(String groupName) { String path = "/" + groupName; try { List<String> children = zk.getChildren(path, false ); for (String child : children) { zk.delete(path + "/" + child, -1); } /** * delete方法有两个参数 * path:节点路径 * -1:版本号 * 如果所提供的版本号与znode的版本号一致,ZK会删除这个znode。 * 这是一种乐观的加锁机制,使客户端能够检测出对znode的修改冲突。 * 通过将版本号设置为-1,可以绕过这个版本检测机制,不管znode的版本号是什么而直接将其删除。 * ZK不支持递归删除,因此在删除父节点之前必须先删除子节点 */ zk.delete(path, -1); } catch (KeeperException e) { System. out .printf( "Group %s does not exist\n" , groupName); System.exit(1); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException, InterruptedException { String hosts = "localhost:2181" ; String groupName = "zoo" ; DeleteGroup deleteGroup = new DeleteGroup(); deleteGroup.connect(hosts); deleteGroup.delete(groupName); deleteGroup.close(); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示