一、简介
Zookeeper是一个分布式应用协调框架,用来解决分布式系统中数据性一致的基础问题。
- 如何解决的?
– 提供了以ZNode为核心的文件系统,每个节点可以是文件也可以是目录,只能用绝对路径使用
– 提供了Watch监听通知机制
二、安装
- 编写docker-compose文件
version: '3.1' services: zoo1: image: zookeeper:3.5 restart: always hostname: zoo1 ports: - 2181:2181 environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 zoo2: image: zookeeper:3.5 restart: always hostname: zoo2 ports: - 2182:2181 environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 zoo3: image: zookeeper:3.5 restart: always hostname: zoo3 ports: - 2183:2181 environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
- 启动(docker-compose up -d)
- 进入(docker-compose exec zoo1 bash)
- 连接(zkCli.sh)
三、ZNode的操作命令
命令 | 示例 | 含义 |
---|---|---|
ls 节点路径 | ls / | 浏览某个节点下的所有子节点 |
create 节点路径 节点值 [数据版本号] | create /baizhi baizhiinfo | 创建节点,并设置节点值 |
get 节点路径 | get /baizhi | 查看节点的值 |
set 节点路径 节点值 | set /baizhi baizhiinfo2 | 更新节点的值 |
delete 节点路径 | delete /baizhi | 删除某个节点 |
rmr 节点路径 | rmr /baizhi | 删除该节点,并递归的删除子节点 |
四、节点类型
-
PERSISTENT(持久节点)
特点:节点一旦创建长久保存,除非显式调用delete命令才会删除节点
创建命令:
create 节点路径 节点值
应用场景:保存服务的配置文件,在多个服务间共享配置
-
EPHEMERAL(临时节点)
特点:创建节点的client一旦断开和zk的连接,自动删除节点
创建命令:
create -e 节点路径 节点值
应用场景:可以用于统计集群中机器的运行情况,机器上线时为每台机器创建一个临时节点,统计临时节点个数获取运行的机器数量
-
PERSISTENT_SEQUENTIAL(持久有序编号节点)
特点:节点一旦创建,长久有效。zk自动为节点添加自增的序号。
创建命令:
create -s 节点路径 节点值
-
EPHEMERAL_SEQUENTIAL(临时有序编号节点)
特点:创建节点的client一旦断开和zk的连接,自动删除节点。zk自动为节点添加自增的序号。
创建命令:
create -s -e 节点路径 节点值
应用场景:分布式锁,多个进程同时创建节点
/locks
,按照节点序号大小依次获取锁,哪个进程的节点值最小,哪个进程获取到锁。
五、watch监听机制
可以监听一个节点,一旦节点发生变化,可以立刻得到通知
- get /节点 watch
- ls /节点 watch
六、zk服务器集群角色的分类
- Leader 角色服务器负责管理集群中其他的服务器,是集群中工作的分配和调度者。
- Follower 服务器的主要工作是选举出 Leader 服务器,在发生 Leader 服务器选举的时候,系统会从 Follower 服务器之间根据多数投票原则,选举出一个 Follower 服务器作为新的 Leader 服务器。
七、ZK集群数据读写
写操作:
- 客户端将写操作请求发送到zk服务器
- 如果连接到的是follower节点,则将写操作转给leader
- leader生成一个新的事务并为这个事务生成一个唯一的
Zxid
- leader节点会把数据通过proposal请求发送到所有节点(包括自己),广播这个 Proposal 事务,Leader 节点和 Follower 节点是解耦的,通信都会经过一个先进先出的消息队列,Leader 会为每一个 Follower 服务器分配一个单独的 FIFO 队列,然后把 Proposal 放到队列中;
- 所有到节点接受到proposal请求以后都会写到自己到本地磁盘上面,成功后向leader返回ACK(确认消息)
- leader接收到半数以上的ACK时(包括自己),leader向所有follower广播commit消息
- 各个节点接收到commit后,就会把消息放入到内存中(放内存是为了保证高性能),该消息就对用户可见了
- 通知 Client 数据写成功了,这时就认为整个写操作成功
读操作:
- client发起请求连接zk节点
- 无论节点是什么角色,都直接从当前zk节点返回读取结果
八、Leader的选举
服务启动时的 Leader 选举:
- 启动时每个节点会向集群中获取主节点,此时节点为跟随状态,没有主节点则进行投票选举,先使用zxid投票选举,达到半数则为主节点,未分辨则根据myid投票选举,半数则为主节点
服务运行时的 Leader 选举(旧的Leader失效):
- 主节点崩溃,其他都变为looking状态
- 每个集群中的服务器都会投票给自己,将投票信息中的 Zxid 和 myid 分别指向本机服务器,这一步中Zxid有很大概率不同,最终选举时一定选举出Zxid更大的机器。