引言:
Apache ZooKeeper是由Apache Hadoop的子项目发展而来的。ZooKeeper 为分布式应用提供了高效且可靠的分布式协调服务,提供了诸如统一命名服务、配置管理和分布式锁等分布式基础服务。在解决分布式数据一致性方面采用了ZooKeeper Atomic Broadcast一致性协议。本文我们会对ZooKeeper做一个初步的介绍,再来了解一下ZooKeeper的应用场景。
目录:
一、初识ZooKeeper
二、ZooKeeper基本原理
三、ZooKeeper应用场景
四、ZooKeeper在鲸技术的实践应用
五、总结
一、初识ZooKeeperZooKeeper 最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统进行分布式协调,但是这些系统往往都存在分布式单点问题。所以雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。
ZooKeeper是一个典型的分布式数据一致性的解决方案,分布式应用可以基于它实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。ZooKeeper可以保证如下分布式一致性特性。
顺序一致性
从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到ZooKeeper中去。
原子性
所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说要么整个集群所有的机器都成功应用了某一个事务,要么都没有应用,一定不会出现集群中部分机器应用了该事务,而另外一部分没有应用的情况。
单一视图
无论客户端连接的是哪个ZooKeeper服务器,其看到的服务端数据模型都是一致的。
可靠性
一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直保留下来,除非有另一个事务又对其进行了变更。
实时性
通常人们看到实时性的第一反应是,一旦一个事务被成功应用,那么客户端能够立即从服务端上读取到这个事务变更后的最新数据状态。这里需要注意的是,ZooKeeper仅仅保证在一定时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
二、ZooKeeper基本原理 ZooKeeper角色ZooKeeper中的角色主要有以下三类,如下表所示:
角色 | 描述 |
Leader | 领导者负责进行投票发起和决议,更新系统状态 |
Follower | Follower用于接收客户请求并向客户端返回结果,在选主过程中参与投票。Follower可以接收Client请求,如果是写请求将转发给Leader来更新系统状态。 |
Observer | Observer可以接收客户端连接,将写请求转发给Leader节点,但Observer不参加投票过程,只同步Leader的状态。Observer 的目的是为了扩展系统,提高读取速度。 |
首先看一下ZooKeeper的架构图
从架构图中我们可以了解到
(1)ZooKeeper分为服务器端(Server)和客户端(Client),客户端可以连接到整个ZooKeeper服务的任意服务器上(除非leaderServes参数被显示设置,Leader不允许接受客户端的连接 )
(2)客户端使用并维护一个TCP连接,通过这个连接发送请求、接受响应、获取观察的事件以及发送心跳。如果这个TCP连接中断,客户端将自动尝试连接到另外的Zookeeper服务器。客户端第一次连接到Zookeeper服务时,接受这个连接的Zookeeper服务器会为这个客户端建立一个会话。当这个客户端连接到另外的服务器时,这个会话会被新的服务器重新建立;
(3)上图中的每一个Server代表一个安装ZooKeeper服务的机器,即是整个提供ZooKeeper服务的集群(或者是由伪集群组成);
(4)组成ZooKeeper服务的服务器必须彼此了解。他们维护一个内存中的状态图像,以及持久存储中的事务日志和快照,只要大多数服务器可用,ZooKeeper服务就可用;
(5)ZooKeeper启动时,将从实例中选举一个Leader,Leader负责处理数据更新等操作,一个更新操作成功的标志是当且仅当大多数Server在内存中成功修改数据。每个Server在内存中存储了一份数据。
(6)ZooKeeper是可以集群复制的,集群间通过Zab协议来保持数据的一致性;
(7)Zab协议包含两个阶段:Leader election 阶段和Atomic Brodcast阶段。
集群中将选举出一个Leader,其他的机器则称为Follower,所有的写操作都被传送给Leader,并通过BroadCast将所有的更新告诉给Follower。
当Leader崩溃或者Leader失去大多数的Follower时,需要重新选举一个新的Leader,让所有服务器都恢复到一个正确的状态。
当Leader被选举出来,且大多数服务器进程完成了和Leader的状态同步后,Leader election 的过程就结束了,将会进入到Atomic Brodcast 过程。
Atomic Brodcast 同步Leader 和Follower 之间的信息,保证Leader和Follower具有相同的系统状态。
随着近年来互联网系统规模的不断扩大,大数据时代飞速到来,越来越多的分布式系统将Zookeeper作为核心组件使用,如Hadoop,HBase 和Kafka等,因此,正确理解ZooKeeper的应用场景,对于ZooKeeper的使用者来说,显得尤为重要。下面我们就来了解一下ZooKeeper的典型应用场景。
数据发布与订阅(配置中心)
数据发布/订阅(Publish/Subscribe)系统,即所谓的配置中心,顾名思义就是发布者将数据发布到ZooKeeper的一个或一系列节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。应用中的一些配置信息放到ZooKeeper上进行集中管理,通常是应用在启动的时候会主动获取一次配置,同时,在节点上注册一个Watcher,这样一来,以后每次配置有更新的时候,都会实时通知到订阅的客户端,从来达到获取最新配置信息的目的。
软负载均衡
在分布式环境中,为了保证高可用性,通常一个应用或服务都会部署多份,达到对等服务。而消费者就需要在这些对等服务器中选择一个来执行相关的业务逻辑。其中比较典型的是消息中间件的生产者和消费者负载均衡。LinkedIn开源的Kafka和阿里开源的metaq都是通过ZooKeeper来做到生产者、消费者的负载均衡。这里以Kafka为例:
1、每当一个Broker启动时,会首先完成Broker注册过程,在ZooKeeper的节点列表里保存Broker。
2、Kafka的生产者会对ZooKeeper上的Broker的新增与减少、Topic的新增与减少和Broker和Topic关联关系的变化等事件注册Watcher监听
3、通过ZooKeeper的Watcher通知能够让生产者动态获取Broker和Topic的变化情况
4、Kafka有消费分组的概念,每个消费者分组包含了若干个消费者,每条消息只会发送给分组内的一个消费者,不同消费者分组消费自己特定的Topic下面的消息,互不干扰。
5、Kafka 会为每个消费者分配全局唯一的Consumer ID,采用“Hostname:UUID”形式来表示
6、每个消费者一旦确定了对一个消息分区的消费权利,ZooKeeper会将其ConsumerID写入到对应消息分区的临时节点上
分布式通知/协调
分布式协调/通知服务是分布式系统中不可缺少的一个环节,是将不同的分布式组件有机结合起来的关键所在。对于一个在多台机器上部署运行的应用而言,通常需要一个协调者来控制整个系统的运行流程,例如分布式事务的处理、机器间的互相协调等。同时引入ZooKeeper作为协调者,便于将分布式协调的职责从应用中分离出来,从而大大减少系统之间的耦合性。
ZooKeeper中特有的Watcher注册与异步通知机制,能够很好地实现分布式环境下不同机器,甚至是不同系统之间的协调与通知,从而实现对数据变更的实时处理。基于ZooKeeper实现分布式协调与通知功能,通常的做法是不同客户端都对ZooKeeper上同一个数据节点进行Watcher注册,监听数据节点的变化,如果数据节点发生变化,那么所有订阅的客户端都能够接收到相应的Watcher通知,并做出相应的处理。
分布式锁
分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。锁服务分为两类,一个是独占锁,另一个是共享锁。所谓独占锁。就是所有视图获取锁的客户端,最终只有一个可以成功获得这把锁。通常的做法是把ZK上的一个znode看做是一把锁,通过create znode的方式来实现。所有客户端都去创建/distribute_lock节点,最终只有一个客户端能够创建成功。那么就可以认为该客户端获取了锁。所谓共享锁(Shared Locks,简称S锁)又称为读锁。下图展示了共享锁的加锁过程。
鲸技术团队的各个项目目前均采用集群部署,同一个项目都会部署多台。这种情况下,两个或多个机器尝试执行特定任务,而实际上只需在任意给定时间由单个机器完成。在这种场景下ZooKeeper分布式锁可以帮助我们控制任务只在一台机器上运行。
首先尝试获得独占锁,代码如下:
在跑批任务执行之前检查本台服务器是否可以跑批,只有成功获得锁的服务才可以执行跑批任务,避免任务重复执行。
总结:ZooKeeper 是一个高可用的分布式数据管理与系统协调框架。基于对ZAB算法的实现,该框架很好的保证了分布式环境中数据的一致性。基于这样的特性,使得ZooKeeper成为了解决分布式一致性问题的利器。随着近年来互联网系统规模的不断扩大,越来越多的分布式系统将ZooKeeper作为核心组件使用。因此正确理解ZooKeeper的应用场景,对于研发人员来说,显得尤为重要。
- END -