Java学习+面试指南:https://javaxiaobear.cn
事务请求(写操作)的唯一调度者和处理者,保证集群事务处理的顺序性;集群内部各个服务器的调度者。对于create、setData、delete等有写操作的请求,则要统一转发给leader处理,leader需要决定编号、执行操作,这个过程称为事务。
处理客户端非事务(读操作)请求(可以直接响应),转发事务请求给Leader;参与集群Leader选举投票。
对于非事务请求可以独立处理(读操作),对于事务性请求会转发给leader处理。Observer节点接收来自leader的inform信息,更新自己的本地存储,不参与提交和选举投票。通常在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
Observer应用场景:
提升集群的读性能。因为Observer和不参与提交和选举的投票过程,所以可以通过往集群里面添加observer节点来提高整个集群的读性能。
跨数据中心部署。 比如需要部署一个北京和香港两地都可以使用的zookeeper集群服务,并且要求北京和香港客户的读请求延迟都很低。解决方案就是把香港的节点都设置为observer。
leader节点可以处理读写请求,follower只可以处理读请求。follower在接到写请求时会把写请求转发给leader来处理。
Zookeeper数据一致性保证:
全局可线性化(Linearizable )写入∶先到达leader的写请求会被先处理,leader决定写请求的执行顺序。
客户端FIFO顺序∶来自给定客户端的请求按照发送顺序执行。
环境准备:三台虚拟机
192.168.65.156
192.168.65.190
192.168.65.200
条件有限也可以在一台虚拟机上搭建zookeeper伪集群
1) 修改zoo.cfg配置,添加server节点配置
# 修改数据存储目录
dataDir=/data/zookeeper
#三台虚拟机 zoo.cfg 文件末尾添加配置
server.1=192.168.65.156:2888:3888
server.2=192.168.65.190:2888:3888
server.3=192.168.65.200:2888:3888
server.A=B:C:D
A 是一个数字,表示这个是第几号服务器; 集群模式下配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面有一个数据 就是 A 的值,Zookeeper 启动时读取此文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是哪个server。
B 是这个服务器的地址;
C 是这个服务器Follower与集群中的Leader服务器交换信息的端口;
D 是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
2)创建 myid 文件,配置服务器编号
在dataDir对应目录下创建 myid 文件,内容为对应ip的zookeeper服务器编号
cd /data/zookeeper
# 在文件中添加与 server 对应的编号(注意:上下不要有空行,左右不要有空格)
vim myid
3)启动zookeeper server集群
启动前需要关闭防火墙(生产环境需要打开对应端口)
# 分别启动三个节点的zookeeper server
bin/zkServer.sh start
# 查看集群状态
bin/zkServer.sh status
用户可以使用Zookeeper四字命令获取 zookeeper 服务的当前状态及相关信息
zookeeper 支持某些特定的四字命令与其交互,用户获取 zookeeper 服务的当前状态及相关信息,用户在客户端可以通过 telenet 或者 nc(netcat) 向 zookeeper 提交相应的命令。
安装 nc 命令:
# centos
yum install nc
四字命令格式:
echo [command] | nc [ip] [port]
ZooKeeper 常用四字命令主要如下:
四字命令 | 功能描述 |
---|---|
conf | 3.3.0版本引入的。打印出服务相关配置的详细信息。 |
cons | 3.3.0版本引入的。列出所有连接到这台服务器的客户端全部连接/会话详细信息。包括"接受/发送"的包数量、会话id、操作延迟、最后的操作执行等等信息。 |
crst | 3.3.0版本引入的。重置所有连接的连接和会话统计信息。 |
dump | 列出那些比较重要的会话和临时节点。这个命令只能在leader节点上有用。 |
envi | 打印出服务环境的详细信息。 |
reqs | 列出未经处理的请求 |
ruok | 测试服务是否处于正确状态。如果确实如此,那么服务返回"imok",否则不做任何相应。 |
stat | 输出关于性能和连接的客户端的列表。 |
srst | 重置服务器的统计。 |
srvr | 3.3.0版本引入的。列出连接服务器的详细信息 |
wchs | 3.3.0版本引入的。列出服务器watch的详细信息。 |
wchc | 3.3.0版本引入的。通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表。 |
wchp | 3.3.0版本引入的。通过路径列出服务器watch的详细信息。它输出一个与session相关的路径。 |
mntr | 3.4.0版本引入的。输出可用于检测集群健康状态的变量列表 |
https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_4lw
开启四字命令
方法1: 在zoo.cfg 文件里加入配置项让这些指令放行
#开启四字命令
4lw.commands.whitelist=*
方法2:在zk的启动脚本zkServer.sh中新增放行指令
#添加VM环境变量-Dzookeeper.4lw.commands.whitelist=*
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"
stat 命令
stat 命令用于查看 zk 的状态信息,实例如下:
$ echo stat | nc 192.168.65.156 2181
zookeeper 的 leader 选举存在两个阶段,一个是服务器启动时 leader 选举,另一个是运行过程中 leader 服务器宕机。
在分析选举原理前,先介绍几个重要的参数:
服务器 ID(myid):编号越大在选举算法中权重越大
事务 ID(zxid):值越大说明数据越新,权重越大
逻辑时钟(epoch-logicalclock):同一轮投票过程中的逻辑时钟值是相同的,每投完一次值会增加
选举状态:
LOOKING: 竞选状态
FOLLOWING: 随从状态,同步 leader 状态,参与投票
OBSERVING: 观察状态,同步 leader 状态,不参与投票
LEADING: 领导者状态
每个节点启动的时候都 LOOKING 观望状态,接下来就开始进行选举主流程。这里选取三台机器组成的集群为例。第一台服务器 server1启动时,无法进行 leader 选举,当第二台服务器 server2 启动时,两台机器可以相互通信,进入 leader 选举过程。
每台 server 发出一个投票,由于是初始情况,server1 和 server2 都将自己作为 leader 服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch,使用(myid,zxid)表示,此时 server1 投票为(1,0),server2 投票为(2,0),然后将各自投票发送给集群中其他机器。
接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
分别处理投票。针对每一次投票,服务器都需要将其他服务器的投票和自己的投票进行对比,对比规则如下:
统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2 都统计出集群中有两台机器接受了(2,0)的投票信息,此时已经选出了 server2 为 leader 节点。
改变服务器状态。一旦确定了 leader,每个服务器响应更新自己的状态,如果是 follower,那么就变更为 FOLLOWING,如果是 Leader,变更为 LEADING。此时 server3继续启动,直接加入变更自己为 FOLLOWING。
当集群中 leader 服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的 leader 选举。
在 Zookeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性。
ZAB 协议分为两部分:
消息广播
崩溃恢复
Zookeeper 使用单一的主进程 Leader 来接收和处理客户端所有事务请求,并采用 ZAB 协议的原子广播协议,将事务请求以 Proposal 提议广播到所有 Follower 节点,当集群中有过半的Follower 服务器进行正确的 ACK 反馈,那么Leader就会再次向所有的 Follower 服务器发送commit 消息,将此次提案进行提交。这个过程可以简称为 2pc 事务提交,整个流程可以参考下图,注意 Observer 节点只负责同步 Leader 数据,不参与 2PC 数据同步过程。
在正常情况消息下广播能运行良好,但是一旦 Leader 服务器出现崩溃,或者由于网络原理导致 Leader 服务器失去了与过半 Follower 的通信,那么就会进入崩溃恢复模式,需要选举出一个新的 Leader 服务器。在这个过程中可能会出现两种数据不一致性的隐患,需要 ZAB 协议的特性进行避免。
Leader 服务器将消息 commit 发出后,立即崩溃
Leader 服务器刚提出 proposal 后,立即崩溃
ZAB 协议的恢复模式使用了以下策略:
选举 zxid 最大的节点作为新的 leader
新 leader 将事务日志中尚未提交的消息进行处理