zookeeper是分布式的/开源的分布式应用程序协调服务;数据和redis一样,都是保存在内存中的,日日志文件存放在磁盘中,功能非常强大,一般会以集群的方式使用;
zookeeper 的数据存储类似于文件系统,是目录树的结构,为了保障 快 的优势,每个node节点的数据最大为1MB。
安装
- 前提:zookeeper是基于java的,需要预先安装jdk,linux中安装jdk的步骤(安装包下载,这里用的是jdk1.8):
1.tar -zxvf jdk-8u251-linux-i586.tar.gz -C /home/soft #解压
2.vim /etc/profile #配置环境变量
export JAVA_HOME=/home/soft/jdk1.8.0_251
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
3.source /etc/profile #执行profile
4.sudo yum install glibc.i686 #解决版本不匹配问题
5.java -version #验证安装成功
- 安装:安装过程如下:
1.wget xxxxx #下载安装包
2.tar xf zookeeper.*tar.gz #解压
3.mkdir /opt/soft #创建安装目录
5.mv zookeeper /opt/soft #将解压后的文件移动到创建好的安装目录中
6.vi /etc/profile #配置环境变量
export ZOOKEEPER_HOME=/opt/mashibing/zookeeper-3.4.6
export PATH=$PATH:$ZOOKEEPER_HOME/bin
7.cd zookeeper/conf #查看配置文件
8.cp zoo.zem*.cfg zoo.cfg #备份配置文件,若改动出问题了,方便还原
9 ci zoo.cfg #修改被指文件
dataDir= #指定数据存放目录
server.1=node01:2888:3888 #创建集群时配置
server.2=node02:2888:3888
server.3=node01:2888:3888
server.4=node01:2888:3888
10.mkdir -p /var/temp/zk #创建存放数据的目录
11.echo 1 > /var/mashibing/zk/myid #创建并指定myid
12.cd /opt && scp -r ./mashibing/ node02:·pwd· #搭建集群时,直接把文件复制到其他机器上
#搭建集群时需要先配置ip互通
#vi /etc/hosts
#192.168.125.60 node01
#192.168.125.61 node02
13.node02~node04 创建myid #集群创建myid文件
14.1,2,3,4启动 #集群分别启动
15.zkServer.sh start-foreground #前台打印日志方式启动,默认是后台启动
#验证:
zkCli.sh #客户端启动
help
ls/
create /ooxx ""
create -s /abc/aaa
create -e /ooxx/xxoo
create -s -e /ooxx/xoxo
get /ooxx
netstat -natp | egrep '(2888|3888)' #2888为lerder接收write请求的端口,3888是选主投票用的
保障
- zookeeper保障顺序一致性,通过集群模型/主从模型,保障client的更新操作是按照发送指令的顺序先后执行的。
- zookeeper保障了原子性,所有的更新操作会实现最终一致性,只有操作成功和操作失败两种状态,不会出现部分成功部分失败的中间状态。
- zookeeper的client无论连接任何一台server,看到的视图都是相同的,保障了统一视图。
- zookeeper是的数据是基于内存的,保障了数据的可靠性和持久性。
- zookeeper的数据在特定的时间范围内是最新的,flower会同步leader,保障了数据的及时性。
特性
- 扩展性
可以通过部署更多的机器来实现zk的更多性能,并通过角色的区分实现读写分离。
zk的server角色分为以下三种:
- leader 负责数据的写入。
- flower 负责数据的读取,还有leader的选举,flower决定选举的效率。
- observer 只负责数据的查询,不参与选举,尽可能地放大查询能力。在配置中添加
server.4=node01:2888:3888:observer
即可注册为observer。
- 可靠性
- 故障恢复快,leader发生故障之后,flower可快速选举新leader,继续对外提供服务,选举的时间大约是200ms。
- 数据一致性,在分布式应用中,zookeeper是通过ZAB协议来实现数据一致性的,ZAB协议是基于paxos算法的,是paxos的简化版。
ZAB协议的选举过程:
第一阶段是数据恢复阶段,每台server在启动的时候,都会从本地数据中找到自己拥有的最大事务id,称zxid。
第二阶段是选举阶段,每台server都会推荐自己做leader,并提交选票,选票中包括自己的zxid(最大事务id)和myid(自己的选举id),逻辑时钟值(确保server在一轮选举中),当前状态(Looking/follower/leader/observer)。
第三阶段是比较阶段,先比较zxid,zxid最大的胜出,若zxid相等,比较myid,myid最大的胜出。
ZAB协议的特征
第一,原子性,只有失败成功两个状态,没有中间状态
第二,广播性,遵循过半原则
第三,顺序队列,有leader自身维护
选举和操作的过程中都需要遵循过半原则,选举时,一个节点胜出过半才能成为leader,服务时,只有集群中存活的节点超过一半,才能对外提供服务;操作时,只有超过一半通过,才能提交请求。
- 数据同步,flower可以选择性地同步数据,若未执行同步操作,某一时间点取到的数据可能不是最新的。
使用
zookeeper是二进制安全的,存放的是字节流,需要在外界指定编码格式。
- 指令
指令 | 说明 | 示例 |
---|---|---|
create | 创建znode,并设置初始内容,可以是空串;附加参数-s 顺序节点,-e临时节点 | create /test1 “ooxx” |
set | 修改znode节点内容,可带版本号,若版本号与data版本不一致,会报错 | set /test “xxoo” 3 |
get | 获取znode节点数据 | get /test |
ls | 获取某个目录下包含的文件 | ls / |
delete | 删除子节点的node,若还有子节点,会报错 | delete /test |
rmr/deleteall | 删除节点,有子节点一并删除 | rmr /test |
create的附加参数说明:-s,是创建顺序节点,规避文件被覆盖,在分布式下,leader会做分区隔离;-e,是创建临时节点,伴随着session的会话期。
session,zk的会话,每次client创建会话时,zk都会分配一个sessioID给这次的会话,会话消失时session也会同时被删除。
- 事务id(zxid)
- czxid 创建的事务id
- mzxid 修改的事务id
- pzid 当前节点下创建的最后节点的事务id
- session 也会消耗事务id
- 监听watch
- znode发生变化(增加/删除/修改/子node)可以通过watch机制通知到客户端,client注册了watch事件,node发生变化就会触发watch事件,watch事件的响应式异步的,可通过callback回调,执行后续操作。watch监听的是session的状态,不是多线程的,是每个连接一个session。
- 分布式锁
用sequence+watch 实现分布式锁。
推导过程:
4.1. 分布式应用争抢锁,其中一个获得锁
4.2 获得锁以后,执行成功,释放锁;发生故障后,临时接待你session被删除,锁释放。
4.3 锁被释放以后,其他client需要重新去抢锁,client要知道锁被释放,可以通过心跳验证,即轮询的方式取查看锁的状态,这种轮询的方式,会对server造成压力,同时也会出现延迟的现象。
4.4 用watch实现对锁的监听,锁被释放以后,立即通知client,规避延迟的问题,但是压力问题还未解决。
4.5 用sequence+watch实现,锁被释放后,zk只给第下一个最小的获得锁的事件回调,降低成本,解决访问压力问题