目录

  1. 安装配置
  2. Paxos简介
  3. ZooKeeper的基本原理
  4. ZooKeeper的基本概念
  5. ZooKeeper的客户端API
  6. ZooKeeper的应用
  7. 附录:

ZooKeeper的安装配置

准备工作:

接下来,安装一个ZooKeeper 3.4.9伪集群:

tar zxvf zookeeper-3.4.9.tar.gz 
for i in `seq 1 4`; do cp -r zookeeper-3.4.9 zookeeper-3.4.9-$i; done
for i in `seq 1 4`; do cp zookeeper-3.4.9-$i/conf/zoo_sample.cfg zookeeper-3.4.9-$i/conf/zoo.cfg ; done
for i in `seq 1 4` ; do mkdir zkdata-$i; mkdir zkdatalog-$i; echo $i >zkdata-$i/myid; done
for i in `seq 1 4`; do sed -i "s/^clientPort=[0-9]\{1,\}/clientPort=218$i/g" zookeeper-3.4.9-$i/conf/zoo.cfg; sed -i "s/^dataDir=.*/dataDir=zkdata-$i\//g" zookeeper-3.4.9-$i/conf/zoo.cfg ; done

for i in `seq 1 4` ; do echo "dataLogDir=zkdatalog-$i/" >>zookeeper-3.4.9-$i/conf/zoo.cfg; for i_ in `seq 1 4`; do echo "server.$i_=0.0.0.0:188$i_:288$i_" >>zookeeper-3.4.9-$i/conf/zoo.cfg; done ; done  
for i in `seq 1 4` ; do sed -i "s/^server.4=\(.*\):\([0-9]\{1,\}\):\([0-9]\{1,\}\)$/server.4=\1:\2:\3:observer/g" zookeeper-3.4.9-$i/conf/zoo.cfg ; done
for i in `seq 1 4`; do zookeeper-3.4.9-$i/bin/zkServer.sh start ; done
$ for i in `seq 1 4`
> do
> zookeeper-3.4.9-$i/bin/zkServer.sh status
> done
ZooKeeper JMX enabled by default
Using config: C:\cygwin64\home\zhoujingjiang\zookeeper-3.4.9-1\conf\zoo.cfg
Mode: follower
ZooKeeper JMX enabled by default
Using config: C:\cygwin64\home\zhoujingjiang\zookeeper-3.4.9-2\conf\zoo.cfg
Mode: leader
ZooKeeper JMX enabled by default
Using config: C:\cygwin64\home\zhoujingjiang\zookeeper-3.4.9-3\conf\zoo.cfg
Mode: follower
ZooKeeper JMX enabled by default
Using config: C:\cygwin64\home\zhoujingjiang\zookeeper-3.4.9-4\conf\zoo.cfg
Mode: observer  

Paxos简介

ZooKeeper在恢复模式下,选举leader使用的就是Paxos算法,因此先简单介绍Paxos算法。
分布式一致性算法解决的问题是:分布式系统如何就一个值达成一致。在Paxos算法中,多个节点之间同一个值达成一致的过程叫Paxos instance。
在Basic Paxos算法中,主要有两类角色:

paxos.png
图1-Basic Paxos

如上图所示,Paxos算法分为两个阶段:

上述流程可知,并发情况下,Paxos存在着活锁问题:

livelock.png
图2-活锁
  1. S1作为提议者,发起prepare(3.1),并在S1,S2和S3达成多数派;
  2. 随后S5作为提议者,发起了prepare(3.5),并在S3,S4和S5达成多数派;
  3. S1发起accept(3.1, value1),由于S3上提议 3.5>3.1,导致accept请求无法达成多数派,S1尝试重新生成提议;
  4. S1发起prepare(4.1),并在S1,S2和S3达成多数派;
  5. S5发起accpet(3.5, value5),由于S3上提议4.1>3.5,导致accept请求无法达成多数派,S5尝试重新生成提议;
  6. S5发起prepare(5.5),并在S3,S4和S5达成多数派,导致后续的S1发起的accept(4.1, value1)失败; ......

Paxos算法的一个特点是:每个Proposer都可以提出一个value,但是Proposer并不会“坚持”自己的value,而是通过Prepare阶段,去“学习”其他的Proposer提出的value(图1中的第4步),最终才能达成一致。


ZooKeeper的基本原理

ZooKeeper中的角色主要有以下三类:

角色描述
leader负责发起提议,更新系统状态
follower接受客户端请求,并向客户端返回结果(在收到写请求时会forward给leader)。选举过程中参与投票
observer与follower类似,但是在选举过程中不参与投票,只同步leader的状态。observer的存在是为了扩展系统,提高读取速度
client请求的发起者

系统模型如下所示:

xitongmoxing.jpg
图3-ZK系统模型


ZooKeeper的特性:


ZooKeeper的基本概念

shujumoxing.jpg
图4-ZK的数据模型


下面看一下ZNode的属性:

[zk: localhost:2181(CONNECTED) 19] get /

cZxid = 0x0
ctime = Thu Jan 01 00:00:00 UTC 1970
mZxid = 0x0
mtime = Thu Jan 01 00:00:00 UTC 1970
pZxid = 0xb0000000d
cversion = 11
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 3

下面以数据版本号为例,说明版本号的作用。假设实现一个AtomicInteger,该数据类型提供了原子的incr <number>操作。那么ZK client的做操可能是这样的:

如果在set时,不校验版本号,那么就可能导致其它的客户端的更新丢失。

接下来看,ZooKeeper的watch特性
ZooKeeper支持watch操作,client可以在ZNode上设置一个watcher(比如:get /a/znode watch),当该ZNode上发生相应的变化时,就会触发watcher,把发生的事件通知给设置watcher的client。需要注意的是:watcher是一次性的,也就是说触发一次之后,就会被取消,如果想要继续watch,需要client重新设置watcher。


ZooKeeper的客户端API

使用命令行客户端,连接到ZK:

/path/to/zookeeper_install_directory/bin/zkCli.sh -server your_host:your_port  

输入help,可以查看ZK支持的命令:

[zk: 192.168.30.3:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
        stat path [watch]
        set path data [version]
        ls path [watch]
        delquota [-n|-b] path
        ls2 path [watch]
        setAcl path acl
        setquota -n|-b val path
        history
        redo cmdno
        printwatches on|off
        delete path [version]
        sync path
        listquota path
        rmr path
        get path [watch]
        create [-s] [-e] path data acl
        addauth scheme auth
        quit
        getAcl path
        close
        connect host:port

ZooKeeper的应用

接下来的应用场景的实例直接使用curator自带的实现,curator是目前最流行的ZooKeeper Java客户端上面的demo也建议使用curator自带的实现,博主之所以自己实现,是为了说明其原理


两阶段提交 和 Zab协议

两阶段提交用来保证分布式事务的原子性,两阶段提交中的角色分为:协调者(1个)和参与者(多个),其过程如下:

  1. 协调者记录Prepare T日志,并向所有的参与者发送Prepare T消息
  2. 协调者收集所有参与者返回的意见,此时存在三种情况:

ZooKeeper Atomic Broadcast(简称ZAB,zookeeper原子消息广播协议)是ZooKeeper保证数据一致性的核心算法。它分为两种模式:

Zab的崩溃恢复需要保证以下两种情况(其他情况不做保证?):

leader-commit.jpg
server1是Leader,C2是在Leader上完成事务提交,但通知Follower服务器要Commit时挂掉,保证C2在Server2和Server3上提交
leader-prepare.jpg
假设初始的Leader服务器Server1在提出一个事务Proposal3(P3)之后,还没有给Follower发送请求,希望得到ack之前,挂了。则要丢弃P3事务


Zab选举算法的要求:


参考文档