wiki中对zookeeper的大概介绍
- ZooKeeper主要服务于分布式系统,可以用ZooKeeper来做:统一配置管理、统一命名服务、分布式锁、集群管理。
- 使用分布式系统就无法避免对节点管理的问题(需要实时感知节点的状态、对节点进行统一管理等等),而由于这些问题处理起来可能相对麻烦和提高了系统的复杂性,ZooKeeper作为一个能够通用解决这些问题的中间件就应运而生了。
那为什么zookeeper能做那么多事呢,首先我们来看看它的数据结构。
zookeeper与redis一样,都是C/S结构(客户端和服务端),可以看做是一个树,每个节点称之为Znode。
-
短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除
- 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除
并且zookeeper还需要通过监听器来监听Znode节点数据变化以及java子节点的增减变化
通过监听+Znode节点(持久/短暂[临时]),ZooKeeper就可以玩出这么多花样了(统一配置管理、统一命名服务、分布式锁、集群管理...)。
1.统一配置管理
所谓统一配置管理,就是在分布式系统中,将多个系统的配置文件的公共配置都提取出来,放入一个新的yml中,而这个yml配置文件放在Znode节点上,
其他系统都监听着Znode这个节点,如果发生变化及时响应。
流程图:
流程图解释:考虑到所有存储系统中,数据库还是比较成熟可靠的,所以这些配置信息,最终在db中存储一份。
刚开始时,配置管理中心从db中加载公用配置信息,然后同步写入ZK中,然后各子应用从ZK中读取配置,并监听配置的变化(这在ZK中通过Watcher很容易实现)。
如果配置要修改,同样也先在配置管理中心中修改,然后持久化到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;
}