那为何zookeeper能作那么多事呢,首先咱们来看看它的数据结构。java
zookeeper与redis同样,都是C/S结构(客户端和服务端),能够看作是一个树,每一个节点称之为Znode。node
短暂/临时(Ephemeral):当客户端和服务端断开链接后,所建立的Znode(节点)会自动删除redis
而且zookeeper还须要经过监听器来监听Znode节点数据变化以及java子节点的增减变化数据库
经过监听+Znode节点(持久/短暂[临时]),ZooKeeper就能够玩出这么多花样了(统一配置管理、统一命名服务、分布式锁、集群管理...)。数据结构
所谓统一配置管理,就是在分布式系统中,将多个系统的配置文件的公共配置都提取出来,放入一个新的yml中,而这个yml配置文件放在Znode节点上,分布式
其余系统都监听着Znode这个节点,若是发生变化及时响应。ide
流程图:spa
流程图解释:考虑到全部存储系统中,数据库仍是比较成熟可靠的,因此这些配置信息,最终在db中存储一份。.net
刚开始时,配置管理中心从db中加载公用配置信息,而后同步写入ZK中,而后各子应用从ZK中读取配置,并监听配置的变化(这在ZK中经过Watcher很容易实现)。code
若是配置要修改,一样也先在配置管理中心中修改,而后持久化到DB,接下来同步更新到ZK,因为各子应用会监听数据变化,因此ZK中的配置变化,会实时传递到子应用中,子应用固然也无需重启。
部分代码以下(这里的Config是自定义的model类,建立了个znode节点zkConfig),
想要了解ZkClient能够点击https://blog.csdn.net/t1dmzks/article/details/78440717
/** * 修改公共配置文件同步到zookeeper */ public void syncConfigToZk(){ //本地zookeeper ZkClient zk = new ZkClient("localhost:2181"); //是否存在zkconfig节点 if(!zk.exists("/zkConfig")){ //建立zookeeper节点 zk.createPersistent("/zkConfig",true); } //更新节点 zk.writeData("/zkConfig", config); zk.close(); } /** * 监听znode节点变化 */ public Config getConfig() { ZkClient zk = new ZkClient("localhost:2181"); config = (Config)zk.readData("/zkConfig"); System.out.println("加载到配置:"+config.toString()); //监听zookeeper的zkConfig节点变化 zk.subscribeDataChanges("/zkConfig", new IZkDataListener(){ @Override public void handleDataChange(String arg0, Object arg1) throws Exception { config = (Config) arg1; System.out.println("监听到配置文件被修改:"+config.toString()); } @Override public void handleDataDeleted(String arg0) throws Exception { config = null; System.out.println("监听到配置文件被删除"); } }); return config; }