欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

zookeeper是如何工作的?
(last modified Jul 30, 2023, 6:37 PM )
by
侧边栏壁纸
  • 累计撰写 176 篇文章
  • 累计创建 61 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

zookeeper是如何工作的?

橙序员
2023-07-30 / 0 评论 / 0 点赞 / 242 阅读 / 2,460 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

Zookeeper维护持久节点和临时节点组成的空间,通过监听节点数据实现节点及其子节点的数据一致性。Zookeeper的数据存储结构与Unix文件系统相似,使用znode作为最小的数据单元,并可以保存数据和挂载子节点。节点类型包括持久节点、持久顺序节点、临时节点和临时顺序节点,它们具有不同的生命周期。会话是Zookeeper中重要的概念,客户端与服务端之间的交互操作都与会话相关。常见的会话状态有连接中、已连接和已关闭。

一句话可以概括为:zookeeper主要维护持久节点和临时节点组成的空间,通过对节点的数据的监听达到节点及其子节点最终的数据一致性

znode

zk数据存储结构与标准的Unix文件系统非常相似,都是在根节点下挂很多子节点。zk中没有引入传统文件系统中目录与文件的概念,而是使用了称为znode的数据节点概念。znode是zk中数据的最小单元,每个znode上都可以保存数据,同时还可以挂载子节点,形成一个树形化命名空间。

节点类型

每个znode根据节点类型的不同,具有不同的生命周期。

  • 持久节点:节点被创建后会一直保存在zk中,直到将其删除。

    • 持久顺序节点:一个父节点可以为它的第一级子节点维护一份顺序,用于记录每个子节点创建的先后顺序。
  • 临时节点:临时节点的生命周期与客户端的会话绑定在一起,会话消失则该节点就会被自动清理。临时节点只能作叶子节点,即临时节点不能创建子节点。

    • 临时顺序节点:添加了创建序号的临时节点。

image-20230730155419940

会话

会话是zk中最重要的概念之一,客户端与服务端之间的任何交互操作都与会话相关。ZooKeeper客户端启动时,首先会与zk服务器建立一个TCP长连接。连接一旦建立,客户端会话的生命周期也就开始了。

会话状态

常见的会话状态有七种:

  • CONNECTING:连接中。Client要创建一个连接,其首先会在本地创建一个zk对象,用于表示其所连接上的Server。
  • CONNECTED:已连接。连接成功后,该连接的各种临时性数据会被初始化到zk对象中。
  • CLOSED:已关闭。连接关闭后,这个代表Server的zk对象会被删除。
    public enum States {
        CONNECTING, ASSOCIATING, CONNECTED, CONNECTEDREADONLY,
        CLOSED, AUTH_FAILED, NOT_CONNECTED;

        public boolean isAlive() {
            return this != CLOSED && this != AUTH_FAILED;
        }

        /**
         * Returns whether we are connected to a server (which
         * could possibly be read-only, if this client is allowed
         * to go to read-only mode)
         * */
        public boolean isConnected() {
            return this == CONNECTED || this == CONNECTEDREADONLY;
        }
    }

会话建立流程

1、解析节点列表,将解析到的节点连接地址使用Collections.shuffle()对其进行随机排列

image-20230730174448298

2、根据获取到的链接地址创建客户端连接,包括一个发送线程和一个watcher事件线程:

  1. 发送线程负责维护与zk节点的连接,如果连接关闭则发送关闭的watcher事件
  2. 事件线程负责处理watcher队列,根据watcher的连接状态和数据变更对其进行处理:
    1. 如果节点状态发生变更,则会根据更新后的状态对连接进行重连或关闭
    2. 如果节点数据发生变更,则会更新当前节点和其下的子节点数据内容

image-20230730174831903

会话连接事件

  1. 连接丢失:因为网络抖动等原因导致客户端长时间收不到服务端的心跳回复,客户端就会导致连接丢失。连接丢失会引发客户端自动从 zk 地址列表中逐个尝试重新连接,直到重连成功,或 按照指定的重试策略终止。
  2. 会话转移:当发生连接丢失后,客户端又以原来的 sessionId 重新连接上了服务器。若重连上的服务器不是原来的服务器,那么客户端就需要更新本地 zk 对象中的相关信息,例如连接上的Server 的 IP 地址。这就是会话转移。
  3. 会话失效:若客户端连接丢失后,在会话超时范围内没有连接上服务器,则服务器会将该会话从服务器中删除。在服务端将某客户端的会话删除后,该客户端仍使用原来的 sessionId 又重新连接上了服务器。那么服务器会给客户端发送一个连接关闭响应,表示这个会话已经失效。 客户端在收到响应后会根据配置,要么关闭连接,要么重新发起新的会话 id 的连接。

会话超时管理

服务器为每一个客户端的会话都记录着上一次交互后空闲的时长,及从上一次交互结束开始会话空闲超时的时间点。一旦空闲时长超时,服务端就会将该会话的 SessionId 从服务端清除。

服务端对于会话空闲超时管理,采用了一种特殊的方式——分桶策略。

分桶策略是指,将空闲超时时间相近的会话放到同一个桶中来进行管理,以减少管理的复杂度。在检查超时时,只需要检查桶中剩下的会话即可,因为没有超时的会话已经被移出 了桶,而桶中存在的会话就是超时的会话。

分桶策略的计算公式为:

【过期时间】=【当前时间】+【会话超时时间】

【会话的过期桶】=(【过期时间】/【过期桶单位时间】+1)

【会话实际清除时间】=【过期桶】X【过期桶单位时间】

watcher事件

zk 的 watcher 机制具有非常重要的两个特性:

  • 一次性:一旦一个 watcher 被触发,zk 就会将其从客户端的 WatcherManager 中删除, 服务端中也会删除该 watcher。zk 的 watcher 机制不适合监听变化非常频繁的场景。
  • 轻量级:真正传递给 Server 的是一个简易版的 watcher。回调逻辑存放在客户端,没有在服务端。

一个watcher由节点路径,节点连接状态,节点变更事件组成。

其中节点连接状态包括:

public enum KeeperState {
    /** 未使用,此状态从不由服务器生成 */
    @Deprecated
    Unknown (-1),

    /** 客户端处于断开连接状态—它未连接到集群中的任何服务器。 */
    Disconnected (0),

    /** 未使用,此状态从不由服务生成 */
    @Deprecated
    NoSyncConnected (1),

    /** 客户端处于连接状态-它连接到集成中的服务器(ZooKeeper客户端创建过程中主机连接参数中指定的服务器之一)。*/
    SyncConnected (3),

    /**
     * 身份验证失败状态
     */
    AuthFailed (4),

    /**
     * 客户端连接到只读服务器,即当前未连接到大多数服务器的服务器。
     * 在接收到此状态之后,唯一允许的操作是读取操作。
     * 此状态仅为只读客户端生成,因为不允许读/写客户端连接到I/o服务器。
     */
    ConnectedReadOnly (5),

    /**
     * SaslAuthenticated:用于通知客户端他们已通过SASL身份验证,以便他们可以使用SASL授权权限执行Zookeeper操作。
     */
    SaslAuthenticated(6),

    /** 服务群集已使此会话过期。
     * ZooKeeper客户端连接(会话)不再有效。如果要访问集群,必须创建一个新的客户端连接(实例化一个新ZooKeeper实例)。
     */
    Expired (-112);

    //......
}

节点变更事件包括:

    None (-1), //当节点连接状态为Disconnected、Expired、AuthFailed,为此值
    NodeCreated (1), //节点创建
    NodeDeleted (2), //节点删除
    NodeDataChanged (3), //节点数据变更
    NodeChildrenChanged (4); //子节点变更

节点访问控制-ACL

ACL 全称为 Access Control List(访问控制列表),是一种细粒度的权限管理策略,可以针对任意用户与组进行细粒度的权限控制。zk 利用 ACL 控制 znode 节点的访问权限,如节点数据读写、节点创建、节点删除、读取子节点列表、设置节点权限等。

Zookeeper 的 ACL 分为三个维度:授权策略 scheme、授权对象 id、用户权
限 permission,子 znode 不会继承父 znode 的权限。

授权策略用于确定权限验证过程中使用的检验策略(简单来说就是,通过什么来验证权限,或一个用户要访问某个节点,系统如何验证其身份),在 zk 中最常用的有四种策略。

  • 根据 IP 地址进行权限验证。
  • 根据用户名与密码进行验证。
  • 对所有用户不做任何验证。
  • 超级用户可以对任意节点进行任意操作。

授权对象指的是权限赋予的用户。不同的授权策略具有不同类型的授权对象。
权限指的是通过验证的用户可以对 znode 执行的操作。共有五种权限:

  • 创建权限:允许授权对象在当前节点下创建子节点。
  • 删除权限:允许授权对象删除当前节点。
  • 读权限:允许授权对象读取当前节点的数据内容,及子节点列表。
  • 写权限:允许授权对象修改当前节点的数据内容,及子节点列表。
  • 授权权限:允许授权对象对当前节点进行 ACL 相关的权限设置。
0

评论区