Zookeeper简介

2019/06/25 17:11
阅读数 15

 

zookeeper 动物园管理员,可以用来管理 hadoop(大象)、hive(蜜蜂)、pig(小 猪)、tomcat(猫)等等。

Apache Hbase 和 Apache Solr 的分布式集群都用到了 zookeeper,Dubbo中也要用到zookeeper。

 

Zookeeper是一个高性能、高可用的分布式管理与协调框架,主要功能包括:配置管理、命名服务、分布式锁、集群管理、发布/订阅、队列管理。

 

 


 

 

 

ZooKeeper 的作用(应用场景)

1、配置管理

项目中有各种配置,比如数据库连接配置,springboot、springcloud的yml配置,集群各节点的配置,等等。

当我们只使用少数几台服务器、配置文件很少的时候,配置文件可以直接放在这些服务器上。

但做分布式项目的时候,往往有很多集群,集群节点很多,各种配置文件一大堆,这时候就需要使用zk来集中管理配置。

常见的有,使用zk来管理HBase集群的配置信息,管理Kafka的broker信息,Dubbo中使用zk来管理各服务节点的信息、实现服务治理(相当于SpringCloud中的Eureka)。

 

 

2、命名服务

访问服务时,直接使用服务所在机器的ip地址很麻烦,全是数字、机器又多,那么多ip,不好记。

可以把集群各节点提供的服务的名称、机器ip注册到ZK上,在项目中直接使用服务名,向ZK请求某个服务时,ZK会选择合适的节点(ip)来提供服务。

 

 

3、分布式锁

一个zk server集群,只有一个leader对外提供写服务,写自然要加锁来保证数据同步,follower都只提供读服务,只读不用加锁。

同一时刻,只有leader持有锁,leader故障时会释放锁,选出新的leader后,把锁分配给新的leader。

 

 

4、 集群管理

在分布式的集群中,由于各种原因,比如硬件故障、网络故障、并发量剧增等,经常要增减节点数量。

添加新的节点、或者旧的节点下线,集群中的各节点需要感知集群节点的变化。zk server可以存储集群各节点(client)的信息,集群各节点再从zk server上获取其它集群的信息。

Dubbo的服务治理就是用ZK实现的。

 

 

5、发布/订阅

利用zk的观察/通知机制。zk client订阅某个znode,这个znode变化时,zk server会通知对应的zk client获取znode的最新数据。

 

 

6、实现队列

利用zk执行写请求的顺序一致性来实现(paxos算法)。

 

 


 

 

 

Zookeeper的集群模式

zk server一般都要集群,保证zk server的高可用。zk server的集群一般要读写分离,搞成分布式读写的形式。

 

 

 

上图的server指的都是zk server节点,client指的是一个服务节点。

 

 

zk server有3种角色

  • leader   负责处理zk client的写请求(更新znode),一个zk集群只能有一个leader
  • follower  同步leader的数据,负责处理zk client的读请求(获取znode中的数据),并参与leader的选举
  • observer  一种特殊的follower,可以处理zk client的读请求,但不参与leader的选举。使用observer的目的是提高zk集群的负载能力(提升处理读请求的速度),相当于临时工,临时加上去分担读请求的压力,没有编制(选举leader的权力)。写请求的压力分担不了,因为只能有一个leader,如果有多个leader一起来处理写请求,难以保证数据的一致性。

 

 

zk server在工作过程中有三种状态

  • LOOKING:当前zk server不知道leader是谁,正在搜寻
  • LEADING:当前zk server就是leader,正在领导follower
  • FOLLOWING:当前节点是follower,正在跟随(同步)leader

 

 

zk server处理读请求的流程:

任意一个zk server节点收到读请求,都可以处理,如果是leader收到的话,也会勉为其难地处理一下。

 

 

zk server处理写请求的流程

leader收到写请求,如果是follower收到,会将写请求转发给leader处理。

leader收到请求后,使用paxos算法来执行写操作,保证数据的一致性。paxos算法执行过程如下:

leader将写请求都放到一个队列中,并给写请求分配一个唯一的编号。执行某个写请求时,leader先向follower发起投票,是否批准这个写请求,如果超过半数同意,leader就会执行这个写请求。同一时刻,leader只会执行一个写请求。

如果某个zk server再执行同步操作时,比如一个follower同步编号为99的写操作时,发现编号为100的写操作之前已经同步了,意识到自己的数据不一致,马上停止对外服务,并从leader同步全量数据。

 

其实也不算是投票、批准。因为follower要从leader同步数据,leader先执行一个写请求,follower再同步这个写操作引起的数据更新,这2步作为一个事务来处理。

如果有一半的follower同步成功(+leader,超过了zk server总数的一半),就认为这个写操作执行成功,事务成功,提交。至于其他尚未同步成功的,如果机器故障要下线,那也不用去管它是否同步了;如果是网络延迟等原因,过会儿会自动从leader同步,也不管用管。

如果同步成功的follower没达到一半,就认为同步失败,在已同步的机器上回滚这个写操作。

 

 

zk server集群至少需要3台机器,为何官方推荐集群的zk server数量为单数?

比如zk server数量为5,挂掉3个,zk server集群就gg;数量为6,还是挂掉3个,集群就gg(达到半数就gg)。

5台、6台的容灾能力是一样的,少用1台机器还可以减少点成本。

 

 


 

 

 

Zookeeper的特点

  • 顺序一致性:zk会给所有更新请分配一个全局唯一的递增编号(paxos算法),按照这个编号来依次执行,即执行顺序写请求发送的顺序相同。写代码时可以利用zk的这个特性来实现更高层次的同步。
  • 数据更新原子性:一次数据更新要么成功(都应用、同步到所有机器),要么失败(所有机器都不使用这次数据更新),会把一次数据更新作为一次事务来处理。
  • 单一视图: zk client无论连接到哪个zk server,获取到的数据都是一样的
  • 可靠性(高可用性):zk server往往要集群,只要半数以上的zk server节点可以正常工作,zk server集群就可以对外提供服务。leader发生
  • 实时性: zk client可以读取到zk server上的最新数据(最终一致性)
  • 高性能:zk server将全量数量存储在内存中,性能极高,尤其是在读的时候。写(更新znode)的时候,要把更新从内存同步到文件,性能稍低。

 

 


 

 

 

Zookeeper的工作原理

zk的核心机制是原子广播,这个机制保证了zk server之间的同步。

 

实现原子广播的协议是Zab协议,Zab协议有两种模式:

  • 恢复模式。leader故障后自动进入恢复模式,从follower中选出一个新的leader,其它follower从新leader处同步数据,同步完后恢复模式就结束了。
  • 广播模式。用于follower从leader处同步数据。

 

 


 

 

 

Zookeeper中的znode

zk用一个znode来储存、管理一个client的信息,z代表zk。一个znode对应一个文件目录。

一个znode可以有子节点。zk server以简单的树形结构来存储所有的znode。

 

有四种类型的znode:

  • PERSISTENT  持久化。一个节点断开与zk server的连接后,zk server会保留该节点对应的znode

  • PERSISTENT_SEQUENTIAL  持久化顺序编号。客户端与zookeeper断开连接后,zk server会保留该节点对应的znode

  • EPHEMERAL  临时。一个节点断开与zk server的连接后,zk server会删除该节点对应的znode

  • EPHEMERAL_SEQUENTIAL   临时顺序编号。一个节点断开与zk server的连接后,zk server会删除该节点对应的znode

 

SEQUENTIAL 顺序编号指的是,创建一个znode时会自动在节点名上加一个整数作为后缀。

这个整数由父节点维护,比如最新的一个SEQUENTIAL znode到5了,那下一个创建SEQUENTIAL  znode就是6。

  

 


 

 

 

Zookeeper的观察/通知机制

一个zk client会观察(watch)它对应的znode,zk server会监听每一个znode的变化,一旦某个znode的数据发生改变,zk server会通知对应的zk client,对应的节点收到通知后,会获取该znode的更新。

不使用zk client轮询zk server的方式,一者开销大,二者轮询大多数时候都是无效的。发生变化时由zk server通知对应的zk client获取更新。

 

zk只能保证分布式系统数据的最终一致性,不能保证强一致性(数据每个时刻都是同步的)。

比如修改了znode,zk server通知对应的节点,这期间可能又有人修改了该znode,节点获取到的是第二次修改后的数据,第一次修改被忽视了,获取到的是最新的数据。

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部