一、zookeeper是分布式数据管理与协调框架,不适合存储大量数据,基础paxos算法 --主从选举
(原子消息广播协议),zookeeper一般都是集群存在,奇数个节点
1、顺序一致性
按照发起的顺序应用到zookeeper
客户端发送消息给zookeeper,消息遵循原子消息广播,消息都同步后才会返回客户端,会加锁,这个时候其他客户端不能操作这条消息,如果多个zookeeper节点间消息同步未成功,例如网络不通的时候,就会返回失败
2、原子性
3、单一视图
4、可靠性
zookeeper 将全量数据存储在内存中,针对非事务效率非常高
一半节点挂掉的时候就不对外提供服务了
zookeeper 是以简单的树形结构来进行相互协调,类似于一个标准的文件系统,
角色
leader
follower
observer
二、应用场景
配置管理 配置文件的动态变更
集群管理
发布与订阅
数据库切换
分布式锁,队列管理等
分布式日志收集
比如多个机器中的项目都有一份配置文件,修改一个配置文件,需要把修改的文件都同步到每个机器的每个项目中 ,就可以用zookeeper,项目中设置watcher,监听某个节点路径的信息
(数据量比较小,数据内容在运行时动态发生变化,集群中各个节点共享信息配置一致)
curator 框架 操作zookeeper 的框架
三、安装
解压到/usr/local/下
tar -zxvf zookeeper-3.4.5.tar.gz -C /usr/local/
把 zookeeper-3.4.5目录 移动到zookeeper
mv zookeeper-3.4.5/ zookeeper
也可以在后面这个地址下载 http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz
如果链接打不开,就先打开 http://mirror.bit.edu.cn/apache/zookeeper , 再选择版本。
更改zoo_sample.cfg 改成zoo.cfg
修改zoo.cfg
dataDir=/mnt/soft/zookeeper-3.4.5/data
/etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.13/
export PATH=$PATH:$ZOOKEEPER_HOME/bin
source /etc/profile
[root@localhost local]# cd /usr/local/zookeeper-3.4.13/bin [root@localhost bin]# ./zkServer.sh start
./zkServer.sh status
默认端口2181
客户端
[root@localhost bin]# ./zkCli.sh
配置文件参数
数据结构
zookeeper命令
ls /path 查找
create /path value 创建并赋值,不能重复创建,创建成功返回path,不允许递归创建节点,如果父节点不存在
create /path/path
get /path 获取
set /path value 设值 value可以时 字符串 或文件,如果是文件的 存的是内容,或是二进制字节码
rmr /path 递归删除节点
delete /path/child 删除指定某个节点
四、java客户端调用
zookeeper客户端和服务器端会话的建立是一个异步的过程
一般用curator 调用客户端
节点类型
1、持久节点
2、持久顺序节点
3、临时节点 可以利用临时节点创建分布式锁 ,只在当前会话中有效,会话结束 path则消失
4、临时顺序节点
zookeeper 原始API
不允许递归创建节点
节点内容必须时字节数组,不支持序列化,如果需要序列化,可使用第三方框架 hessian,kryo
关闭防火墙
systemctl stop firewalld.service
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency>
添加log4j.properties
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.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class ZkTest { /** * 集群地址 */ private static final String CONNECT_ADDRES = "192.168.233.100:2181"; /** * 超时时间 */ private static final int SESSIONTIME = 2000; private static final CountDownLatch countDownLatch = new CountDownLatch(1); public static void main(String[] args) throws Exception, InterruptedException, KeeperException { ZooKeeper zk = new ZooKeeper(CONNECT_ADDRES, SESSIONTIME, new Watcher() { public void process(WatchedEvent event) { // 获取时间的状态 KeeperState keeperState = event.getState(); EventType tventType = event.getType(); // 如果是建立连接 if (KeeperState.SyncConnected == keeperState) { if (EventType.None == tventType) { // 如果建立连接成功,则发送信号量,让后阻塞程序向下执行 countDownLatch.countDown(); System.out.println("zk 建立连接"); } }else { System.out.println("zk 建立失败"); } } }); // 进行阻塞 countDownLatch.await(); // 创建父节点 // String result = zk.create("/testRott", "12245465".getBytes(), // Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // System.out.println("result:" + result); // 创建子节点 String result = zk.create("/testRott/children", "children 12245465".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("result:" + result); zk.close(); } }
五、zookeeper 事件监听
客户端发送请求到 某一个节点zookeeper,该节点就会建立一个watcher,这个watcher的动作事件叫watch,watch 是一次性的 ,boolean true 代表该watcher时候还监听
Watcher 可以监听某一个路径,对某一个路径设置监听
package com.itman; 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.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class ZkWatcher implements Watcher { /** * 集群地址 */ private static final String CONNECT_ADDRES = "169.254.197.135:2181"; private static ZooKeeper zooKeeper; /** * 超时时间 */ private static final int SESSIONTIME = 2000; public ZkWatcher() { createConnection(CONNECT_ADDRES, SESSIONTIME); } // zk节点、发生变更、删除、修改 、 新增 事件通知 public void process(WatchedEvent event) { KeeperState keeperState = event.getState(); // 事件类型 EventType eventType = event.getType(); // 节点名称 String path = event.getPath(); System.out.println( "#####process()####调用####keeperState:" + keeperState + ",eventType:" + eventType + ",path:" + path); if (KeeperState.SyncConnected == keeperState) { // 连接类型 if (EventType.None == eventType) { // 建立zk连接 System.out.println("建立zk连接成功!"); } // 创建类型 if (EventType.NodeCreated == eventType) { System.out.println("####事件通知,当前创建一个新的节点####路径:" + path); } // 修改类型 if (EventType.NodeDataChanged == eventType) { System.out.println("####事件通知,当前创建一个修改节点####路径:" + path); } // 删除类型 if (EventType.NodeDeleted == eventType) { System.out.println("####事件通知,当前创建一个删除节点####路径:" + path); } } System.out.println("####################################################"); System.out.println(); } // 创建zk连接 private void createConnection(String connectAddres, int sessiontime) { try { zooKeeper = new ZooKeeper(connectAddres, sessiontime, this); } catch (Exception e) { // TODO: handle exception } } // 创建节点 public void createNode(String path, String data) { try { String result = zooKeeper.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("创建节点成功....result:" + result); } catch (Exception e) { e.printStackTrace(); } } // 修改节点 public void updateNode(String path, String data) { try { zooKeeper.setData(path, data.getBytes(), -1); } catch (Exception e) { // TODO: handle exception } } // 删除节点 public void deleNode(String path) { try { zooKeeper.delete(path, -1); } catch (Exception e) { // TODO: handle exception } } public void close() { try { if (zooKeeper != null) zooKeeper.close(); } catch (Exception e) { // TODO: handle exception } } public static void main(String[] args) throws KeeperException, InterruptedException { ZkWatcher zkWatcher = new ZkWatcher(); // zkWatcher.createNode("/parent1", "6452852"); String path = "/parent1"; zooKeeper.exists(path, true); // zkWatcher.updateNode(path, "88888"); zkWatcher.deleNode(path); zkWatcher.close(); } }
六、zookeeper 安装认证
acl认证
七、zookeeper 第三方实现
zkclient
subscribeChildChanges("/super","")
只监听当前节点和当前节点下的新增和删除
subscribeDataChanges("/super","")
对父节点添加监听子节点变化
curator