对于Zookeeper的一些理解

本文涉及的产品
无影云电脑企业版,4核8GB 120小时 1个月
无影云电脑个人版,1个月黄金款+200核时
资源编排,不限时长
简介: 该文档介绍了如何使用ZooKeeper实现统一配置、命名服务和分布式锁以及集群管理。首先,为了解决多个系统重复配置的问题,提出了抽取公共配置到`common.yml`并存储在ZooKeeper中的方法,系统通过监听ZNode变化实时更新配置。接着,详细说明了配置管理的实现步骤,包括在服务器端将配置同步到ZooKeeper,以及客户端监听配置变更。此外,还解释了命名服务如何根据名称获取服务地址,并以域名访问为例进行了说明。最后,讨论了ZooKeeper实现的两种分布式锁策略,并阐述了其在集群管理中的应用,如检测节点状态变化和选举Master节点。

实现统一配置

实现思路

  • 比如我们现在有三个系统A、B、C,他们有三份配置,分别是ASystem.yml、BSystem.yml、CSystem.yml,然后,这三份配置又非常类似,很多的配置项几乎都一样。
  • 此时,如果我们要改变其中一份配置项的信息,很可能其他两份都要改。并且,改变了配置项的信息很可能就要重启系统。于是,我们希望把ASystem.yml、BSystem.yml、CSystem.yml相同的配置项抽取出来成一份公用的配置common.yml,并且即便common.yml改了,也不需要系统A、B、C重启。

实现方法

我们可以将common.yml这份配置放在ZooKeeper的Znode节点中,系统A、B、C监听着这个Znode节点有无变更,如果变更了,及时响应。

实现步骤

配置管理中心实现:

  1. 导入zkClient对应的jar。
  2. 实现工具类方法,完成从数据库加载配置、将配置文件保存到数据库、配置文件同步到zookeeper。
/**
   * 配置文件同步到zookeeper
   */
  public void syncConfigToZk(){
    ZkClient zk = new ZkClient("localhost:2181");
    if(!zk.exists("/zkConfig")){
      zk.createPersistent("/zkConfig",true);
    }
    zk.writeData("/zkConfig", config);
    zk.close();
  }
  1. 具体的代码是实现,将上面的1、2进行代码实现。运行就可以实现同步配置信息到zookeeper了,

客户端实现:

  1. 监听zookeeper中zkConfig对应的zoNode节点。
private Config config;
  public Config getConfig() {
    ZkClient zk = new ZkClient("localhost:2181");
    config = (Config)zk.readData("/zkConfig");
    System.out.println("加载到配置:"+config.toString());
    
    //监听配置文件修改
    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;
  }

统一命名服务

命名服务功能主要是根据指定名字来获取资源或服务的地址、提供者信息,利用zookeeper我们可以创建唯一标识路径,这个路径可以作为一个名字,指定集群中的集群,提供的服务的地址或者一个远程对象。这个路径就好比是一个仓库,这个仓库的地址是唯一的,这些仓库里面存了一些东西,当我们来到这个仓库,我们就能取到仓库里的东西。

比如说,现在我有一个域名www.liancan.com,而这个域名下有多台机器:

192.168.0.91

192.168.0.93

192.168.0.94

192.168.0.95

通过访问 www.liancan.com 就可以访问到我的机器,而不是通过 IP 去访问,如下图所示:

分布式锁

实现分布式锁有两种,一种是保持独占,一种是控制时序。

  1. 第一种方式
  1. 我们将zookeeper上的节点看成一把锁,通过createznode的方式来实现,所有客户端都去创建/distribute_lock节点,最终成功创建的那个客户端就拥有了这把锁。用完删掉自己创建的节点就释放锁。
  2. 缺点:
  1. 注意:不适用于客户端数量很大的情况,当一个客户端拥有第一把锁之后,所有的客户端都要去监听节点,节点的释放也会通知所有的客户端,这样会出现羊群效应。
  1. 第二种方式
  1. 假设/distribute_lock已经预先存在,所有的客户端都在它下面创建临时顺序编号目录节点,编号最小的获取锁
  2. 没有获取到锁的客户端就监听编号比自己小的前一个节点,因为节点是有顺序的,很容易找到自己创建的前一个节点。
  3. 当监听到前一个节点删除节点,即释放锁,该客户端就会获得锁。
  4. 这样避免所有的客户端只需要监听一个节点和节点删除需要通知所有客户端的情况。
  5. 实现思路:
  1. 客户端 A 拿到 /distribute_lock 节点下的所有子节点,经过比较,发现自己(id_001),是所有子节点最小的。所以得到锁。
  2. 客户端 B 拿到 /distribute_lock 节点下的所有子节点,经过比较,发现自己(id_002),不是所有子节点最小的。所以监听比自己小的节点 id_001 的状态。
  3. 客户端 C 拿到 /distribute_lock 节点下的所有子节点,经过比较,发现自己(id_003),不是所有子节点最小的。所以监听比自己小的节点 id_002 的状态。
  4. 等到客户端 A 执行完操作以后,将自己创建的节点 id_001 删除。通过监听,客户端 B 发现 id_001 节点已经删除了,发现自己已经是最小的节点了,于是顺利拿到锁。

集群管理

在分布式环境中,掌握集群中每个节点的状态,zookeeper做集群管理可以实现检测是否有机器加入或退出,还可以用来选举集群的master。

只要客户端 A 挂了,那/GroupMember/A这个节点就会删除,通过监听 GroupMember 下的子节点,客户端 B 和客户端 C 就能够感知到客户端 A 已经挂了(新增也是同理)

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
5月前
|
存储 分布式计算 算法
ZooKeeper
【6月更文挑战第21天】ZooKeeper
163 39
|
5月前
|
算法 Java Apache
你真的了解Zookeeper吗?
你真的了解Zookeeper吗?
42 0
|
运维 分布式计算 算法
Zookeeper解读
Zookeeper解读
67 0
|
存储 算法 Linux
Zookeeper
 ZooKeeper 是一种分布式协调服务,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper 通过其简单的架构和 API 解决了这个问题。ZooKeeper 允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。
146 0
|
JSON Linux Shell
zookeeper
zookeeper
159 0
|
存储 设计模式 分布式计算
Zookeeper系列 (一)
Zookeeper 是 Apache 的一个分布式服务框架,是 Apache Hadoop 的一个子项目。
119 0
Zookeeper系列 (一)
|
存储 监控 Unix
一文了解Zookeeper
一文了解Zookeeper
259 0
一文了解Zookeeper
|
SQL 存储 关系型数据库
|
存储 消息中间件 算法
ZooKeeper 到底解决了什么问题?
目标 ZooKeeper 很流行,有个基本的疑问: ZooKeeper 是用来做什么的? 之前没有ZK,为什么会诞生 ZK?
337 0
ZooKeeper 到底解决了什么问题?
zookeeper理解与应用
它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。
106 0