美文网首页
Zookeeper学习笔记

Zookeeper学习笔记

作者: 我是老薛 | 来源:发表于2018-12-07 20:32 被阅读0次

    本文是对Zookeeper组件基础知识的一个学习总结,包含如下章节内容:

    • Zookeeper是什么
    • Zk文件系统
    • Zk的观察机制
    • Zk的设计思路
    • 安装和运行
    • 命令行程序

    一、Zookeeper是什么

    ZooKeeper(下面简称Zk)是一个开源的分布式协调服务组件,它为分布式应用提供了高效且可靠的分布式协调服务,提供了诸如统一命名空间服务,配置服务和分布式锁等分布式基础服务。

    Zk是一个独立的组件,不依赖其它服务。它本身就是一个分布式应用。作为分布式应用,分为Server(服务器) 和 Client(客户端) 两部分。作为Zk的使用者,可以使用Zk组件提供的客户端(命令行程序)或自己利用Zk提供的api编写客户端程序来访问Zk服务器。

    hadoop生态圈中很多分布式组件都使用Zk来作为分布式协调服务,如hdfs HA(High Availability), yarn HA, hbase,kafka等,从这角度看,hbase等就是Zk服务的客户端。当然,也可以使用Zk提供的服务来开发自己的分布式应用程序。

    二、Zk文件系统

    Zk服务的核心是一个精简的文件系统,类似linux文件系统的树形层次结构,与文件系统节点分目录和文件不同,Zk文件系统中的节点统一称为znode。如下图所示:


    Zk文件系统的信息会保存在内存中(以加快读取的速度),同时会进行持久化。

    (一)znode的概念

    znode通过路径被引用,类似linux文件系统的路径。根节点用/表示,其余节点从/开始加上各层节点的名称,如/zoo/duck。但是与文件系统路径不同,znode没有相对路径的概念,每个节点都以绝对路径标识。

    znode既可以作为保存数据的容器(如同文件),也可以作为保存其它znode的容器(如目录)。znode除了可以保存数据外(保存的数据不能太大,一个znode存储的数据被限制在1M以内),znode本身就是一个数据结构,其中的信息称为元数据(如创建时间、子节点信息、版本信息、ACL信息等)。

    (二)znode的操作

    znode支持如下9种基本操作:

    • create:创建znode
    • delete:删除znode
    • exists:测试一个znode是否存在并且查询它的元数据
    • getChildren:获取一个znode的子节点列表
    • setACL:设置znode的ACL
    • getACL:获取znode的ACL
    • setData:设置znode所保存的数据
    • getData:获取znode所保存的数据
    • sync:将客户端的znode视图与zk服务器同步

    (三)znode的类型

    znode可分为短暂的(或叫临时的)和持久的。所谓短暂znode,是指创建该节点的客户端会话结束后,该节点会被自动删除。而持久znode的生存期与创建它的客户端会话无关,如果要删除,需要显示的执行命令删除。注意,短暂znode不可以有子节点。

    顺序znode:指znode的名称中包含顺序号。当我们创建一个顺序znode时,框架会自动在指定的名称之后附加一个单调递增的计数器值(由父节点维护),并且保证这个计数器值是唯一的。注意,顺序znode可以是持久的,或短暂的。

    (四)znode的版本信息

    znode有版本信息,对于每个znode来说,均存在三个版本号:

    1. dataVersion
      数据版本号,每次对节点进行set操作,dataVersion的值都会增加1(即使设置的是相同的数据),初始值为0。

    2. cversion
      子节点的版本号。当znode的子节点有变化时,cversion 的值就会增加1,初始值为0。

    3. aclVersion
      ACL的版本号。

    下面以dataVersion (数据版本号)为例来说明Zk中版本号的作用。每一个znode都有一个数据版本号,它随着每次数据变化而自增。ZooKeeper提供的一些API例如setData和delete根据版本号有条件地执行。多个客户端对同一个znode进行操作时,版本号的使用就会显得尤为重要。例如,假设客户端C1对znode /config写入一些配置信息,如果另一个客户端C2同时更新了这个znode,此时C1的版本号已经过期,C1调用setData一定不会成功。这正是版本机制有效避免了数据更新时出现的先后顺序问题。在这个例子中,C1在写入数据时使用的版本号无法匹配,使得操作失败。因此使用版本号可用来阻止并行操作的不一致性。

    (五)znode的ACL列表

    每个znode都有一个ACL(权限控制列表),用于决定哪个客户端可以对它执行何种操作,也就是说一种权限控制的方式。 znode的ACL列表可以在创建时指定,也可以后续重新设置。如果不加设置,默认所有客户端可以对znode进行任何操作。关于ACL的更详细信息本文不再介绍。

    三、Zk的观察机制

    当znode的发生变化时,Zk提供一种观察(watch)机制可以让希望获取这个变化信息的客户端得到通知。当一个客户端对一个节点设置了观察,如果该节点发生变化(如被删除、设置数据、添加/删除子节点等),Zk框架会通知设置了观察的客户端。

    注意,节点上设置了观察,当节点发生变化后,只会通知一次。如果想再次获取通知,需要重新设置。

    四、Zk的设计思路

    在集群环境下,Zk通过复制来实现高可用性,只要集群环境下的超过一半机器处于可用状态,它就能提供服务。比如一个集群有5个节点,任意2台机器出现问题,但因为还有3台机器可用,3台超过1半,所以服务可以继续保证。如果集群是6台节点,也最多只能有2台机器出问题,因为如果有3台机器有问题,则可用的没超过一半,服务也不可用。因此,对于Zk的集群,其节点的数量通常配置为奇数个。

    集群中的节点分为两种类型:领导者(leader)和跟随着(flower)。 集群中的机器通过一个选择过程来选出领导者,其它的机器就作为跟随者。如果领导者出现故障,其它机器就会选出一个新的领导者。随后,如果之前的领导者恢复,则会成为一个跟随者。

    Zk客户端可以连接到任意一台Zk服务器,但是所有的写请求都会被转发给领导者,再由领导者将更新广播给跟随者,当半数以上的跟随者已经将修改持久化之后,领导者才会提交这个更新,然后客户端才会收到一个更新成功的响应。

    下面示意图可以简单说明上面描述的内容:


    (摘自hadoop权威指南一书)

    五、安装和运行

    Zk既可以运行在windows系统下,也可以运行在liunux系统下。它有两种不同的运行模式。一种是独立模式,即只有一个Zk服务器,这种模式只适合开发测试环境,不能保证高可用性和可恢复性。另一种是复制模式,运行在集群环境下,至少需要三台机器(启动3个Zk服务)。在本文中,我们使用独立模式来学习Zk的基本概念和操作。

    1、下载Zookeeper,本文下载的版本是zookeeper-3.4.10.tar.gz。

    将该压缩文件解压到某个目录下。

    2、修改conf 下的zoo.cfg文件(如果没有就新建),增加如下的配置信息,最少的配置信息如下(假设我们采用独立模式运行Zk服务器,即只在一台机器上启动单个Zk服务),其它配置信息采用默认值。

    tickTime=2000
    dataDir= 本地某目录
    clientPort=2181
    

    tikeTime是超时时间设置(单位是毫秒);dataDir用于设置一个本地目录,保存Zk文件系统的持久化信息。clientPort是设置Zk服务器的端口号。

    3、启动Zk服务器
    启动服务器的程序位于Zk安装目录下的bin目录下,windows下的可执行程序为zkServer.cmd,linux下的可执行程序是zkServer.sh

    说明:可以将bin目录加到PATH环境变量下,这样可以在任意在目录下运行服务器程序。

    六、命令行程序

    Zk提供了一个命令行程序,可以连接到Zk服务器,执行对znode的各种操作。该命令行程序在Zk安装目录的bin目录下,windows下的程序名叫zkCli.cmd,linux下的程序名叫zkCli.sh

    如果是连接到本机的服务器,在控制台中运行上面客户端程序即可。
    如果是连接到其它机器的服务器,则加上服务器ip地址和端口即可。如:zkCli.cmd/zkCli.sh -server IP地址:2181

    如果一切正常,则就可以执行命令了。下面展示一些常见的命令:

    1、ls命令
    语法: ls 节点路径
    含义:列出指定节点下的所有子节点名称
    举例:

    [zk: localhost:2181(CONNECTED) 0] ls /
    [cluster, brokers, zookeeper, admin,  zoo]
    [zk: localhost:2181(CONNECTED) 1] ls /zoo
    [dd]
    

    2、ls2命令
    语法: ls2 节点路径
    含义:列出指定节点下的所有子节点名称 ,以及当前节点的元数据信息,如time、version等信息
    举例:

    [zk: localhost:2181(CONNECTED) 2] ls2 /zoo
    [dd]
    cZxid = 0xf1
    ctime = Mon Dec 03 17:17:41 CST 2018
    mZxid = 0x126
    mtime = Tue Dec 04 20:03:09 CST 2018
    pZxid = 0x106
    cversion = 3
    dataVersion = 11
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 4
    numChildren = 1
    

    3、create命令
    语法: create [-s] [-e] path data acl
    含义:创建znode节点,其中参数path是节点的路径,data是节点存储的字符串数据,-s选项表示是创建短暂的节点,-e选项表示是创建顺序节点。
    举例:

    [zk: localhost:2181(CONNECTED) 8] create /zoo/newnode ""
    Created /zoo/newnode
    [zk: localhost:2181(CONNECTED) 9] create -e /zoo/tmpnode "hello"
    Created /zoo/tmpnode
    [zk: localhost:2181(CONNECTED) 10] create -s /zoo/mynode "data"
    Created /zoo/mynode0000000006
    [zk: localhost:2181(CONNECTED) 11] ls /zoo
    [dd, tmpnode, mynode0000000006, newnode]
    

    4、delete命令
    语法:delete path [version]
    含义:删除指定的节点,path为待删除节点路径。version是节点版本号,如果指定,则version值必须与待删除节点的数据版本号一致,否则无法删除。如果不指定version参数,则删除时不管版本号。如果节点下有子节点,则无法删除。
    举例:

    [zk: localhost:2181(CONNECTED) 17] delete /zoo/newnode 2
    version No is not valid : /zoo/newnode
    [zk: localhost:2181(CONNECTED) 18] delete /zoo/newnode
    [zk: localhost:2181(CONNECTED) 19] ls /zoo/newnode
    Node does not exist: /zoo/newnode
    

    5、set命令
    语法:set path data [version]
    含义:设置znode存储的数据。path为znode路径。data为要设置的字符串内容。version是节点版本号,如果指定,则version值必须与待设置节点的数据版本号一致,否则无法设置。如果不指定version参数,则设置时不管版本号。
    举例:

    [zk: localhost:2181(CONNECTED) 28] set /zoo gooddata
    cZxid = 0xf1
    ctime = Mon Dec 03 17:17:41 CST 2018
    .............
    

    6、get命令
    语法:get path [watch]
    含义:获取znode存储的数据及元数据信息。如果加上watch标记,则表示该客户端对该znode进行观察。当其它客户端(或本客户端)对该znode进行变更后,该客户端会收到通知。
    举例:

    [zk: localhost:2181(CONNECTED) 30] get /zoo watch
    gooddata
    cZxid = 0xf1
    ctime = Mon Dec 03 17:17:41 CST 2018
    mZxid = 0x148
    mtime = Thu Dec 06 10:29:37 CST 2018
    pZxid = 0x145
    cversion = 11
    dataVersion = 14
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 8
    numChildren = 3
    

    上面例子中的get命令加上了可选项watch标记。这时如果我们打开另外一个命令行客户端,并对/zoo节点进行设置存储数据操作。会发现当前客户端会收到消息,如下面内容:

    [zk: localhost:2181(CONNECTED) 30] get /zoo watch
    gooddata
    cZxid = 0xf1
    ctime = Mon Dec 03 17:17:41 CST 2018
    mZxid = 0x148
    mtime = Thu Dec 06 10:29:37 CST 2018
    pZxid = 0x145
    cversion = 11
    dataVersion = 14
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 8
    numChildren = 3
    [zk: localhost:2181(CONNECTED) 31]
    WATCHER::
    
    WatchedEvent state:SyncConnected type:NodeDataChanged path:/zoo
    

    如果我们在另外一个客户端对/zoo节点进行设置存储数据操作后,再次执行set操作,会发现上面客户端不会再收到消息。这正如前面介绍,设置观察后,收到一次消息后观察不再有效,要想再次接受消息,必须重新设置。

    上面介绍了zk命令行客户端的一些常见命令,还有其它一些命令(可以输入help查看所有支持的命令),这里不再一一介绍。在实际应用中,我们更多往往通过zk提供的编程API(如java api)来编写zk客户端程序,这个在后面的文章中介绍。

    相关文章

      网友评论

          本文标题:Zookeeper学习笔记

          本文链接:https://www.haomeiwen.com/subject/pqmxhqtx.html