ZooKeeper专题(十二)——服务安装及知识总结

By timebusker on May 1, 2017

单机服务安装

# 解压下载安装包,进入  zookeeper-3.4.10\conf 目录
# cp zoo_sample.cfg zoo.cfg
# 编辑zoo.cfg文件
tickTime=2000
dataDir=/root/zookeeper/data/
dataLogDir=/root/zookeeper/logs/
clientPort=2181

# tickTime     Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,单位毫秒
# dataDir      保存zookeeper数据路径
# dataLogDir   保存zookeeper日志路径,当此配置不存在时默认路径与dataDir一致
# clientPort   客户端访问zookeeper时经过服务器端时的端口号

真实集群安装

# 解压下载安装包,进入  zookeeper-3.4.10\conf 目录
# cp zoo_sample.cfg zoo.cfg
# 编辑zoo.cfg文件
tickTime=2000
# 当事务日志记录的次数达到一定数量后(默认10W次),就会将内存数据库序列化一次,使其持久化保存到磁盘上,序列化后的文件称为"快照文件"。每次拍快照都会生成新的事务日志。
# ZooKeeper的数据目录,主要目的是存储内存数据库序列化后的快照路径。如果没有配置事务日志(即dataLogDir配置项)的路径
dataDir=/root/zookeeper/data/
# 指定事务日志的存放目录。事务日志对ZooKeeper的影响非常大,强烈建议事务日志目录和数据目录分开,不要将事务日志记录在数据目录(主要用来存放内存数据库快照)下
dataLogDir=/root/zookeeper/logs/
# 将数据目录与日志目录隔离开,避免高性能障碍


clientPort=2181
initLimit=10
syncLimit=5

# tickTime     Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,单位毫秒
# dataDir      保存zookeeper数据路径
# dataLogDir   保存zookeeper日志路径,当此配置不存在时默认路径与dataDir一致
# clientPort   客户端访问zookeeper时经过服务器端时的端口号
# initLimit    配置Zookeeper接受客户端(这里所说的客户端不是用户连接Zookeeper服务器的客户端,而是Zookeeper服务器集群中连接到Leader的Follower 服务器)
#              初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过10个心跳的时间(也就是tickTime)长度后Zookeeper 服务器还没有收到客户端的返回信息,
#              那么表明这个客户端连接失败。总的时间长度就是10*2000=20 秒。
# syncLimit    配置项标识Leader与Follower之间发送消息,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是5*2000=10秒。

server.1=12.12.12.21:2881:3881
server.2=12.12.12.22:2881:3881
server.3=12.12.12.23:2881:3881

# server.A=B:C:D
# A   是一个数字,表示这个是第几号服务器;
# B   是这个服务器的IP地址(或者是与IP地址做了映射的主机名);
# C   第一个端口用来集群成员的信息交换,表示这个服务器与集群中的Leader服务器交换信息的端口;
# D   是在leader挂掉时专门用来进行选举leader所用的端口。

# 创建myid文件,标志服务唯一编号
# cd 到 dataDir 配置目录下  dataDir=/root/zookeeper/data/
cd  /root/zookeeper/data/  
echo 1 > /root/zookeeper/data/myid


# 启动服务
zkServer.sh start
# 查看服务状态
zkServer.sh status

伪集群模式安装

暂无…..

知识总结

zookeeper是什么?

image

  • ZooKeeper是一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。 所有这些类型的服务都以分布式应用程序的某种形式使用。 每次实现某个服务时都需要做很多工作来修复不可避免的错误和竞争条件(资源竞争等情况)。 由于难以实现这些类型的服务,应用程序最初通常会吝啬(规避)它们,这使得它们在变化的情况下变得脆弱并且难以管理。 即使正确完成,这些服务的不同实现也会在部署应用程序时导致管理复杂性。

zookeeper能做什么?

  • 配置维护 :在分布式系统中,一般会把服务部署到n台机器上,服务配置文件都是相同的,如果配置文件的配置选项发生了改变,那我们就得一台一台的去改动。这时候zookeeper就起作用了,可以把zk当成一个高可用的配置存储器,把这样配置的事情交给zk去进行管理,将集群的配置文件拷贝到zookeeper的文件系统的某个节点上,然后用zk监控所有分布式系统里的配置文件状态,一旦发现有配置文件发生了变化,那么每台服务器同步zk的配置文件,zk同时保证同步操作的原子性,确保每个服务器的配置文件都能被更新。
  • 命名服务 :在分布式应用中,通常需要一个完整的命名规则,既能够产生唯一的名称又便于人识别和记住。Zk就提供了这种服务,类似于域名和ip之间对应关系,域名容易记住,通过名称来获取资源和服务的地址,提供者等信息。
  • 分布式锁 :分布式程序分布在不同主机上的进程对互斥资源进行访问的时候需要加锁。这样理解:很多分布式系统有多个服务窗口,但是某个时刻只让一个服务去干活,当这台服务器出问题的时候锁释放,立即fail over到另外的服务。举例子,比如去某个地方办理证件的时候,只能有一个窗口对你服务,如果这个窗口的柜员有急事走了,那么系统或者经理给你指定另外一个窗口继续服务。
  • 集群管理 :分布式集群中,经常会由于各种原因,比如硬件故障,网络问题,有些节点挂掉、有些节点加进来。这个时候机器需要感知到变化,然后根据变化做出对应的决策,那么zk就实现了类似这种集群的管理。
  • 队列管理 :类似一些mq实现队列的功能,这个不常用,不适合高性能的应用。

zookeeper的角色管理

  • 领导者(Leader):领导者负责进行投票的发起和决议,更新系统状态。
  • 学习者(Learner)
    • 跟随者(Follower):用于接受客户请求并向客户端返回结果,在选主过程中参与投票。
    • 观察者(ObServer):ObServer可以接受客户端连接,将写请求转发给leader节点,但ObServer不参加投票过程,只同步leader状态。ObServer的目的是为了扩展系统,提高读取速度。
  • 客户端(Client):请求发起方。

zookeeper设计原则

  • 最终一致性:客户端(Client)无论连接到哪个zk的节点,展示给他的视图都是一样的。
  • 可靠性:消息message被到一台服务器接受,那么它到任何服务器都被接受。
  • 实时性:zk保证在一个时间间隔范围内获得服务器的更新信息,或者服务器失效信息。但是由于网络延时等一些其他原因,zk不能保证两个客户端同事得到跟新或者失效信息。
  • 等待无关:慢的或者失效的客户端(Client)不得干预快速的client的请求,使得每个client都能有效的等待。
  • 原子性:更新只能成功或者失败,没有其他中间信息。
  • 顺序性:包括全局有序和偏序两种:全局有序是指如果再一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

zookeeper工作原理

  • 命令登录ZK服务./zkCli.sh -server 12.12.12.21:2181
  • 基本操作命令:ls /目录 get /目录

ZK的核心是原子广播,这个机制保证了各个Server之间的同步,实现这个机制的协议叫做Zab协议。Zab协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。 当服务启动或者领导者崩溃后,Zab进入恢复模式,当leader被选举出来,然后进行同步模式,同步完成以后,恢复模式结束。

为了保证事务的顺序一致性。实现中zxid是一个64位的数字,它高32位是用epoch用来标志leader关系是否改变, 每次一个新的leader选举出来,都会拥有一个新的epoch。低32位用来递增计数。

  • Serverid:在配置server时,给定的服务器的标示id。
  • Zxid:服务器在运行时产生的数据id,zxid越大,表示数据越新。
  • Epoch:选举的轮数,即逻辑时钟。随着选举的轮数++

每个Server在工作过程中有三种状态:

  • LOOKING:当前Server不知道Leader是谁,正在搜寻。
  • LEADING:当前Server即为选举出来的leader。
  • FOLLOWING:leader已经选举出来,当前Server与之同步。

选主流程

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,然后需要重新选举出一个leader。让所有的Server都恢复到一个正确的状态。 Zk选举算法有两种,一种是基于basic paxos实现,一种是基于fast paxos算法实现。系统默认的是fast paxos。

basic paxos流程
  • 选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server。
  • 选举线程首先向所有Server发起一次询问(包括自己)。
  • 选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(myid,zxid),并将这些信息存储到当次选举的投票记录表中。
  • 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次投票的Server。
  • 线程将当前zxid最大的Server设置成为当前Server要推荐的Leader,若果此时获胜的Server获得n/2+1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置成自己的状态,否则,继续这个过程,直到leader被选举出来。
    备注:要使Leader获得多数的Server支持,则Server总数必须是奇数2n+1,且存活的Server的数据不得少于n+1。
    image
fast paxos流程(basic paxos算法优化)

Basic Paxos算法在出现竞争的情况下,其收敛速度很慢,甚至可能出现活锁的情况, 例如当有三个及三个以上的节点在发送选举提案请求后,很难有一个节点收到半数以上的回复而不断地执行第一阶段的协议。 因此,为了避免竞争,加快收敛的速度,在Fast Paxos算法中引入了一个Leader这个角色,在正常情况下同时应该最多只能有一个参与者扮演Leader角色, 而其它的参与者则扮演接收选举的角色,同时所有的人又都扮演Learner的角色。

在这种优化算法中,只有Leader可以提出议案,从而避免了竞争使得算法能够快速地收敛而趋于一致,此时的paxos算法在本质上就退变为两阶段提交协议。 但在异常情况下,系统可能会出现多Leader的情况,但这并不会破坏算法对一致性的保证,此时多个Leader都可以提出自己的提案, 优化的算法就退化成了原始的paxos算法。

image

  • server启动、恢复准备加入集群,此时都会读取本身的zxid等信息。
  • 所有server加入集群时都会推荐自己成为leader,然后将(leader id,zxid,epoch)作为广播信息到集群中所有的server,等待集群中的server返回信息。
  • 收到集群中其他服务器返回的信息,分为两类,服务器处于looking状态,或者其他状态。
    • 服务器处于looking状态
      说先判断逻辑时钟Epoch:
      (a)如果接受到Epoch大于自己目前的逻辑时钟,那么更新本机的Epoch,同时clear其他服务器发送来的选举数据。然后判断是否需要更新当前自己的选举情况(开始选择的leader id是自己)。判断规则:保存的zxid最大值和leader id来进行判断。先看数据zxid,zxid大的胜出;其次判断leader id,leader id大的胜出;然后再将自身最新的选举结果广播给其他server。
      (b)如果接受到的Epoch小于目前的逻辑时钟,说明对方处于一个比较低一轮的选举轮数,这时需要将自己的选举情况发送给它即可。
      (c)如果接收到的Epoch等于目前的逻辑时钟,再根据(a)中的判断规则,将自身的最新选举结果广播给其他server。
      同时server还要处理两种情况:
      (a)如果server接收到了其他所有服务器的选举信息,那么则根据这些选举信息确定自己的状态(Following,Leading),结束Looking,退出选举。 (b)即时没有收到所有服务器的选举信息,也可以判断一下根据以上过程之后最新的选举leader是不是得到了超过半数以上服务器的支持,如果是则尝试接受最新数据,如果没有最新数据,说明都接受了这个结果,同样也退出选举过程。
    • 服务器处于其他状态(Following,Leading)
      (a)若果逻辑时钟Epoch相同,将该数据保存到recvset,若果所接受服务器宣称自己是leader,那么将判断是不是有半数以上的服务器选举他,若果是则设置选举状态退出选举过程。
      (b)若果Epoch不相同,那么说明另一个选举过程中已经有了选举结果,于是将选举结果加入到outofelection集合中,再根据outofelection来判断是否可以结束选举,保存逻辑时钟,设置选举状态,并退出选举过程。
同步流程(选主完成后)
  • leader等待server连接。
  • follower连接到leader,将最大的zxid发送给leader。
  • leader根据zxid确定同步点。
  • 同步完成之后,通知follower成为uptodat状态。
  • follower收到uptodate消息后,开始接受client请求服务。
Leader主要功能
  • 恢复数据。
  • 维持与Learner的心跳,接受Learner请求并判断Learner的请求消息类型。
  • 备注:Learner的消息类型主要是ping、request、ack、revalidate。
    • ping消息:是指Learner的心跳信息。
    • request消息:follower发送的提议信息,包括写请求和同步请求。
    • ack消息:是follower对提议的回复,超过半数follower通过,则commit提议。
    • revalidate消息:用来延长session有效时间。
Follower主要功能
  • 向Leader发送请求。
  • 接受Leaser消息并进行处理。
  • 接受Client的请求,如果是写请求,发送给Leader进行投票。
  • 返回结果给Client。
  • 备注: follower处理Leader的如下几个消息:
    • ping:心跳信息。
    • proposal消息:leader发起提案,要求follower投票。
    • commit消息:服务器端最新一次提案的消息。
    • uptodate消息:表明同步完成。
    • revalidate消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
    • sync消息:返回sync信息到client客户端。

zookeeper读写数据流程

  • 读数据:
    zookeeper连接客户端可以随时连接任何一个server读取任何一个目录下的最近成功的一次数据 (zookeeper因为写数据的同步延时,不能保证任何时候数据完全一致,只能保证最终数据一致性)。

因为集群中所有的zk节点都呈现一个同样的命名空间视图(就是结构数据),上面的写请求已经保证了写一次数据必须保证集群所有的zk节点都是同步命名空间的, 所以读的时候可以在任意一台zk节点上。

  • 写数据:
    当一个客户端进行写数据请求时,会指定zk集群中节点,如果是follower接收到写请求,就会把请求转发给Leader,Leader通过内部的Zab协议进行原子广播, 直到所有(N/2+1个节点完成)zk节点都成功写了数据后(内存同步以及磁盘更新)。** 这次写请求算是完成,然后zk service就会给client发回响应。**
    image
    • Client 向 ZooKeeper 的 Server1 上写数据,发送一个写请求。
    • 如果Server1不是Leader,那么Server1 会把接受到的请求进一步转发给Leader,因为每个ZooKeeper的Server里面有一个是Leader。这个Leader 会将写请求广播给各个Server,比如Server1和Server2, 各个Server写成功后就会通知Leader。
    • 当Leader收到大多数(N/2+1) Server 数据写成功了,那么就说明数据写成功了。如果这里三个节点的话,只要有两个节点数据写成功了,那么就认为数据写成功了。写成功之后,Leader会告诉Server1数据写成功了。
    • Server1会进一步通知 Client 数据写成功了,这时就认为整个写操作成功。
    • ZooKeeper 整个写数据流程就是这样的。 image

ZooKeeper的原子广播机制和Zab协议

Zookeeper的核心是原子广播机制,这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式和广播模式。

(1) 恢复模式 当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数server完成了和leader的状态同步以后, 恢复模式就结束了。状态同步保证了leader和server具有相同的系统状态。

(2) 广播模式 一旦Leader已经和多数的Follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。这时候当一个Server加入ZooKeeper服务中, 它会在恢复模式下启动,发现Leader,并和Leader进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper服务一直维持在Broadcast状态, 直到Leader崩溃了或者Leader失去了大部分的Followers支持。

https://mp.weixin.qq.com/s?__biz=MzU0ODI5NTM1MQ==&mid=2247484512&idx=1&sn=760919b661be2b66ad55482644149767&scene=19#wechat_redirect