ZooKeeper基础知识分析罗列

一、Zookeeper 的数据模型

Zookeeper 数据模型的结构是基于节点的,我们把这种节点叫做 Znode 

1、Znode 的元素组成部分

     Znode 节点中由 4 种元素组成,以下每个元素具体是什么分别介绍如下:

  • data : Znode 存储的数据信息,这里的数据指用户保存的数据;
  • ACL : 对节点进行权限控制,记录了哪些用户或者哪些 IP 地址可以访问本节点;
  • child : 当前节点的子节点引用,通过这个节点来找到它的子节点;
  • stat : 包含 Znode 的各种元数据,比如事务 ID、版本号、时间戳、大小等 Znode 本身的数据。

2、Znode 的类型 

  • 持久节点: 持久节点是 Zookeeper 的默认节点,持久节点被创建后会一直存在,除非进行手动删除;
  • 持久顺序节点: 持久顺序节点是在持久节点的基础上,增加了顺序性。也就是说,持久顺序节点被创建时,会根据创建的时间进行编号,根据编号我们就可以判断它们的顺序;
  • 临时节点: 临时节点与持久节点的特点相反,临时节点被创建之后,如果与创建它的客户端断开连接,临时节点就会被销毁;
  • 临时顺序节点: 临时顺序节点就是在临时节点的基础上,增加了顺序性。

节点的类型的应用以及它们的特点:

  1. 我们可以使用临时节点来实现服务注册与发现。在某个服务注册到 ZooKeeper 时,我们可以让这个这个服务创建一个临时节点,并把它的访问信息交给到 Zookeeper 维护。当这个服务与 Zookeeper 断开连接时,这个临时节点就会被销毁,这时 Zookeeper 发现这个服务离线了,就会移除它的访问地址,避免出现 404 的情况。我们也可以手动删除某个临时节点让相对应的服务下线;

  2. 当我们有大量的服务时,一旦配置信息需要修改,会消耗我们大量的时间去每个服务中修改,而且还有可能会出错,这种情况我们就可以使用持久节点来保存全局的配置信息。当某个服务注册到 ZooKeeper 时,可以去保存配置信息的节点读取配置信息。当我们修改配置时,Zookeeper 会通知这些服务,服务就会重新去读取配置信息;

  3. 我们可以使用临时顺序节点来实现分布式锁。当多个服务同时对一个资源进行修改时,会出现数据错误,所以我们要避免这种情况。我们这里采取的方式就是为这个资源加锁,想要获取这个资源的服务会创建一个临时顺序节点,根据它的顺序判断这个临时顺序节点是否为第一个,如果是第一个则成功获得锁,这时这个服务就可以对这个资源进行修改了。完成操作后或者这个服务断线了都会删除这个节点,也就是释放了锁。后面的服务会根据它创建的临时顺序节点的顺序来依次对资源进行操作。

二、Zookeeper 集群模式

在我们的生产环境中,Zookeeper 的单机模式无法保证 Zookeeper 服务的高可用性,也就是我们常说的单点故障问题,性能也存在瓶颈。所以在生产环境中,Zookeeper 最好的使用方式就是 Zookeeper 的集群模式,这样不仅在性能方面比单机模式更好,服务的高可用性也得到了保障。

集群部署建议规则:

Zookeeper 集群的数量通常是大于等于 3 的奇数,比如 3、5、7,但也不宜太多。

Tips: Zookeeper 集群的数量为什么需要奇数个呢?如果采用偶数,在 Leader 节点选举投票时,有可能会产生两个 Leader 节点,两个 Leader 都不能满足大多数选票的原则,这时就会出现脑裂问题。

1、Zookeeper 集群的同步机制

当其中一个节点的信息被修改时,首先会修改 Leader 节点,然后再将数据同步到集群中所有的 Follower 节点,这样就确保了集群中所有节点的数据一致。

2、Zookeeper 集群的启动流程

Zookeeper 集群启动时,首先会通过配置文件判断 Zookeeper 的启动方式是否为集群模式,如果为集群模式,则通过配置文件进行初始化工作,然后集群的节点进行 Leader 选举,选举完毕后, Follower 节点与 Leader 节点进行数据同步,完成同步后就可以启动 Leader 和 Follower 实例了。

1、初始化

首先在集群启动的过程中,每个 Zookeeper 服务的主函数会都通过 zoo.cfg 配置文件来判定这个 Zookeeper 服务是以哪种模式启动的,然后通过配置文件进行初始化工作。
与单机模式初始化不同的是,集群模式的 Zookeeper 服务在初始化过程中还需要配置服务器列表、Leader 选举算法、会话超时时间等参数。

2、Leader选举

在所有 Zookeeper 服务初始化完成后,第一件事情就是创建 Java 类 QuorumCnxManager 来进行 Zookeeper 集群的 Leader 选举。
在选举过程中,每个 Zookeeper 服务会使用自身的服务器编号 SID 、最新的事务编号 ZXID 、和当前服务器纪元值 currentEpoch 这三个参数去参加选举,然后根据 zoo.cfg 的 electionAlg 参数来选择 Leader 选举算法,来完成 Leader 的选举,完成选举后 Leader 会向其它 Zookeeper 服务发起数据同步的通知。

3、Follower同步

Leader 选举完毕,其它 Zookeeper 服务的状态就会变为 Follower ,在 Follower 接收到来自 Leader 的通知后, Follower 会创建一个 LearnerHandler 类的实例来处理与 Leader 的数据同步,在半数以上的 Follower 完成数据同步后,Leader 和 Follower 的实例就可以启动了。

4、Leader和Follower启动

在 Leader 和 Follower 实例启动时,创建和启动会话管理器,初始化 Zookeeper 的请求处理链,处理器也会在启动阶段串联请求处理链,然后把 Zookeeper 实例注册到 JMX 服务中,整个 Zookeeper 集群的启动才算完成。

三、Zookeeper 的通信及会话

Zookeeper Java 客户端 ZkClient 和 Curator ,客户端是如何与 Zookeeper 服务端建立通信的呢?我们就带着这个问题开启本节的内容

Zookeeper 是基于 TCP/IP 协议实现了自己的通信方式

四、Zookeeper Watch

在我们使用 Zookeeper 来实现服务注册与发现、配置中心、分布式通知等功能时,需要使用 Zookeeper 的核心功能 Watch,来对节点进行监听。

1、Watch 的原理

在介绍 Watch 的原理之前,我们先熟悉一个概念:Zookeeper 客户端对 Znode 的写操作,也就是新增节点、更新节点、删除节点这些操作,默认会开启监听;Zookeeper 客户端对 Znode 的读操作,也就是查询节点数据、查询节点是否存在、查询子节点等操作,需要手动设置开启监听。这也是为什么在 GetDataRequest 请求体中会有 watch 这个属性的原因。
Watch 的运行过程分为 4 部分,分别是:客户端注册 Watch 、服务端注册 Watch、服务端触发 Watch、客户端处理回调。

  • 客户端注册 Watch
    当我们使用 Zookeeper 客户端向 Zookeeper 服务端发送带有事件监听的请求时,Zookeeper 客户端会把该请求标记成带有 Watch 的请求,然后把 Watch 监听器注册到 ListenerManager 中。

  • 服务端注册 Watch
    Zookeeper 服务端接收到 Zookeeper 客户端发送过来的请求,解析请求体,判断该请求是否带有 Watch 事件,如果有 Watch 事件,就会把 Watch 事件注册到 WatchManager 中。

  • 服务端触发 Watch
    Zookeeper 服务端注册完 Watch 事件后,会调用 WatchManager 的 triggerWatch 方法来触发 Watch 事件,Watch 事件完成后,向客户端发送响应。

  • 客户端处理回调
    Zookeeper 客户端接收到 Zookeeper 服务端的响应后,解析响应体,根据响应体的类型去 ListenerManager 中查找相对应的 Watch 监听器,然后触发监听器的回调函数。

五、Zookeeper Jute

在 Zookeeper 的通信与会话一节中,我们学习了 Zookeeper 使用的是基于 TCP 的通信协议,TCP 协议是一种面向连接的、可靠的、基于字节流的通信协议。
我们想要使用 Zookeeper 客户端向 Zookeeper 服务端发送请求,我们就需要把请求发送的 Java 对象转换为字节流的形式,这个转换的过程就是序列化。相对来说,把字节流转换为 Java 对象的过程就是反序列化。

那么我们什么时候使用序列化呢?

  1. 对象需要持久化时;
  2. 对象进行网络传输时。

序列化框架Jute介绍

Jute 前身是 Hadoop Record IO 中的序列化组件,从 Zookeeper 第一个正式版,到目前最新的稳定版本 Apache ZooKeeper 3.6.1 都是用的 Jute 作为序列化组件。
为什么 Zookeeper 会一直选择 Jute 作为它的序列化组件呢?并不是 Jute 的性能比其他的序列化框架好,相反的,现在市面上有许多性能更好的序列化组件,比如 Apache Thrift,Apache Avro 等组件,性能都要优于 Jute。之所以还使用 Jute,是因为到目前为止,Jute 序列化还不是 Zookeeper 的性能瓶颈,没有必要强行更换,而且很难避免因为替换基础组件而带来的一系列版本兼容的问题。
简单的介绍了一下 Jute ,那么在 Zookeeper 中,Jute 又是如何实现的呢?接下来我们就来讲解 Jute 在 Zookeeper 中的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值