在zookeeper的介绍中,我们经常会看到这样一句话,ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。可以看出,zookeeper主要是在分布式系统中,对各个子系统起到协调的作用,主要解决分布式环境各个系统数据的一致性问题。

ZooKeeper 实现诸如配置管理,注册中心,数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

目前在比较流行的应用或框架中都有被用到,像Hadoop、solr、kafka、dubbo中都有用到,可见其在当下环境中,构建集群或微服务环境都是起着举足轻重的作用。

  • 下载及安装

直接在官网下载,地址https://www.apache.org/dyn/closer.cgi/zookeeper/,我们选择下载.tar.gz版本的,这样直接解压就可以使用了。

首先修改下config/zoo_sample.cfg,将其拷贝一份,命名为zoo.cfg即可。一般情况下,我们会修改下数据与日志的存放路径:

dataDir=../data
dataLogDir=../data/log

然后在bin目录下,双击zkServer.cmd,即可启动,如下:

zookeeper 管理工具 zookeeper的使用_zookeeper

和大多数应用一样,zookeeper也为我们提供了cli方式进行操作。

从中摘取了部分内容,上面提到,zookeeper主要帮助我们保证分布式环境中,协调各个子系统可靠的工作,而zookeeper提供的主要还是数据的存取与监听服务,在这些基础服务的基础上,在各种应用场景下,让它帮助我们完成了更多的功能,比如保证数据的一致性,完成服务的注册发现等,那么这些设计的前提必须要满足几点:

1. 一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是ZooKeeper最重要的性能。
2. 可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3. 实时性:ZooKeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,ZooKeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4. 等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
5. 原子性:更新只能成功或者失败,没有中间状态。
6. 顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

zookeeper是存储结构非常类似于文件系统,每一个目录对应了一个节点(znode),数据都存储在各个节点上,对节点的访问必须是绝对路径,因为每个节点都是唯一的,同时每个节点可以设置访问控制ACL,或者设置watch来监听节点关联数据的变化,节点主要有stat、data、children三个属性,其中stat:

zookeeper 管理工具 zookeeper的使用_zookeeper_02

从节点的性质看,一共分为四种类型:

1、临时无序 断开连接则删除,其实是session断开或关闭
2、临时有序 同上,只不过节点由zookeeper进行顺序编号
3、持久无序 持久化的节点在连接断开后依然存在
4、持久有序 同上,只不过节点由zookeeper进行顺序编号
-注意:
临时节点不能有子节点
数据存在节点上,而数据都有版本号的
节点都可以被客户端监听,当出现节点上数据修改、子节点变化,都会进行通知

对节点的操作前提是有对应的ACL权限,在建立节点时,可以设置对该节点有那哪些操作权限,一共有以下这些可选值:

CREATE: 创建子节点的权限。(对子节点)
READ: 获取节点数据和子节点列表的权限。
WRITE:更新节点数据的权限。
DELETE: 删除子节点的权限。(对子节点)
ADMIN: 设置节点ACL的权限。

zookeeper中服务器与客户端间是通过tcp长连接进行通信,在连接成功后会建立两者间的会话(session),之后的请求都是依赖于此,而维持会话的则是通过心跳检查机制。session有以下几个状态:CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE等。在每次请求过程中,都会重新激活会话,当然,如果客户端长时间没有与服务器通信,则会在1/3超时时间时通过PING命令维持会话。【参考

一般不会在单机下使用zookeeper,那样可靠性就没了保证,那么在集群环境中,zookeeper是如何保证数据的一致性呢?

首先需要了解,zookeeper集群中会将各个机器分为三个角色:
1、Leader:系统故障时完成数据恢复;保证并维持多台机器的状态一致;发起投票与决策。
    维持服务器间的心跳连接,并接受处理其发送的请求,讲多请求的有序化,保证请求的有序与原子性。
2、Fllower:与Leader通信保存连接;Leader故障参与选举;与客户端通信与数据交互。
    向Leader发送命令(PING消息、REQUEST消息、ACK消息、REVALIDATE消息),处理Leader的命令。
    处理客户端请求,写则交由Leader完成。
3、Observer:类似Fllower,但不参与集群选举与投票。
    对集群的扩展
消息类型:
    PING消息: 心跳消息;
    PROPOSAL消息:Leader发起的提案,要求Follower投票;
    COMMIT消息:服务器端最新一次提案的信息;
    UPTODATE消息:表明同步完成;
    REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
    SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
-

那么zookeeper的具体原理又是怎样的呢?

1、zookeeper保证数据一致性的关键是ZAB协议,该协议主要完成两点功能,恢复、广播。当Leader出现故障导致崩溃时,出现新的选举,当选举完新的Leader后,会进行状态恢复;而广播模式让Leader与Learner保持状态一致。
2、为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数
3、每个Server在工作过程中有三种状态:
    LOOKING:当前Server不知道leader是谁,正在搜寻
    LEADING:当前Server即为选举出来的leader
    FOLLOWING:leader已经选举出来,当前Server与之同步
--选举【参考】
  当系统启动或者leader崩溃后,就会开始leader的选举。
    1.状态变更。服务器启动的时候每个server的状态时Looking,如果是leader挂掉后进入选举,那么余下的非Observer的Server就会将自己的服务器状态变更为Looking,然后开始进入Leader的选举状态;
    2.发起投票。每个server会产生一个(sid,zxid)的投票,系统初始化的时候zxid都是0,如果是运行期间,每个server的zxid可能都不同,这取决于最后一次更新的数据。将投票发送给集群中的所有机器;
    3.接收并检查投票。server收到投票后,会先检查是否是本轮投票,是否来自looking状态的server;
    4.处理投票。对自己的投票和接收到的投票进行PK:
        先检查zxid,较大的优先为leader;
        如果zxid一样,sid较大的为leader;
        根据PK结果更新自己的投票,在次发送自己的投票;
    5.统计投票。每次投票后,服务器统计投票信息,如果有过半机器接收到相同的投票,那么leader产生,如果否,那么进行下一轮投票;
    6.改变server状态。一旦确定了Leader,server会更新自己的状态为Following或者是Leading。
    7.选举结束。
说明:
    在步骤2发送投票的时候,投票的信息除了sid和zxid,还有:
        electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作。
        peerEpoch:被推举的Leader的epoch。
        state:当前服务器的状态。
    为了能够相互投票,每两台服务器之间都会建立网络连接,为避免重复建立TCP连接,zk的server只允许sid大于自己的服务器与自己建立连接,否则断开当前连接,并主动和对方建立连接。
--请求流程
    1.在Client向Follwer发出一个写的请求
    2.Follwer把请求发送给Leader
    3.Leader接收到以后开始发起投票并通知Follwer进行投票
    4.Follwer把投票结果发送给Leader
    5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;
    6.Follwer把请求结果返回给Client
--事务一致
    更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
    数据更新原子性,一次数据更新要么成功,要么失败。
    全局唯一数据视图,client无论连接到哪个server,数据视图都是一致的。
    实时性,在一定事件范围内,client能读到最新数据。
--
  • 应用场景(【参考】)
1、命名服务
2、配置管理
3、集群管理
4、分布式锁
5、队列管理
6、发布订阅
  • 常用命令
conf 输出相关服务配置的详细信息。
cons 列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。
dump 列出未经处理的会话和临时节点。
envi 输出关于服务环境的详细信息(区别于 conf 命令)。
reqs 列出未经处理的请求
ruok 测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。
stat 输出关于性能和连接的客户端的列表。
wchs 列出服务器 watch 的详细信息。
wchc 通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。
wchp 通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。

zookeeper 管理工具 zookeeper的使用_服务器_03

  • ZAB协议与Paxos算法