网站如何免费做SEO优化,靖安县城乡规划建设局网站,山西太原今天的消息,苏州建网站的公司一站式服务公司1. Zookeeper节点信息
指定服务端#xff0c;启动客户端命令#xff1a;
bin/zkCli.sh -server 服务端主机名:端口号
1#xff09;ls / 查看根节点下面的子节点 ls -s / 查看根节点下面的子节点以及根节点详细信息 其中#xff0c;cZxid是创建节点的事务id#xff0c…1. Zookeeper节点信息
指定服务端启动客户端命令
bin/zkCli.sh -server 服务端主机名:端口号
1ls / 查看根节点下面的子节点 ls -s / 查看根节点下面的子节点以及根节点详细信息 其中cZxid是创建节点的事务id每次修改Zookeeper的状态都会产生一个事务id
ctime是节点被创建的毫秒数从1970年开始这里是zookeeper自带的默认节点其ctime就是0mZxid是节点最后被更新的事务id
mtime是节点最后修改的毫秒数pZxid是最后更新的子节点的事务idephemeralOwner如果是临时节点则表示拥有这个节点的s
ession id如果不是临时节点则为0
dataLength是该节点的数据长度
numChildren是该节点的子节点数量。
2. Zookeeper节点类型
持久节点客户端和服务端断开连接后创建的节点不删除
短暂/临时节点客户端和服务端断开连接后创建的节点删除
上面两种节点还可以继续分为带序号和不带序号的如果带序号节点名称后面会接一个数值顺序递增由父节点维护。 创建永久节点create path val 注意ls命令后面的路径不能以/结尾这里跟Linux不一样
查询节点的值get -s path 创建带序号的永久节点create -s path val 以相同的路径再次创建同名节点带序号的节点会自动序号加1不带序号的节点创建报错 以上是永久节点退出客户端之后这些节点依然存在
创建临时节点create -e path val 创建带序号的临时节点只需加上-s即可 因为已经有shuguoweiguowuguo所以新创建的带序号的临时节点的序号为3。
断开客户端之后上面创建的临时节点wuguo会被删除。
修改节点的值set path newVal 3. 监听原理 监听主要是通过getChildren和getData来实现表面上是获取节点子节点或者节点数据的方法但是第二个参数表示是否监听一般为true第二个参数也可以传一个自定义的监听器所以实现了监听当子节点发生增减或者节点数据发生变化时就会通知客户端触发process方法。getChildren和getData是Java API监听方式稍后介绍这里先介绍命令行监听。
命令行开启监听节点数据get -w path 在另一个会话端修改sanguo的节点值在本端会产生事件通知 再次在另一个会话端修改sanguo的节点值在本端不会产生事件通知因为监听只生效一次要想再次监听需要再次注册即执行get -w path。
监控子节点变化ls -w path
再另一个会话端创建一个子节点在本端会产生一个事件通知 节点删除delete path
删除节点及其下面的子节点deleteall path 查看节点状态stat path
4. Java API
添加pom依赖
dependencygroupIdorg.apache.zookeeper/groupIdartifactIdzookeeper/artifactIdversion3.5.7/version
/dependency
建立Zookeeper连接
Zookeeper zk new Zookeeper(connectString, sessionTimeout, new Watcher() {Overridepublic void process(WatchedEvent watchedEvent) {}
})
其中connectString是主机地址如果有多个主机用逗号隔开中间不能有空格。sessionTimeout是超时时间单位是微秒。第三个参数是监听器里面一般是根据事件类型以及事件路径来做相应的处理也可在里面继续调用getChildren或者getData方法实现持续监听。
一旦连接上Zookeeper之后就会调用到process方法里面一般会根据事件类型来对某个countDownLatch变量进行减1操作在主线程中会等待这个变量为0即等待Zookeeper连接上。
创建节点
String node zk.create(path, data, ZooDfs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
监控子节点的增删注册监听
ListString children zk.getChildren(path, true)for (String child : children) {System.out.println(child);
}
要想验证对子节点增删的监听首先在java主线程中添加一个睡眠的函数使其持续运行不至于很快结束然后在process回调中添加相应的打印代码比如继续getChildren打印子节点信息这样手动去添加节点会执行到process函数中的打印信息。
判断节点是否存在
Stat stat ck.exists(path, false);
System.out.println(stat null ? not exist : exist);
5. 写数据原理
1写请求直接发给Leader 其中只要有半数节点写完就可以发送ack给客户端其他没写的服务端稍后再写。
2) 写请求发给Follower 这里也是半数节点写完就发送ack给客户端所不同的是由接受写请求的Follower发送给客户端而不是Leader因为客户端最开始建立连接的是Follower。
6. 服务器动态上下线监听案例 分析客户端监听服务器的上下线本质是监听子节点的增删服务器启动时会去Zookeeper集群注册临时子节点使用的是create操作而客户端监听则是get操作。注意这里的服务器和客户端对于Zookeeper集群来说都是客户端。
于是代码主要分两部分服务器创建子节点和客户端监听子节点。
// 服务器
private Zookeeper zk;public static void main(String[] args) throws Exception {// 创建本类服务器类的对象DistributeServer server new DistributeServer();// 建立Zookeeper连接server.getConnect()// 注册即创建子节点server.register(args[0]);// 服务端业务逻辑睡觉server.business();
}private void business() throws Exception {Thread.sleep(Long.MAX_VALUE);
}private void register(String hostName) throws Exception {String create zk.create(/servers/ hostName, hostName.getBytes(), ZooDef.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMRAL_SEQUENTIAL);System.out.println(hostName is online);
}private void getConnect() throws Exception {zk new Zookeeper(xxx, 2000, new Watcher() {Overridepublic void process(WatchedEvent watchedEvent){}});
}
// 客户端
private Zookeeper zk;public static void main(String[] args) throws Exception {// 创建本类服务器类的对象DistributeClient client new DistributeClient();// 建立Zookeeper连接client.getConnect()// 注册即创建子节点client.getServerList();// 客户端业务逻辑睡觉client.business();
}private void business() throws Exception {Thread.sleep(Long.MAX_VALUE);
}private void getServerList() throws Exception {ListString children zk.getChildren(/servers, true);ListString servers new ArrayList;for (String child : children) {byte[] data zk.getData(/servers/ child, false, null);servers.add(new String(data));}System.out.println(servers);
}private void getConnect() throws Exception {zk new Zookeeper(xxx, 2000, new Watcher() {Overridepublic void process(WatchedEvent watchedEvent){getServerList();}});
}
验证时可以先验证客户端功能服务端可以先用create -e -s 来代替如果客户端功能ok再继续验证服务端功能。
7. 分布式锁案例 分析进程用客户端表示每个客户端进程会去Zookeeper中创建一个临时带序号的子节点如果子节点序号最小则表示获取到锁否则监听前一个序号更小的节点持有锁执行完业务之后会删除节点表示释放锁后面的节点/进场即可获取到锁。 private Zookeeper zk;
private String waitPath;
private String currentNode;
private CountDownLatch connectLatch new CountDownLatch(1);
private CountDownLatch waitLatch new CountDownLatch(1);public DistributeClient() throws Exception {// 创建本类服务器类的对象DistributeClient client new DistributeClient();// 建立Zookeeper连接getConnect()connectLatch.await();
}// 加锁创建临时节点并判断是否是序号最小的节点如果是则获取到锁处理业务如果不是则监听前一个序号较小的节点
public void lock() throws Exception {// currentNode是全路径名String currentNode zk.create(/locks/seq-, null, ZooDefs.Ids.OPEN_ACL_UNSAGE, CreateMode.EPHEMETAL_SEQUENTIAL);ListString children zk.getChildren(locks, false);if (children.size() 1) {return;} else {Collections.sort(children);String thisNode currentNode.substring(/locks/.length());int index children.indexOf(thisNode);if (index -1) {System.out.println(数据异常);} else if (index 0) {return;} else {// 监听前一个节点waitPath /locks/ children.get(index -1);zk.getData(waitPath, true, null);waitLatch.await();}}}public void unlock() throws Exception {zk.delete(currentNode, -1);
}private void getConnect() throws Exception {zk new Zookeeper(xxx, 2000, new Watcher() {Overridepublic void process(WatchedEvent watchedEvent) {if (watchedEvent.getType() Event.KeeperState.SyncConnected) {connectLatch.countDown(); }if (watchedEvent.getType() Event.EventType.NodeDeleted Event.getPath.equals(waitPath)) {waitLatch.countDown();}}});
} 测试步骤建立两个线程每个线程起一个客户端去加锁解锁加日志打印加锁解锁之间有睡眠运行这两个线程可以看到最终只有1个客户端去持有锁 8. Curator框架 上述分布式锁的案例中有如下缺点 1会话印布链接需要自己使用CountDownLatch处理 2监听需要重复注册 3代码较复杂 4不支持多节点删除与创建 因此引入Curator框架添加pom依赖 dependencygroupIdorg.apache.curator/groupIdartifactIdcurator-framework/artifactIdversion4.3.0/version
/dependency
dependencygroupIdorg.apache.curator/groupIdartifactIdcurator-recipes/artifactIdversion4.3.0/version
/dependency
dependencygroupIdorg.apache.curator/groupIdartifactIdcurator-client/artifactIdversion4.3.0/version
/dependency public static void main(String[] args) {// 获取分布式锁1InterProcessMutex lock1 new InterProcessMutex(getCuratorFramework, /locks);// 获取分布式锁2InterProcessMutex lock2 new InterProcessMutex(getCuratorFramework, /locks);// 启动两个线程分别加锁释放锁该锁可重入// 加锁: lock1.acquire(); 释放锁: lock1.release();
}private static CuratorFramework getCuratorFramework() {ExponentialBackoffRetry retry new ExponentialBackoffRetry(3000, 3);CuratorFramework client CuratorFrameworkFactory.builder().connectString(xxx).connectionTimeoutMs(2000).sessionTimeoutMs(2000).retryPolicy(retry).build();client.start();System.out.println(客户端启动成功);return client;
} 9. 面试题