ZooKeeper专题(二)——ZK入门

By timebusker on March 31, 2017

ZooKeeper的一些基础

  • 一些协调的原语经常被各个应用间共享,因此构建协调服务的一个基本方法就是使用一系列原语。比如分布式锁构成了一个原语,它包含创建、获得和释放锁。
  • 使用这样的设计会有两个弊端:
    1. 要么能列举全所有原语,要么能不断扩展原语
    2. 没有使用灵活的方式来实现现有原语

因此,ZooKeeper并没有直接暴露原语,而是暴露了类似文件系统的API。

  • ZNode
    ZNode是ZK树形结构的一个节点,它可以包含或者不包含数据。
    ZK提供了如下API,用于操作ZNode。
    1. create path data
    2. delete path data
    3. exists path
    4. getdata path
    5. putdata path data
    6. getChildren path

ZK客户端通过建立一个Session会话,来连接ZK服务,通过这些API来操作ZNode。

  • ZNode模式
    目前ZNode包含持久化模式临时模式(ephemeral)ephemeral模式指的是这个节点在session断了之后就会消失。而持久模式的ZNode则会继续保持。
    在master-worker模式下,ephemeral模式可以用于检测master或者worker是否挂掉。 如果使用持久模式的话,由于ZNode一直存在,无法感知到master或者worker是否已经crash。
    ephemeral模式的节点也可以被主动删除。 除了持久模式和ephemeral模式外,ZNode还可以是有序的(自动分配自增ID到节点上,比如task-1,task-2,task-3)。
    因此ZNode一共有四种形态:
    1. 持久
    2. 持久有序
    3. ephemeral
    4. ephemeral有序

  • Watch和Notifications
    Watch可以避免每次主动去请求数据是否变化,而是当ZNode变化时,来通知。Watch是个一次性操作,每次收到通知后,必须重新watch, 如果时间比较久或者ZNode更新频繁,在此时间之间,可能会有更新没有被通知到(还没来得急watch)。ZNode的创建、删除和修改都可以被watch到。
    遗留问题:ZK是否能得到每次节点通知?
    ZK有个保证是,每次通知被送到每个客户端前,ZNode不会发生下一次的变化。因此客户端可以保证看到的变化是顺序一致的。

  • 版本号 每个ZNode都会带有一个版本号,每次节点变化,版本号就会变化。以此可以避免并发的更新问题(版本号不正确的更新会失败)。

  • 实际操作
    启动ZK: ./zkServer.sh start
    客户端连接 ./zkCli.sh
    退出 :quit
    关闭 ./zkServer.sh stop

Session状态和生命周期

  • Session状态:
    • NOT_CONNECTED
    • CONNECTING
    • CONNECTED
    • CLOSED

创建Session的时候可以设置超时时间t,t意味着如果在t的时间内没有消息,那么这个session就过期。对于客户端而言,如果在1/3t的时间内没有消息, 那么客户端将发送心跳给服务端。在2/3t的时候,客户端开始寻找另个服务端。因此它有1/3t的时间去建立到另个服务端的新的连接。

  • ZXID
    为保证客户端重连到新的服务端时,不会看到过期的更新,保证至少新服务端上的更新比客户端之前看到的更新要新。 ZK有个全局的事务ID,每次更新操作后,ZXID会自增。如果客户端连在S1上,并且执行了更新操作,那么ZXID将会+1,比如ZXID=2。 当客户端尝试重连到S2时,若S2由于延迟等,导致上面的ZXID 依旧为1的话,客户端将重试连接到S3(ZXID>2)。

ZK 实现Quorums

./zkServer.sh start CONFIG_FILE
CONFIG_FILE中设置启动的端口和名称等,以及其它的相关server。

    tickTime=2000    
    initLimit=10    
    syncLimit=5    
    dataDir=./data    
    clientPort=2181    
    server.1=127.0.0.1:2222:2223    
    server.2=127.0.0.1:3333:3334    
    server.3=127.0.0.1:4444:4445    

实现Lock

客户端通过创建ephemeral znode /lock ,只有一个客户端P会成功,则这个P获取锁成功。 其它客户端失败,它可以通过watch /lock,等删除时继续尝试获得锁。

实现master-worker

  • master和worker
    create -e /master “”
    创建ephemeral 的 master和worker的节点,当断掉后,该节点自动消失。
  • client
    create -s /assign/task- “” 创建id自增的任务节点
    stat PATH可以查看节点状态
    get PATH查看节点状态和数据