13.7.16

ZK教程 -- 笔记


本文是上面的在线文档的一些阅读笔记。和其他所有笔记一样,本文的目的不是分享,而是给我自己以后重温相关信息时看的。

ZooKeeper是什么?

  • ZooKeeper is a distributed co-ordination service to manage large set of hosts
这里包含了几点:
  • 分布式环境
  • 用于协调
  • 是一种服务
  • 大量主机
分布式环境以及一种服务这两点很好理解,但大量主机和协调服务这两个让我有点“逆反”的考虑:如果不是大量主机,或者不是用于协调服务,会不会和ZooKeeper的设计初衷不相符而带来问题?

我们来看目前ZooKeeper的实际应用。

ZooKeeper的实际应用项目


首先看看Apache项目:
  • Apache Accumulo
  • Apache BookKeeper
  • Apache CXF DOSGi
  • Apache Flume (planning)
  • Apache Hadoop MapReduce2 /YARN
  • Apache HBase
  • Apache Hedwig
  • Apache Kafka
  • Apache S4 (incubating)
  • Apache Solr
Free Software Projects
  • AdroitLogic UltraESB
  • Akka
  • Eclipse Communication Framework
  • Eclipse Gyrex
  • GoldenOrb
  • Juju
  • Katta
  • KeptCollections
  • Mesos
  • Neo4j
  • Norbert
  • Talend ESB
  • redis_failover

ZooKeeper的用应场景

  • Naming service
  • Configuration management
  • Synchronization
  • Leader election
  • Message Queue
  • Notification system

了解exists()函数

这个是我自己的个人笔记。

四个exists()函数

  • exists(String path, boolean watch)
  • exists(String path, boolean watch, AsyncCallback.StateCallback cb, Object ctx)
  • exists(String path, Watcher watcher)
  • exists(String path, Watcher watcher, AsyncCallback.StateCallback cb, Object ctx)
基本上这四个函数可以分为:
是否采用缺省监控器是否带异步回调

理解缺省监控器

要进一步理解整个编程模型,就需要先理解什么是缺省监控器。一个ZooKeeper Session会带有一个缺省监控器,这个监控器有两种设置的方法
  • 随构函数设置
  • 使用注册函数设置

缺省监控器的调用

可以看出,exists()方法在watch设定为true时,将会调用缺省监控器。从这个角度来说,除非有很必要的原因,我觉得这种相对“方便”的方法还是少用为妙,尤其是在现在lambda表达式这么方便的时候。

理解回调


从上面的代码来看并没有看到太多关于callback回调的实现,只知道它被放入到一个队列里进行处理。更深入的代码实现先不要花时间去看,可以从另一个角度来查看相关的信息。

回调函数的函数签名



ZooKeeper的会话与会话事件

ZooKeeper会话在ZooKeeper程序员指南中有篇幅比较大的介绍。而之前我自己对于ZK的相关了解关不多,可以趁这次的开发机会,深入了解一下。

什么是ZK会话

  • A ZooKeeper client establishes a session with the ZooKeeper service by creating a handle to the service using a language binding.
  • Once created, the handle starts of in the CONNECTING state and the client library tries to connect to one of the servers that make up the ZooKeeper service at which point it switches to the CONNECTED state.
  • During normal operation will be in one of these two states.
  • If an unrecoverable error occurs, such as session expiration or authentication failure, or if the application explicitly closes the handle, the handle will move to the CLOSED state.

12.7.16

ZK的一些简单的笔记(3.4.8)

前言

断断续续的对 zookeeper 浅尝即止。每次重新拿起来又要重新过一遍之前学过的东西,真是苦不堪言。希望这次能做一些笔记,帮助下一次重新拾起时快速重温吧。

ZK的语义特性

不知道应不应该说是“语义特性”,姑且这样记下来。
  • 类文件路径的数据模型
  • 监察器
  • 一致性保证
上面三样在这次重温时多少还有点印象。但下面这个就没有多少印象了。有可能前一次就没有认真看,或没有看懂:
  • ZK会话

一个简单的ZK编程模型

ZK提供了四种recipes。但如果从最基本的语义,或分布式操作原语的角度来看,ZK有一个最基本的编程模型:异步消息驱动的树型结构的数据库。

理论上说ZK可以用轮询的方式进行编程,但显然,在一个有实际意义的系统中,单纯的论询是很有限制的。整个ZK编程模型,基本上是建立在异步消息驱动上。

监控的位置(三个读操作)

ZooKeeper Programmer's Guide文档的ZooKeeper Watches一节中开宗明义地指出了三种(也就是所有的)读操作,都可以设定监控,或事件驱动接口。
  • getData()
  • getChildren()
  • exists()
我觉得更合适的说法应该是注册事件驱动器。具体的信息可以查看相关的API文档:ZooKeeper (ZooKeeper 3.4.6 API)

读操作以外:连接监控

我觉得还需要记得的一点是连接监控器。如果一直活跃地进行ZK的开发,当然知道这个,但象我断断续续地做这个,就很容易忘了。为了实现一个简单的zk连接测试,我以前还做过这个笔记。


定义中的三个重要组成部分

在程序员指南中重点指出了ZK监控的三个重要语义:
  • 单触发(One-time trigger)
  • 撩客户(Sent to the client)
  • 仅数据(The data for which the watch was set)
这个是基于ZK监控定义提炼出来的语义特点:A watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。

单触发

这个是很重要的语义,就是一次注册只会触发一次,而GUI等事件驱动编程模型中都不是单触发的。为什么要这样设计?

撩客户

从ZK watch event的英文定义看,这一点很容易理解:一个监控事件最后是发向注册事件的那个客户端。然而在文档的解释里就有一些不太好理解的东西,我先记录下来:


  • This implies that an event is on the way to the client, but may not reach the client before the successful return code to the change operation reaches the client that initiated the change.
  • Watches are sent asynchronously to the watchers. 
  • ZooKeeper provides an ordering guarantee: a client will never see a change for which it has set a watch until it first sees the watch event.
  • Network delays or other factors may cause different clients to see watches and return codes from updates at different times. 
  • The key point is that everything seen by the different clients will have a consistent order.
第一,二句很好理解:更新数据的客户端和监控数据的客户端在数据更新和更新消息上是异步的。既然是异步的,就会存在先后问题。有可能更新数据的客户端已经收到服务器的返回代码表示数据已经更新,而监听更新的客户端并没有收到更新通知。这个要求我们在编写程序的时候不要假设接收端已经收到消息 —— 对于有MQ编程经验的人来说,这个很好理解。
第三句我暂时理解为:不要期望你可以通过轮询能更快获得最新数据,事实上最快获得更新数据的只有监控器。
第四句和第一,二句并没有太大区别。
第五句我有点怀疑是说:不同客户之间有时间差,但同一客户自己是确保次序的。

仅数据

这个地方其实是解释了“数据”是什么的问题。原文提出两种思考方法,一是把数据和children list分开,另一咱是干脆把children list也看成是数据的一种。

监控器的维护

  • “Watches are maintained locally at the ZooKeeper server to which the client is connected.”这个需要结合整个ZK的分布式架构来理解。监控器必须有人(server)来维护。按这句话的意思,监控器只在单个服务器上维护(不知道会不会有单点问题)。
  • When a client connects to a new server, the watch will be triggered for any session events.

消息类型