Zookeeper 说明
Zoo Keeper 顾名思义动物园管理员,因为hadoop生态的各个项目都是动物图标,所以作为协调应用的zookeeper为管理员很形象。
Zookeeper 是 Google 的 Chubby一个开源的实现 ,是 Hadoop 的分布式协调服务
它包含一个简单的原语集,分布式应用程序可以基于 它实现同步服务,配置维护和命名服务等
为什么使用Zookeeper?
大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进 程(如资源、任务分配等)
目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制
协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器
ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用
Keepalived监控节点不好管理
Keepalive 采用优先级监控 • 没有协同工作 • 功能单一
Keepalive可扩展性差
Zookeeper优点(原语)
最终一致性 : 为客户端展示同一个视图,统一的数据视图,这是zookeeper里面一 个非常重要的功能
可靠性 : 如果消息被到一台服务器接受,那么它将被所有的服务器接受,节点故障不影响使用
实时性 : Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
独立性 : 各个Client之间互不干预
原子性 : 更新只能成功或者失败,没有中间状态
顺序性 : 所有Server,同一消息发布顺序一致。队列FIFO,主从模型,一写多读
zookeeper的工作原理
每个Server在内存中存储了一份数据;
Zookeeper启动时,将从实例中选举一个leader(Paxos 协议)
Leader负责处理数据更新等操作
一个更新操作成功,当且仅当大多数Server在内存中成功修改数据。
Zookeeper能帮我们做什么?
Hadoop,使用Zookeeper的事件处理确保整个集群只有一个NameNode,存储配置信息等.
HBase,使用Zookeeper的事件处理确保整个集群只有 一个HMaster,察觉HRegionServer联机和宕机,存储 访问控制列表等.
Zookeeper的特性
Zookeeper是简单的
Zookeeper是富有表现力的
Zookeeper具有高可用性
Zookeeper采用松耦合交互方式
Zookeeper是一个资源库
Zookeeper的安装和配置(集群模式)
在conf目录下创建一个配置文件zoo.cfg
tickTime=2000
dataDir=/var/zookeeper/data
dataLogDir=/var/zookeeper/dataLog
clientPort=2181
initLimit=5
syncLimit=2
server.1=node01:2888:3888
server.2=node02:2888:3888
server.3=node03:2888:3888
创建myid文件,写入每个节点对应的编号
tickTime : 发送心跳的间隔时间,单位:毫秒
dataDir : zookeeper保存数据的目录。
clientPort : 客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客
户端的访问请求。
initLimit : 这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连 接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5 个心跳的 时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表 明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
syncLimit : 这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最
长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
server.A=B:C:D : 其 中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一 集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这 个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是 一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号
Zookeeper的角色
领导者(leader) : 负责进行投票的发起和决议,更新系统状态 ,维护事物的唯一和有序性
学习者(learner): 包括跟随者(follower)和观察 者(observer)
follower : 接受客户端请求并想 客户端返回结果,在选主过程中参与投票
Observer: 接受客户端连接,将写请求转发给 leader,但observer不参加投票过程,只同步leader 的状态,observer的目的是为了扩展系统,提高读取速度, Server增多,投票阶段延迟增大,影响性能
客户端(client) : 请求发起方
Follower主要有四个功能
向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消 息)
接收Leader消息并进行处理
接收Client的请求,如果为写请求,发送给Leader进行投票
返回给Client结果。
Follower的消息循环处理如下几种来自Leader的消息
PING消息 : 心跳消息
PROPOSAL消息 : Leader发起的提案,要求Follower投票
COMMIT消息 : 服务器端最新一次提案的信息
UPTODATE消息 : 表明同步完成
REVALIDATE消息 : 根据Leader的REVALIDATE结果,关闭待revalidate的 session还是允许其接受消息
每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
Zookeeper的读写机制
Zookeeper是一个由多个server组成的集群
一个leader,多个follower
每个server保存一份数据副本
全局数据一致
分布式读写
更新请求转发,由leader实施
会话session
客户端与集群节点建立TCP连接后获得一个session
如果连接的Server出现问题,在没有超过Timeout时间时,可以连接其他节点
同一session期内的特性不变
Zookeeper工作过程
· Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。
· Zab协议有两种模式,它们分别是 恢复模式(选主) 和 广播模式(同步)
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后 ,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
一旦leader已经和多数的follower进行了状态同步后 ,他就可以开始广播消息了,即进入广播状态。这时候当一个server加入zookeeper服务中,它会在恢复模式下启动,发现leader,并和leader进行状态同步 。待到同步结束,它也参与消息广播。Zookeeper服务一直维持在Broadcast状态,直到leader崩溃了或 者leader失去了大部分的followers支持。
· 广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。
实现中 zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch。低32位是个递增计数。
ZooKeeper状态的每一次改变, 都对应着一个递增的 Transaction id, 该id称为zxid. 由于zxid的递增性质, 如果 zxid1小于zxid2, 那么zxid1肯定先于zxid2发生. 创建任意节点 , 或者更新任意节点的数据, 或者删除任意节点, 都会导致 Zookeeper状态发生改变, 从而导致zxid的值增加.
· 当leader崩溃或者leader失去大多数的follower,这 时候zk进入恢复模式,恢复模式需要重新选举出一个 新的leader,让所有的server都恢复到一个正确的状 态。
Leader选举
每个Server启动以后都询问其它的Server它要投票给谁.
对于其他server的询问,server每次根据自己的状态 都回复自己推荐的leader的id和上一次处理事务的 zxid(系统启动时每个server都会推荐自己)
收到所有Server回复以后,就计算出zxid最大的哪个Server,并将这个Server相关信息设置成下一次要投票的Server。(zxid最大即此server的数据最新)
计算这过程中获得票数最多的的sever为获胜者,如 果获胜者的票数超过半数,则改server被选为leader 。否则,继续这个过程,直到leader被选举出来
leader就会开始等待server连接
Follower连接leader,将最大的zxid发送给leader
完成同步后通知follower 已经成为uptodate状态
Follower收到uptodate消息后,又可以重新接受client的 请求进行服务了
数据一致性与paxos算法
在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致 的状态。
Paxos算法解决的什么问题呢,解决的就是保证每个节点执行相同的操作序列。好吧,这还不简单,master维护一个 全局写队列,所有写操作都必须 放入这个队列编号,那么无论我们写多少个节点,只要写操作是按编号来的,就能保证一 致性。没错,就是这样,可是如果master挂了呢。
Paxos算法通过投票来对写操作进行全局编号,同一时刻,只有一个写操作被批准,同时并发的写操作要去争取选票, 只有获得过半数选票(弱一致性)的写操作才会被批准(所以永远只会有一个写操作得到批准),其他的写操作竞争失败只好再发起一 轮投票,就这样,在日复一日年复一年的投票中,所有写操作都被严格编号排序。编号严格递增,当一个节点接受了一个 编号为100的写操作,之后又接受到编号为99的写操作(因为网络延迟等很多不可预见原因),它马上能意识到自己 数据不一致了,自动停止对外服务并重启同步过程(最终一致性)。任何一个节点挂掉都不会影响整个集群的数据一致性(总2n+1台,除非挂掉大于n台)。
为什么zookeeper集群的数目,一般为奇数个?
Leader选举算法采用了Paxos协议
Paxos核心思想
当多数Server写成功,则任务数据写成功
如果有3个Server,则两个写成功即可
如果有4或5个Server,则三个写成功即可
如果有3个Server,则最多允许1个Server挂掉; 如果有4个Server,则同样最多允许1个Server挂掉 由此,我们看出3台服务器和4台服务器的的容灾能力是一样的。
所以为了节省服务器资源,一般我们采用奇数个数,作为服务器部署个数
Zookeeper的数据模型
层次化的目录结构,命名符合常规文件系统规范 ,便于管理逻辑关系
每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
节点Znode可以包含数据和子节点,但是 EPHEMERAL 类型的节点不能有子节点
Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本
客户端应用可以在节点上设置监视器
节点不支持部分读写,而是一次性完整读写
Zookeeper的节点node
最大包含最大1MB的数据信息,并记录了Zxid等元数据信息
Znode有两种类型,短暂的(ephemeral)和持久的(persistent)
短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不可以有子节点
持久znode不依赖于客户端会话,只有当客户端明确要删除该持久 znode 时才会被删除
Znode的类型在创建时确定并且之后不能再修改
Znode支持序列SEQUENTIAL
Znode有四种形式的目录节点
PERSISTENT
EPHEMERAL
PERSISTENT_SEQUENTIAL
EPHEMERAL_SEQUENTIAL
观察(watcher)
Watcher 在 ZooKeeper 是一个核心功能。
Watcher 可以 监控目录节点的数据变化以及子目录的变化,一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的 Watcher(RPC 调用客户端的上的watcher类 ),从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应 。
可以设置观察的操作:exists,getChildren,getData
可以触发观察的操作:create,delete,setData
Zookeeper API
String create(final String path, byte data[], List acl, CreateMode createMode)
参数: 路径、 znode内容,ACL(访问控制列表)、 znode创建类型
void delete(final String path, int version)
参数: 路径、版本号;如果版本号与znode的版本号不一致,将无 法删除,是一种乐观加锁机制;如果将版本号设置为-1,不会去检 测版本,直接删除
Stat exists(final String path, Watcher watcher)
参数: 路径、Watcher(监视器);当这个znode节点被改变时,将会 触发当前Watcher
Stat exists(String path, boolean watch)
参数: 路径、并设置是否监控这个目录节点,这里的 watcher 是在 创建 ZooKeeper 实例时指定的 watcher
Stat setData(final String path, byte data[], int version)
参数: 路径、数据、版本号;如果为-1,跳过版本检查
byte[] getData(final String path, Watcher watcher, Stat stat)
参数: 路径、监视器、数据版本等信息
List getChildren(final String path, Watcher watcher)
参数: 路径、监视器;该方法有多个重载
ACL
»每个znode被创建时都会带有一个ACL列表,用于决 定谁可以对它执行何种操作
身份验证模式有三种:
digest:用户名,密码
host:通过客户端的主机名来识别客户端
ip: 通过客户端的ip来识别客户端
new ACL(Perms.READ,new Id("host","example.com"));
这个ACL对应的身份验证模式是host,符合该模式的 身份是example.com,权限的组合是:READ
KeeperState.SyncConnected
KeeperState.SyncConnected 时事件类型为 EventType.None
发生在客户端收到ConnectResponse,与客户端协调好session time的时间后,会触发一个 KeeperState.SyncConnected 的None事件类型。
ZK应用场景
统一命名服务
分布式应用中,通常需要有一套完整的命名规则,既 能够产生唯一的名称又便于人识别和记住,通常情况下用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,既对人友好又 不会重复 。
Name Service 是 Zookeeper 内置的功能,只要调 用 Zookeeper 的 API 就能实现
配置管理
配置的管理在分布式应用环境中很常见,例如同一个 应用系统需要多台 PC Server 运行,但是它们运行的 应用系统的某些配置项是相同的,如果要修改这些相 同的配置项,那么就必须同时修改每台运行这个应用 系统的 PC Server,这样非常麻烦而且容易出错。
将配置信息保存在 Zookeeper 的某个目录节点中, 然后将所有需要修改的应用机器监控配置信息的状态 ,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。
集群管理
Zookeeper 能够很容易的实现集群管理的功能,如 有多台 Server 组成一个服务集群,那么必须要一个 “总管”知道当前集群中每台机器的服务状态,一旦 有机器不能提供服务,集群中其它集群必须知道,从 而做出调整重新分配服务策略。同样当增加集群的服 务能力时,就会增加一台或多台 Server,同样也必须 让“总管”知道。
Zookeeper 不仅能够维护当前的集群中机器的服务 状态,而且能够选出一个“总管”,让这个总管来管理集群,这就是 Zookeeper 的另一个功能 Leader Election。
总结
Zookeeper 作为 Hadoop 项目中的一个子项目,是 Hadoop 集群管理的一个必不可少的模块,它主要用 来控制集群中的数据,如它管理 Hadoop 集群中的 NameNode,还有 Hbase 中 Master Election、 Server 之间状态同步等。
Zoopkeeper 提供了一套很好的分布式集群管理的机 制,就是它这种基于层次型的目录树的数据结构,并 对树中的节点进行有效管理,从而可以设计出多种多 样的分布式的数据管理模型
思维导图