背景
为了协调分布式数据中各个进程之间的关系。
主从架构(常见分布式系统)需求:
主节点选举
使得主节点可以给从节点分配任务
崩溃检测
主节点必须具有检测从节点崩溃或失去连接的能力
组成员关系管理
主节点必须具有知道哪一个从节点可以执行任务的能力
元数据管理
主节点和从节点必须具有通过某种可靠的方式来保存分配状态和执行状态的能力
以上需求都可以被视为协作的原语,反映了分布式系统中通用的需求,因此,设计一个用于协作需求的服务的方法往往是提供原语列表,暴露出每个原语的实例化调用方法,并直接控制这些实例。
但是这种设计存在重大缺陷:首先,我们要么预先提出一份详尽的原语列表,要么提供 API 扩展,以便引入新的原语;其次,以这种方式实现原语的服务使得应用丧失了灵活性。
Zookeeper 没有选择这种方式,而是提供了一小部分调用方法组成的类似文件系统的 API,以便允许应用实现自己的原语。
Zookeeper 基础
Znode
Zookeeper 的核心概念是 znode,有点类似文件系统中的文件/文件夹,包含路径和数据(可选的,字节数组),每个 znode 可以有子节点。
Znode 分类
持久节点 & 临时节点
znode 节点可以是持久节点,还可以是临时节点。持久的 znode,只能调用 delete 来删除。临时节点与之相反,当创建该节点的客户端崩溃或关闭了与 Zookeeper 的连接时候,这个节点就会被删除。
持久化节点很有用,可以为分布式应用保存一些数据,即使节点的创建者不再属于该应用系统,数据也可以保存下来而不丢失。例如,在主从模式中,需要保存从节点的任务分配情况,即使分配任务的主节点已经崩溃了。
临时节点传递了应用的一些信息,仅当创建者会话有效时候,临时节点才存在。一个例子就是主节点问题。当临时主 znode 存在时候,说明主节点正常工作。当主节点崩溃之后,主 znode 也会随之消失。这样从节点/备主节点就会知道主节点已经崩溃,从而进行后续操作。
值得注意的是,因为临时的 znode 在创建者会话结束后会被删除,所以目前临时节点不允许拥有子节点。
有序节点
一个 znode 还可以设置为有序节点。一个有序节点被分配唯一一个单调递增的整数。当创建有序节点时,一个序号会被追加到路径之后。有序节点提供了创建具有唯一名称的 znode 的简单方式。同时,通过这种方式可以直观的获取 znode 的创建顺序。
综上,znode 一共有 4 种类型:持久的、临时的、持久有序的、临时有序的。
监视和通知
Zookeeper 采用了通知机制向客户端传递节点树的变化:客户端向 Zookeeper 注册需要接收通知的 znode,通过对 znode 设置监视点(watch)来接受通知。监视点是一个单次触发的操作,为了持续监听,客户端必须在每次通知后设置一个新的监视点。
为了防止连续两次变更(在设置下一次监视点之前又出现了变更),往往在设置监视点之前都要去取一次数据,这样客户端节点就不会错过任何变更。
Zookeeper 可以定义多种类型的通知,这依赖于设置监视点对应的通知类型。客户端可以设置多种监视点,如监控 znode 的数据变化,监控 znode 的子节点的变化,监控 znode 的创建和删除。
版本
每一个 znode 都有一个版本号,它随着每次数据变化而自增。setDate 和 delete 以版本号作为传入参数,只有当传入参数的版本号与服务器上的版本号一致时调用才会成功(其实就是一种乐观锁,CAS 操作)。
Zookeeper 架构
Zookeeper 是 C/S 架构,分为客户端和服务器端。应用通过客户端库来对 Zookeeper 实现调用,客户端库负责与 Zookeeper 服务器端进行交互。
Zookeeper 服务器端有两种模式:独立模式和仲裁模式。
独立模式指的是 Zookeeper 服务器只有一台。仲裁模式也就是 Zookeeper 集群,有一组 Zookeeper 服务器。
Zookeeper 仲裁
仲裁模式下,Zookeeper 复制集群中的所有服务器的数据树。但是让一个客户端等待每个服务器完成数据保存后再继续,延迟会非常高。
Zookeeper 设置了“法定人数”,是指为了使 Zookeeper 工作必须有效运行的服务器的最小数量,也是服务器告知客户端安全保存数据前,需要保存客户端数据的服务器的最小个数。
一般来说,法定人数要超过集群中机器数量的一半,否则会发生“脑裂”问题。在集合中,服务器的个数不一定是奇数,只不过使用偶数会使得系统更加脆弱(浪费机器,损耗性能)。比如,在集群中使用 4 台服务器,根据多数原则,必须有 3 台服务器存活才可以提供服务,所以仅仅能容许 1 台服务器崩溃。对比使用 3 台服务器,同样也是允许 1 台服务器崩溃。同时,4 台服务器时候,每次确认需要 3 台,而 3 台服务器时候,每次确认只需要 2 台。这意味着对于每个请求,需要更多的确认操作。因此最好使用奇数台服务器。
会话
客户端必须先和服务器端建立会话才能执行请求。会话和临时节点关系密切。
客户端初始连接到集合中某一个服务器,通过 TCP 协议与服务器进行连接并通信。当会话无法与当前连接的服务器继续通信时,会话会透明地转移到另外一台服务器上。
会话提供了顺序保障,意味着同一个会话中的请求会以先进先出的方式执行。
扫描二维码,分享此文章