1.Zookeeper 简介
Zookeeper 分布式服务框架主要是用来解决分布式应用中经常遇到的一些数据管理问题,提供分布式、高可用性的协调服务能力,在 FusionInsight 集群中主要用途是保存上层组件的元数据,并保证其主备倒换。

Zookeeper 的作用
(1) 配置管理这个好理解。分布式系统都有好多机器,比如我在搭建 hadoop 的 HDFS 的时候,需要在一个主机器上(Master 节点)配置好 HDFS 需要的各种配置文件,然后通过 scp 命令把这些配置文件拷贝到其他节点上,这样各个机器拿到的配置信息是一致的,才能成功运行起来 HDFS 服务。 Zookeeper 提供了这样的一种服务:一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。这样就省去手动拷贝配置了,还保证了可靠和一致性。这里写图片描述
(2) 名字服务这个可以简单理解为一个电话薄,电话号码不好记,但是人名好记,要打谁的电话,直接查人名就好了。分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同服务;类似于域名与 ip 之间对应关系,域名容易记住;通过名称来获取资源或服务的地址,提供者等信息
(3) 分布式锁,单机程序的各个进程需要对互斥资源进行访问时需要加锁,那分布式程序分布在各个主机上的进程对互斥资源进行访问时也需要加锁。很多分布式系统有多个可服务的窗口,但是在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即 failover 到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫
LeaderElection(leader 选举)。举个通俗点的例子,比如银行取钱,有多个窗口,但是呢对你来说,只能有一个窗口对你服务,如果正在对你服务的窗口的柜员突然有急事走了,那咋办?找大堂经理(zookeeper)!大堂经理指定另外的一个窗口继续为你服务!
(4) 集群管理,在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中有些机器(比如 Master 节点)需要感知到这种变化,然后根据这种变化做出对应的决策。我已经知道 HDFS 中 namenode 是通过 datanode 的心跳机制来实现上述感知的,那么我们可以先假设 Zookeeper 其实也是实现了类似心跳机制的功能吧!
Zookeeper 的特点
(1) 最终一致性:为客户端展示同一视图,这是 zookeeper 最重要的功能。
(2) 可靠性:如果消息被到一台服务器接受,那么它将被所有的服务器接受。
(3) 实时性:Zookeeper 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用 sync()接口。
(4) 等待无关(wait-free):慢的或者失效的 client 不干预快速的 client 的请求。
(5) 原子性:更新只能成功或者失败,没有中间状态。(6) 顺序性:所有 Server,同一消息发布顺序一致。用到 Zookeeper 的系统(1) HDFS 中的 HA 方案(2) YARN 的 HA 方案
(3) HBase:必须依赖 Zookeeper,保存了 Regionserver 的心跳信息,和其他的一些关键信息。
(4) Flume:负载均衡,单点故障。
2.Zookeeper 服务框架

(1) ZooKeeper 集群由一组 Server 节点组成,这一组 Server 节点中存在一个角色为 Leader 的节点,其他节点都为 Follower。当客户端 Client 连接到 ZooKeeper 集群,并且执行写请求时,这些请求会被发送到 Leader 节点上,然后 Leader 节点上数据变更会同步到集群中其他的 Follower 节点。
(2) Leader 节点在接收到数据变更请求后,首先将变更写入本地磁盘,以作恢复之用。当所有的写请求持久化到磁盘以后,才会将变更应用到内存中。(3) ZooKeeper 使 用 了 一 种 自 定 义 的 原 子 消 息 协 议(ZookeeperAtomicBroadcas Zab 协议),在消息层的这种原子特性,保证了整个协调系统中的节点数据或状态的一致性。Follower 基于这种消息协议能够保证本地的 ZooKeeper 数据与 Leader 节点同步,然后基于本地的存储来独立地对外提供服务。
(4) 当一个 Leader 节点发生故障失效时,失败故障是快速响应的,消息层负责重新选择一个 Leader,继续作为协调服务集群的中心,处理客户端写请求,并将 ZooKeeper 协调系统的数据变更同步(广播)到其他的 Follower 节点。
3.Zookeeper 数据模型

每个节点(znode)中存储的是同步相关的数据(这是 ZooKeeper 设计的初衷,数据量很小,大概 B 到 KB 量级),例如状态信息、配置内容、位置信息等。一个 znode 维护了一个状态结构,该结构包括:版本号、ACL 变更、时间戳。每次 znode 数据发生变化,版本号都会递增,这样客户端的读请求可以基于版本号来检索状态相关数据。每个 znode 都有一个 ACL,用来限制是否可以访问该 znode。在一个命名空间中,对 znode 上存储的数据执行读和写请求操作都是原子的。客户端可以在一个 znode 上设置一个监视器(Watch),如果该 znode 数据发生变更,ZooKeeper 会通知客户端,从而触发监视器中实现的逻辑的执行。每个客户端与 ZooKeeper 连接,便建立了一次会话(Session),会话过程中,可能发生 CONNECTING、CONNECTED 和 CLOSED 三种状态。ZooKeeper 支持临时节点(EphemeralNodes)的概念,它是与 ZooKeeper 中的会话(Session)相关的,如果连接断开,则该节点被删除。若非操作人员删除,永久节点会永久保存,所以永久节点可以用来保存元数据,而临时节点则可用来进行 leader 选举及锁服务等。
Zookeeper 的主流应用场景实现思路
(1)配置管理
集中式的配置管理在应用集群中是非常常见的,一般商业公司内部都会实现一套集中的配置管理中心,应对不同的应用集群对于共享各自配置的需求,并且在配置变更时能够通知到集群中的每一个机器。Zookeeper 很容易实现这种集中式的配置管理,比如将 APP1 的所有配置配置到/APP1znode 下,APP1 所有机器一启动就对/APP1 这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法 Watcher,那么在 zookeeper 上 /APP1znode 节点下数据发生变化的时候,每个机器都会收到通知,Watcher 方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",false,null));以上这个例子只是简单的粗颗粒度配置监控,细颗粒度的数据可以进行分层级监控,这一切都是可以设计和控制的

(2)集群管理
应用集群中,我们常常需要让每一个机器知道集群中(或依赖的其他某一个集群)哪些机器是活着的,并且在集群机器因为宕机,网络断链等原因能够不在人工介入的情况下迅速通知到每一个机器。Zookeeper 同样很容易实现这个功能,比如我在 zookeeper 服务器端有一个 znode叫/APP1SERVERS,那么集群中每一个机器启动的时候都去这个节点下创建一个EPHEMERAL 类型的节点,比如 server1 创建/APP1SERVERS/SERVER1(可以使用 ip, 保证不重复),server2 创建/APP1SERVERS/SERVER2,然后 SERVER1 和 SERVER2 都 watch/APP1SERVERS 这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行 watch 的客户端。因为 EPHEMERAL 类型节点有一个很重要的特性,就是客户端和服务器端连接断掉或者 session 过期就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,然后集群中所有对/APP1SERVERS 进行 watch 的客户端都会收到通知,然后取得最新列表即可。另外有一个应用场景就是集群选 master,一旦 master 挂掉能够马上能从 slave 中选出一个 master,实现步骤和前者一样,只是机器在启动的时候APP1SERVERS 创建的节点类型变为 EPHEMERAL_SEQUENTIAL 类型,这样每个节点会自动被编号我们默认规定编号最小的为 master,所以当我们对/APP1SERVERS节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为 master,那么 master 就被选出,而这个 master 宕机的时候,相应的 znode 会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为 master,这样就做到动态 master 选举。

4.Zookeeper 的容灾能力
一般情况下,ZooKeeper 能够完成选举即能够正常对外提供服务。ZooKeeper 选举时,当某一个实例获得了半数以上的票数时,则变为 leader。对于 n 个实例的服务,n 可能为奇数或偶数 n 为奇数时,假定 n=2x+1,则成为 leader 的节点需获得 x+1 票,容灾能力为 x。 n 为偶数时,假定 n=2x+2,则成为 leader 的节点需要获得 x+2 票(大于一半),容灾能力为 x。由此可见,2x+1 个节点与 2x+2 个节点的容灾能力相同(3 个与 4 个相同,5 个与 6 个相同…),而考虑到选举以及完成写操作的速度与节点数的相关性,我们建议 ZooKeeper 部署奇数个节点。Zookeeper 的选举是使用举手表决制的,谁的票超过半数谁就获胜。这个机制不仅用于选举,也用于内部的各种业务中,所以节点的数量对于业务的执行是很重要的。比如,我们现在有三个节点 ABC,那么 A 如果要成为组长它只需要得到 B 或者 C 中的一票就可以获胜,这个时候如果 B 或者 C 中损坏一个节点,对于 A 来说都是没有影响的,损坏的节点我们可以理解为弃权,A 获取剩下的节点的一票仍然是可以当选的,没有影响到现有的业务正常运行。我们允许损坏一个节点继续运行业务。但是现在如果有 4 个节点 ABCD,那么 A 如果想要成为组长,它就必须得到 BCD 中的两票超过半数才行。这个时候如果 D 损坏了,那么 A 仍旧是需要的到 BC 的两票即可,业务正常运行。但是如果此时 C 也损坏了,那么 A 得到自己和 B 的票之后,没有超过半数,那么业务就无法正常执行了。所以 4 节点情况下,我们最多损坏一个节点。如果现在有 5 个节点 ABCDE,那么同上,我们为了保证半数以上节点存活,最多可以允许 2 个节点损坏。这里原因不在赘述。所以我们可以发现,当节点数是 3 个和 4 个的时候,他们都只能允许损坏 1 个节点,容灾能力是相同的,5 节点的时候容灾能力+1,所以我们说,尽量建议部署为奇数个节点。这样对于容灾性和数据的读写速度来说,都是有更好的提升的。
5.Zookeeper 关键特性
(1) 最终一致性:无论哪个 server,对外展示的均是同一个视图。
(2) 实时性:保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。
(3) 可靠性:一条消息被一个 server 接收,它将被所有 server 接受。
(4) 原子性:更新只能成功或者失败,没有中间状态。
(5) 顺序一致性:客户端所发送的更新会按照它们被发送的顺序进行应用。
6.Zookeeper 的读写特性
(1)读特性

由 ZooKeeper 的一致性可知,客户端无论连接哪个 server,获取的均是同一个视图。所以,读操作可以在客户端与任意节点间完成。
(2)写特性

上图中展示的是写请求的处理过程:编号 1~5 表示具体步骤
(1) 同读请求一样,客户端可以向任一 server 提出写请求。
(2) server 将这一请求发送给 leader。
(3) leader 获取写请求后,会向所有节点发送这条写请求信息,询问是否能够执行这次写操作。
(4) follower 节点根据自身情况给出反馈信息 ACK 应答消息,leader 根据反馈信息,若获取到的可以执行写操作的数量大于实例总数的一半,则认为本次写操作可执行。
(5) leader 将结果反馈给各 follower,并完成写操作,各 follower 节点同步 leader 的数据,本次写操作完成。
7.Zookeeper—ACL
ACL 可以控制访问 ZooKeeper 的节点,只能应用于特定的 znode 上,而不能应用于该 znode 的所有子节点上。设置 ACL 命令为 setAcl/znodescheme:id:perm。 Scheme 为认证方式,ZooKeeper 内置了 4 种方式:
(1) world 一个单独的 ID,表示任何人都可以访问。
(2) auth 不使用 ID,只有认证的用户可以访问。
(3) digest 使用 username:password 生成 MD5 哈希值作为认证 ID。
(4) IP 使用客户端主机 IP 地址来进行认证。Id:用来认证的字段,用来判断认证信息是否合法,不同的 scheme 的认证方式不同。
Perm:即 permission,通过 Acl 认证的用户对该节点可拥有的操作权限。

737

被折叠的 条评论
为什么被折叠?



