应用场景
分布式环境下高可靠的协调系统
hdfs HA / YARN ResourceManager / HBase / Dubbo
特点
- 最终一致性:为所有客户端展示同一视图
- 可靠性:如果一条消息被一台服务器接受,那么它将被所有服务器接受。
- 实时性:ZK不能保证两个客户端同时得到刚刚更新的数据,如果需要读最新数据,那么需要在读之前调用sync()
- 等待无关(wait-freee):慢的或者失效的client不干预快速的client的请求
- 原子性:更新要么成功,要么失败,没有中间状态
- 顺序性:对于所有Server,同一消息
原理
- paxos协议 [peikses]
- 集群启动时选举leader
- 更新成功的原则:当超过半数的server(无论是否alive)更新成功后,则认为此更新成功。
角色
- leader:投票的发起和决议。接收请求,广播任务,
- follower:
- 接收client请求,转发给server, 处理server分配的任务,返回处理结果给。
- 参与投票。
- observer:
- 接受client的请求并转发给leader;
- 同步leader的状态;
- 不参与投票,降低了投票过程的延迟;
数据模型
- 层次化目录结构,符合常规文件系统命名规范
- 每个目录节点称为znode,有个唯一的路径标识
- znode包含数据data 和 子节点children 属性
- znode中的数据可以有多个版本
- znode不支持部分读写,必须是一次完整的读写
- client可以在znode上设置监视器watcher
- 两种节点,节点类型创建时确定,创建后不能更改
- ephemeral(短暂的): 临时节点,创建此节点的client与server的连接(connection)一旦断开,则节点消失。
- persistent(持久的):持久节点
- 四种形式:Persistent、Persistent_Sequential、Ephemeral、
Ephemeral_Sequential
应用
统一命名服务
{
"nodename":"imageServer",
"data":" 存放图片的服务器",
"children":[
{
"nodename":"imgServer1",
"data":'{
"hostname" : "img1",
"ip" : "192.168.1.120",
"cpu_count" : "1",
"RAM" : "5T"
}',
"children":[]
},
{
"nodename":"imgServer2",
"data":'{
"hostname" : "img2",
"ip" : "192.168.1.121",
"cpu_count" : "1",
"RAM" : "6T"
}',
"children":[]
}
]
}
配置文件管理和同步
- 例如在hadoop集群中,所有节点的hdfs-site.xml,core-site.xml等都必须是完全相同的,当某个配置项需要更改时,需要对所有及节点同步更新。
只需在ZK中对相应的配置文件,建立持久节点hadoop_conf_node,hadoop集群的所有节点都在此节点上加Watcher,一旦此数据有更新,则从此节点中拉取最新配置信息,更新本地信息。
分布式通知与协调
zk可以实现心跳监测机制、实现信息推送,相当于一个发布/订阅系统
分布式锁
利用zookeeper的以下三个特性实现,分布式锁:
- 强一致性
- 锁独占性
- 控制锁时序
伪码: - 多个client同时请求创建路径为 /rootnode/distribute_lock_node 的临时节点时,只会有一个client成功,那么就认为此client获得了锁,并且独占了锁。
- 只有占有锁的client主动删除了节点后,表示他释放了锁。其它client才能再次去创建相同名称的节点,谁创建成功,谁就占有了锁。
- 利用Sequential形式的节点,按照自动生成的序列,控制锁时序
zk集群搭建
- 节点规划
5台服务器:zk1,zk2,zk3,zk4,zk5;
前三台参与选举,后两台作为observer - 安装jdk
- 在zk1上解压缩zk
tar -xzvf zookeeper.xxx.tar.gz
- 创建zk数据文件夹
mkdir -p /home/hadoop/appdata/zookeeper/dataDir
mkdir -p /home/hadoop/appdata/zookeeper/dataLogDir
-
设置myid
创建并编辑myid文件,设置每台zookeeper的id编号
vi /home/hadoop/appdata/zookeeper/dataDir/myid -
编辑配置文件
cp zookeeper/conf/zoo_sample.cfg zookeeper/conf/zoo.cfg
vi zookeeper/conf/zoo.cfg
tickTime=2000 #leader与follower之间心跳间隔为2s
initLimit=10
syncLimit=5
clientPort=2181 #对外(对客户端)提供服务的端口号
dataDir=/home/hadoop/appdata/zookeeper/dataDir
dataLogDir=/home/hadoop/appdata/zookeeper/dataLogDir
peerType=observer #仅在zk4、zk5的配置文件中出现
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:3888
server.4=zk4:2888:3888:observer
server.5=zk5:2888:3888:observer
发送配置好的安装文件到其它几台机器上
scp -r zk2:/home/hadoop/app
scp -r zk3:/home/hadoop/app
scp -r zk4:/home/hadoop/app
scp -r zk5:/home/hadoop/app
脚本启动所有server
vi /home/hadoop/freUse/start-zk.sh #创建脚本文件并保存
chmod 755 /home/hadoop/freUse/start-zk.sh #设置权限为可执行
#!/bin/bash
echo "-----------start zk1 zookeeper--------------------"
ssh zk1 zkServer.sh start
echo $?
echo "-----------start zk2 zookeeper--------------------"
ssh zk2 zkServer.sh start
echo $?
...
echo "-----------zk1 status --------------------"
info=`ssh zk1 zkServer.sh status`
echo ${info}
echo "-----------zk2 status --------------------"
info=`ssh zk2 zkServer.sh status`
echo ${info}
...
执行启动脚本,
执行jps
命令查看是否有了QuorumPeerMain进程
执行zkCli.sh
,进入zk客户端命令行
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