Zookeeper简介

一、什么是Zookeeper

Zookeeper是一个分布式的,开源的程序协调服务,是Hadoop下的一个子项目。是一个分布式程序协调服务,他提供的主要功能包括:配置管理,名字服务,分布式锁,集群管理。

二、Zookeeper的应用场景

1. 配置管理

如果有很多服务器都需要同样的配置文件,这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的地方都可以获得变更。它使用 Zab这种一致性协议来提供一致性。比如在 HBase 中,客户端就是连接一个 Zookeeper,获得必要的 HBase 集群的配置信息,然后才可以进一步操作。还有在开源的消 息队列 Kafka 中,也使用 Zookeeper来维护broker的信息。在 Alibaba开源的 SOA 框架Dubbo 中也广泛的使用 Zookeeper 管理一些配置来实现服务治理。

2. 名字服务

在我们的应用中,服务特别多的时候,如果我们在本地保存服务的地址的时候非常不方便,但是只要我们访问一个大家都熟知的访问点,这里提供统一的入口,对应着不同的服务,那么维护起来就方便多了。

3. 分布式锁

在一个分布式环境中,为了提高可靠性,我们几群的每台服务器上都部署着同样的服务,但是,一件事如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来非常复杂。而如果我们让一个服务进行操作,那又存在单点。
通常有一种方法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务器出问题的时候,立即释放fail over到另外的服务。这在很多分布式系统中都是这么做(Leader Election选举),比如HBase的master就是采用这种机制。但是注意,分布式锁跟同一个进程的锁还是有区别的,所以使用的时候要比同一个进程里的锁更谨慎使用。

4. 集群管理

在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,有老的节点退出集群,这时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出相应的决策。
比如:一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候,我们要根据现在集群目前的状态分配存储节点。这个时候我们就需要动态感知到集群目前的状态。
比如:一个分布式的SOA框架中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制)。还有开源的Kafka队列就采用了Zookeeper作为Cosnumer的上下线管理。

三、Zookeeper概念

1. znode

Zookeeper会保存任务的分配、完成情况,等共享信息,ZooKeeper中,这些信息被保存在一个个数据节点上,这些节点被称为znode。它采用了类似文件系统的层级树状结构进行管理。
在这里插入图片描述
根节点/包含4个子节点,其中三个拥有下一级节点。有的叶子节点存储了信息。
节点上没有存储数据,也有着重要的含义。比如在主从模式中,当/master节点没有数据时,代表分布式应用的主节点还没有选举出来。
znode节点存储的数据为字节数组。存储数据的格式zookeeper不做限制,也不提供解析,需要应用自己实现。


实际上图就是主从模式存储数据的示例,这里先简单讲解:

  • /master,存储了当前主节点的信息
  • /workers,下面的每个子znode代表一个从节点,子znode上存储的数据,如“foo.com:2181”,代表从节点的信息。
  • /tasks,下面的每个子znode代表一个任务,子znode上存储的信息如“run cmd”,代表该任务内容
  • /assign,下面每个子znode代表一个从节点的任务集合。
    如/assign/worker-1,代表worker-1这个从节点的任务集合。
    /assign/worker-1下的每个子znode代表分配给worker-1的一个任务。

1. 持久节点和临时节点(ephemeral)

持久节点(persistent)只能通过delete删除。临时节点在创建该节点的客户端崩溃或关闭时,自动被删除。
前面例子中的/master应该使用临时节点,这样当主节点失效或者退出时,该znode被删除,其他节点知道主节点崩溃了,开始进行选举的逻辑。
另外/works/worker-1也应该是临时节点,在此从节点失效的时候,该临时节点自动删除。
在目前的版本,由于临时znode会因为创建者会话过期被删除,所以不允许临时节点拥有子节点。

2. 有序节点

znode可以被设置为有序(sequential)节点。有序znode节点被分配唯一一个单调递增的证书。
如果创建了个一有序节点为/workers/worker-,zookeeper会自动分配一个序号1,追加在名字后面,znode名称为/workers/worker-1。通过这种方式,可以创建唯一名称znode,并且可以直观的看到创建的顺序。

3. znode支持的操作及暴露的API:

create /path data:创建一个名为/path的znode,数据为data。
delete /path: 删除名为/path的znode。
exists /path:检查是否存在名为/path的znode
setData /path data:设置名为/path的znode的数据为data
getData /path:返回名为/path的znode的数据
getChildren /path:返回所有/path节点的所有子节点列表

2. 观察与通知

分布式应用需要及时知道zookeeper中znode的变化,从而了解到分布式应用整体的状况,如果采用轮询方式,代价太大,绝大多数查询都是无效的。因此,zookeeper采用了通知的机制。客户端向zookeeper请求,在特定的znode设置观察点(watcher)。Watcher是Zookeeper中的一个很重要的特性。Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。

客户端首先向Zookeeper注册一个watcher(观察点),当数据发生改变的时候,Zookeeper就会给他发送一个通知,当我们注册的时候,会有一个watcherManager帮我们管理已经注册的这些事件,当值被修改了,会调用客户端的一个回调函数。

Zookeeper的事件监听有以下特性:

  • 当监听事件被触发,服务端会发送通知给客户端,但是不包括事件的具体内容,需要客户端在收到通知后手动去获取。
  • Watcher是一次性的,一旦触发将会失效。如果需要反复进行监听,就需要反复进行注册。这么设计是为了帮助服务器减轻压力,可以通过Zookeeper的开源客户端轻松实现对某一事件的永久监听。

3. 版本

每个znode都有一个版本号,随着每次数据变化自增。setData和delete都会导致版本号的改变。客户端每次请求服务器都会带着版本号,当版本号一致的时候,说明Zookeeper中的节点还没有被修改过;如果版本号不一致时,调用失败。

4. 会话

Session 指的是 ZooKeeper 服务器与客户端会话。在 ZooKeeper 中,一个客户端连接是指客户端和服务器之间的一个 TCP 长连接。

  • 客户端启动的时候,首先会与服务器建立一个 TCP 连接,从第一次连接建立开始,客户端会话的生命周期也开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知。
  • Session的sessionTimeout值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在sessionTimeout规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。
  • 在为客户端创建会话之前,服务端首先会为每个客户端都分配一个sessionID。由于 sessionID 是Zookeeper 会话的一个重要标识,许多与会话相关的运行机制都是基于这个 sessionID 的,因此,无论是哪台服务器为客户端分配的 sessionID,都务必保证全局唯一。

5. 法定人数

Zookeeper运行的两种模式:独立模式和仲裁模式(集群)。

仲裁模式下,会复制所有服务器的数据树。但如果让客户端等待所有复制完成,延迟太高。这里引入法定人数概念,指为了使zookeeper集群正常工作,必须有效运行的服务器数量。同时也是服务器通知客户端保存成功前,必须保存数据的服务器最小数
例如我们有一个5台服务器的zookeeper集群,法定人数为3,只要任何3个服务器保存了数据,客户端就会收到确认。只要有3台服务器存活,整个zookeeper集群就是可用的。

法定人数需要大于服务器数量的一半。也称为多数原则。此外,我们要尽量选用奇数个服务器,这样集群能容忍崩溃服务器占比更大,性价比更高。
例如4台服务器的集群,法定人数最少为3,那么只能允许1台服务器崩溃,也就是仅允许25%的机器崩溃。而5台服务器的集群,法定人数最少也是3,但是此时允许2台服务器崩溃。换句话讲,40%的机器崩溃后还能工作。
仲裁模式下,负载均衡通过客户端随机选择连接串中的某个服务器来实现。

6. ZAB协议

6.1 ZAB协议简介

Zab协议的全称是Zookeeper Atomic Broadcast (Zookeeper原子广播)。Zookeeper 是通过Zab 协议来保证分布式事务的最终一致性

  1. Zab协议是为分布式协调服务Zookeeper专门设计的一种 支持崩溃恢复原子广播协议,是Zookeeper保证数据一致性的核心算法。
  2. 在Zookeeper中主要依赖Zab协议来实现数据一致性,基于该协议,Zookeeper实现了一种主备模型(即Leader和Follower模型)的系统架构来保证集群中各个副本之间数据的一致性。这里的主备系统架构模型,就是指只有一台客户端(Leader)负责处理外部的写事务请求,然后Leader客户端将数据同步到其他Follower节点。
  3. ZAB的协议核心是在整个zookeeper集群中只有一个节点即Leader将客户端的写操作转化为事物(或提议proposal)。
  4. ZAB协议中主要有两种模式,第一是消息广播模式;第二是崩溃恢复模式

6.2 消息广播模式

消息⼴播,用于在zookeeper集群正常状态下的消息同步

  • 在初次发送提议时只需要等到超半数的ack回复,即开始发送commit到所有节点
  • ZAB协议会确保,每个commit最终被所有follower提交以实现最终⼀致性
  • 所有提议都先进入队列,follower从队列中取出处理,以达到异步解耦,提高效率
  • 具体步骤如下:
  1. 客户端发起一个写操作请求
  2. leader服务器将客户端的request请求转化为事务proposql提案,同时为每个proposql分配一个全局唯一的id、即ZXID
  3. leader服务器与每个follower之间都有一个队列,leader将消息发送到该队列
  4. follower机器从队列中取出消息处理(写入本地事物日志中)完毕后,向leader服务器发送ACK确认。
  5. leader服务器收到半数以上的follower的ACK后,即认为可以发送commit
  6. leader向所有的follower服务器发送commit消息。
  • zookeeper采用ZAB协议的核心就是只要有一台服务器提交了proposal,就要确保所有的服务器最终都能正确提交proposal。这也是CAP/BASE最终实现一致性的一个体现。
  • leader服务器与每个follower之间都有一个单独的队列进行收发消息,使用队列消息可以做到异步解耦。leader和follower之间只要往队列中发送了消息即可。如果使用同步方式容易引起阻塞。性能上要下降很多。

6.3 崩溃恢复

  1. zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是leader服务器接受写请求,即使是follower服务器接受到客户端的请求,也会转发到leader服务器进行处理。
  2. 如果leader服务器发生崩溃,则zab协议要求zookeeper集群进行崩溃恢复和leader服务器选举。
  3. ZAB协议崩溃恢复要求满足如下2个要求:
    3.1) 确保已经被leader提交的提案必须最终被所有的follower服务器提交。
    3.2) 确保丢弃已经被leader提出但是没有被提交的提案。
  4. 新选举出来的leader不能包含未提交的提案,即新选举的leader必须都是已经提交了的提案的follower服务器节点。同时,新选举的leader节点中含有最高的ZXID。这样做的好处就是可以避免了leader服务器检查提案的提交和丢弃工作。
  5. leader服务器发生崩溃时分为如下场景:
    5.1) leader在提出proposal时未提交之前崩溃,则经过崩溃恢复之后,新选举的leader一定不能是刚才的leader。因为这个leader存在未提交的提案
    5.2) leader在发送commit消息之后,崩溃。即消息已经发送到队列中。经过崩溃恢复之后,参与选举的follower服务器(刚才崩溃的leader有可能已经恢复运行,也属于follower节点范畴)中有的节点已经是消费了队列中所有的commit消息。即该follower节点将会被选举为最新的leader。剩下动作就是数据同步过程。

当leader宕机时,判断存活的follower节点数量⼤于法定⼈数,则开始选举新的leader,否则集群不可⽤,同时奔溃恢复后重新选举新的leader,leader需满⾜以下条件:

  • 新的leader不能存在任何未提交的提议
  • ZAB协议确保选举的leader包含最新的数据,每个提议都会产⽣⼀个唯⼀的zxid,选举时则依据zxid判断拥有最新数据的节点,选举完成后,会将zxid发送给所有节点,各节点则根据zxid进⾏数据同步或另外ZAB会确保被leader提交的提议最终被所有follower提交,确保丢弃被提出但没有提交的提议;

7.4 数据同步

  1. 在zookeeper集群中新的leader选举成功之后,leader会将自身的提交的最大提案的事物ZXID发送给其他的follower节点。follower节点会根据leader的消息进行回退或者是数据同步操作。最终目的要保证集群中所有节点的数据副本保持一致。
  2. 数据同步完之后,zookeeper集群保证新选举的leader分配的ZXID是全局唯一

8. Observer

为什么需要Observer:

为了提⾼zookeeper的吞吐量,我们可以为其添加更多的follower,但是更多的follower会导致投票过程变得更慢,而客户端的响应时间变⻓,因此zookeeper设计了Observer节点

什么是Observer:

Observer与普通的 follower仅有⼀个区别: Observer不参与投票环节; 但是提议 和commit同样会发送给Observer,这意味着Observer中的数据也是⼀致的,既提高了整个集群的性能同时避免了,投票带来的延迟;

注意Observer不能算在法定⼈数内。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值