分布式协调服务之 Zookeeper介绍
Zookeeper是apache 开源项目,官方站点
Zookeeper介绍
ZooKeeper is a high-performance coordination service for distributed applications. It exposes common services - such as naming, configuration management, synchronization, and group services。
如果有过分布式程序开发经验的会更容易理解它,简单说它用来维护分布式应用的配置信息,提供分布式同步的服务,还可以提供统一命名服务、群组服务。例如分布式应用中不可避免要发生配置的变更,怎么同步到每个机器并确保一致性,其实这是一个棘手的工作。Zookeeper就可以干这个。
Zookeeper的汉语意思是动物管理员,分布式应用这些比如Hadoop、Hbase的Logo都是动物,Zookeeper扮演的角色也就顾名思义了,把他们管理协调起来。包括用过Kafka消息服务,也要依赖Zookeeper提供集群的配置信息(甚至老版本中消费者的offset也存储在Zookeeper)。
Zookeeper部署依赖jdk环境。
Zookeeper特点
一个Leader,多个Follower组成的集群。集群中要求至少有一半以上的节点存活,就可以work。一般是奇数个节点,因此集群部署通常至少需要3台机器。集群的选举机制是半数机制,达到一半以上的确认就是Leader。
全局数据一致,每个server保存一份相同的副本,client连哪个server数据都一样。
数据更新原子性,要么成功,要么失败。
适合场景举例
Zookeeper设计本身是为了分布式服务的协调数据,并非是设计一个数据库或者大对象的存储。通常是数据较小的配置信息、状态信息等,以kb为单位的。如果非要存储较大数据,可以存储在大容量的存储系统中,然后Zookeeper存这个数据指针(主键)。
配置管理的应用
比如集群下各机器同步配置信息的场景,希望配置变更快速反映到所有机器上。
可以把配置放到Zookeeper的Znode上,这些机器作为客户端watch这个节点,发生变更时,Zookeeper同步。
数据存储结构
类似于Unix的文件系统,类似一个层次的树,每个节点是ZNode,每个ZNode通过路径唯一标识。这里没有.和..这种相对路径的概念,比如/a/b/./c 这种是无效的。
每个Znode维护统计信息,比如版本号、时间戳等。每有数据或者ACL(Access Control List)的变更,版本号都要+1。
介绍统计结构前,先说下Zxid的概念,Zxid (ZooKeeper Transaction Id):机器节点下全局的顺序,每次变动都有一个唯一的zxid。比如zxid1小于zxid2,那意味着zxid2的事件发生的更晚。
了解下统计结构(Stat Structure)的组成:
field | 描述 |
---|---|
czxid | 创建这个znode的zxid |
mzxid | 上次修改znode的zxid |
pzxid | 上次修改该znode的孩子的zxid |
ctime | 创建该znode的时间戳 |
mtime | 修改该znode的时间戳 |
version | 该znode data变化的版本号 |
cversion | 该znode孩子变化的版本号,创建、删除 |
aversion | 该znode ACL变化的版本号 |
ephemeralOwner | 短暂节点下的会话id,非短暂是0 |
dataLength | 数据长度 |
numChildren | 孩子个数 |
安装部署Zookeeper
虽是分布式协调服务,Zookeeper通常工作在多机部署的集群环境,不过学习使用也可以单机部署。
一. 安装JDK
二. 解压tar压缩包到安装目录 如version3.4.14
三. 修改配置文件 conf目录下 .cfg
# mv zoo_sample.cfg zoo.cfg
# vi zoo.cfg
设置下 dataDir目录 默认 dataDir=/tmp/zookeeper
配置文件下几个配置:
# 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
dataDir=/home/work/zookeeper/zookeeper-3.4.14/zkdata
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
在集群环境的安装过程中,需要给每个机器分配一个唯一编号。在zoo.cfg配置文件的dataDir参数目录下创建一个 myid文件,把编号写进去。 并且在zoo.cfg配置文件中,把集群信息写进去:
server.myid=ip:port1:port2
server.myid1=ip1:port1:port2
server.myid2=ip2:port1:port2
server.myid3=ip3:port1:port2
1). myid:每个机器的编号;
2). ip:每个机器的ip;
3). port1:是Leader和Follower数据同步的服务端口;
4). port2:是机器节点之间进行选举的服务端口;
四. 运行
启动/停止服务
启动
# bin/zkServer.sh start
停止
# bin/zkServer.sh stop
查看状态
查看运行状态
# bin/zkServer.sh status
Mode: standalone 单机服务
客户端连接
# bin/zkCli.sh
成功提示: 执行 ls / (和Unix文件系统类似)
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
客户端操作命令
Zookeeper 可以简单认为是个类似文件系统+有通知机制的组件。
进入客户端连接以后,执行help命令,即可了解各个命令使用。如:
[zk: localhost: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
创建节点 create [-s] [-e] path data acl
-s表示顺序节点(Zookeeper会保证创建顺序,znode名字会有序号);
如 # create -s /a 1
产生 /a0000000006 、 /a0000000007等节点
-e是临时节点(session断开会清除该znode) 默认是永久节点;
利用Zookeeper的临时顺序节点,可以实现分布式锁。
设置节点 set path data [version]
如果指定version参数,需要和当前版本号匹配上,否则无效。
删除没孩子的节点 delete path
递归删除 rmr path
查看节点下的子节点 ls path [watch]
指定watch 当节点目录发生变更(创建、删除节点)时,会得到通知。
查看节点信息 get path [watch]
指定watch 当节点发生变更时,会得到通知。
Zookeeper Watch 监听
Zookeeper的读操作,getData(), getChildren(), exists(),都有可选项是否监听。数据有变动的话,监听事件会告诉客户端,并且是触发一次(第二次变动则不会再触发监听,除非再设置监听选项)。
ls path [watch]
如:
session A:
#ls / true
session B:
#create /node1 666
此时session A:
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/
-- 只有事件的通知,不会显示具体数据是什么
get path [watch]
如:
session A:
#create /test 1
#get /test true
session B:
set /test 2
此时session A:
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/test
watch监听是一次性的,如果需要再监听,需要再次watch。监听只会得到事件的通知,不会告诉变更后的具体数据是什么。
Zookeeper主从同步数据一致性
Zookeeper一致性协议采用的ZAB协议。 数据提交过程: Leader广播给所有Follower;
Follower收到请求,写到日志成功后,返回Leader ACK消息;
Leader接到半数以上的ACK消息后,返回成功给客户端,广播Commit;
Follower再提交。