分布式应用协同服务:ZooKeeper
ZooKeeper是Apache Hadoop的一个子项目,其实现的功能与Google的Chubby基本一致,主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。  
  
  数据模型:</span> 
  zookeeper维护一个层次关系的数据结构,其非常类似于一个标准的文件系统,如下: 
  
  znode具有如下特点: 
  1. ZooKeeper有临时节点的概念。临时节点在创建它的会话活动期间存在。会话终止的时候,临时节点被删除,所以临时节点不能有子节点。 
  2. Znode可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端。 
  3. Znode可以保留数据,但是,其不是设计用来作为通用数据库或者大型对象存储的,而是用来存储协调数据的。协调数据的形式可能是配置、状态信息、聚合等 等。各种形式的协调数据的一个共同特点是:它们通常比较小,以千字节来衡量。ZooKeeper客户端和服务器实现会进行检查,以保证znode数据小于 1MB 
  4.Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。 
  
  ZooKeeper中的时间: 
  zxid : 每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid。 
  版本号 : 对节点的每次修改将使得节点的版本号增加一。版本号有三种:version(znode数据修改的次数)、cversion(znode子节点修改的次数),以及aversion(znode的ACL修改次数)。 
  tick : 多服务器ZooKeeper中,服务器使用tick来定义状态上传、会话超时、节点间连接超时等事件的时序。tick仅被最小会话超时(2倍的tick时间)间接使用:如果客户端要求小于最小会话超时的时间,服务器将告知客户端,实际使用的是最小会话超时。 
  
  znode会维护一个包含数据修改和ACL修改版本号的 Stat结构体 , 这个结构体还包含时间戳字段。版本号和时间戳让ZooKeeper可以校验缓存,协调更新。每次修改znode数据的时候,版本号会增加。客户端获取数据 的同时,也会取得数据的版本号。执行更新或者删除操作时,客户端必须提供版本号。如果提供的版本号与数据的实际版本不匹配,则更新操作失败。stat结构 体内容: 
  czxid : The zxid of the change that caused this znode to be created. 
  mzxid : The zxid of the change that last modified this znode. 
  ctime : The time in milliseconds from epoch when this znode was created. 
  mtime : The time in milliseconds from epoch when this znode was last modified. 
  version : The number of changes to the data of this znode. 
  cversion : The number of changes to the children of this znode. 
  aversion : The number of changes to the ACL of this znode 
  ephemeralOwner : The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero. 
  dataLength : The length of the data field of this znode. 
  numChildren : The number of children of this znode. 
  
  安装使用
  下载解压:</span> 
  $ wget http://mirror.bit.edu.cn/apache//zookeeper/zookeeper-3.4.3/zookeeper-3.4.3.tar.gz . 
  $ tar -zxvf zookeeper-3.4.3.tar.gz 
  
  修改配置: 
  $ cp zookeeper-3.4.3/conf/zoo_sample.cfg zookeeper-3.4.3/conf/zoo.cfg 
  $ cat  zookeeper-3.4.3/conf/zoo.cfg 
  
  # The number of milliseconds of each tick 
  tickTime=2000 
  # The number of ticks that the initial 
  # synchronization phase can take 
  initLimit=10 
  # The number of ticks that can pass between 
  # sending a request and getting an acknowledgement 
  syncLimit=5 
  # the directory where the snapshot is stored. 
  # do not use /tmp for storage, /tmp here is just 
  # example sakes. 
  dataDir=/tmp/zookeeper 
  # the port at which the clients will connect 
  clientPort=2181 
  # 
  # Be sure to read the maintenance section of the 
  # administrator guide before turning on autopurge. 
  # 
  # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance 
  # 
  # The number of snapshots to retain in dataDir 
  #autopurge.snapRetainCount=3 
  # Purge task interval in hours 
  # Set to "0" to disable auto purge feature 
  #autopurge.purgeInterval=1 
  
  
  启动zookeeper: 
  ZooKeeper 要求 JAVA 的环境才能运行,并且需要 JAVA6 以上的版本 
  ubuntu下安装jdk: 
  $sudo apt-get install  openjdk-7-jre-headless 
  启动zookeeper: 
  $ sudo sh zookeeper-3.4.3/bin/zkServer.sh start 
  JMX enabled by default 
  Using config: /home/zxm/zookeeper-3.4.3/bin/../conf/zoo.cfg 
  Starting zookeeper ... STARTED 
  查看相应端口: 
  $ netstat -na | grep 2181 
  tcp6       0      0 :::2181                 :::*                    LISTEN 
  
  客户端连接测试: 
  $ sh zookeeper-3.4.3/bin/zkCli.sh -server 127.0.0.1:2181 
  ....... 
  输入help 
  [zk: 127.0.0.1:2181(CONNECTED) 0] help 
  ZooKeeper -server host:port cmd args 
      connect host:port 
      get path [watch] 
      ls path [watch] 
      set path data [version] 
      rmr path 
      delquota [-n|-b] path 
      quit 
      printwatches on|off 
      create [-s] [-e] path data acl 
      stat path [watch] 
      close 
      ls2 path [watch] 
      history 
      listquota path 
      setAcl path acl 
      getAcl path 
      sync path 
      redo cmdno 
      addauth scheme auth 
      delete path [version] 
      setquota -n|-b val path 
  
  我们可以尝试做一些操作: 
  [zk: 127.0.0.1:2181(CONNECTED) 4] ls / 
  [zookeeper] 
  [zk: 127.0.0.1:2181(CONNECTED) 5] create /test1 99 
  Created /test1 
  [zk: 127.0.0.1:2181(CONNECTED) 6] get /test1 
  99 
  cZxid = 0xa 
  ctime = Thu Apr 19 02:08:37 PDT 2012 
  mZxid = 0xa 
  mtime = Thu Apr 19 02:08:37 PDT 2012 
  pZxid = 0xa 
  cversion = 0 
  dataVersion = 0 
  aclVersion = 0 
  ephemeralOwner = 0x0 
  dataLength = 2 
  numChildren = 0 
  [zk: 127.0.0.1:2181(CONNECTED) 7] create /test1/mytest 1000 
  Created /test1/mytest 
  [zk: 127.0.0.1:2181(CONNECTED) 8] get /test1/mytest 
  1000 
  cZxid = 0xb 
  ctime = Thu Apr 19 02:08:54 PDT 2012 
  mZxid = 0xb 
  mtime = Thu Apr 19 02:08:54 PDT 2012 
  pZxid = 0xb 
  cversion = 0 
  dataVersion = 0 
  aclVersion = 0 
  ephemeralOwner = 0x0 
  dataLength = 4 
  numChildren = 0 
  
  编译使用C客户端: 
  $ cd zookeeper-3.4.3/src/c 
  $ mkdir prefix 
  $ ./configure --prefix=/home/zxm/zookeeper-3.4.3/src/c/prefix 
  $ make 
  $ ./cli_mt 127.0.0.1:2181 
  Watcher -1 state = CONNECTED_STATE 
  Got a new session id: 0x136c9d62bdc0004 
  ls / 
  time = 4 msec 
  /: rc = 0 
      test1 
      zookeeper 
  time = 7 msec 
  get /test1 
  time = 2438 msec 
  /test1: rc = 0 
   value_len = 2 
  99 
  Stat: 
      ctime = Thu Apr 19 02:08:37 2012 
      czxid=a 
      mtime=Thu Apr 19 02:08:37 2012 
      mzxid=a 
      version=0    aversion=0 
      ephemeralOwner = 0