事务请求(写操作)的唯一调度者和处理者,保证集群事务处理的顺序性。
集群内部各个服务器的调度者,对于create、setData、delete等有写操作的请求,则要统一转发给leader处理,leader需要决定编号、执行操作,这个过程称为事务。
处理客户端非事务(读操作)请求(可以直接响应),转发事务请求给Leader。
参与集群Leader选举投票。
对于非事务请求可以独立处理(读操作),对于事务性请求会转发给leader处理。Observer节点接收来自leader的inform信息,更新自己的本地存储,不参与提交和选举投票。通常在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
Observer应用场景:
提升集群的读性能。因为Observer不参与提交和选举的投票过程,所以可以通过往集群里面添加Observer节点来提高整个集群的读性能。
跨数据中心部署。 比如需要部署一个北京和香港两地都可以使用的zookeeper集群服务,并且要求北京和香港客户的读请求延迟都很低。解决方案就是把香港的节点都设置为observer。
leader节点可以处理读写请求,follower只可以处理读请求。follower在接到写请求时会把写请求转发给leader来处理。
图示:
Zookeeper数据一致性保证:
三台虚拟机,如下:
192.168.65.156
192.168.65.190
192.168.65.200
也可以在同一台机器上搭建伪集群。
修改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,而这个端口就是用来执行选举时服务器相互通信的端口。
创建myid文件,配置服务器编号。
在dataDir对应目录下创建myid文件,内容为对应ip的zooKeeper服务器编号。
cd /data/zookeeper
# 在文件中添加与server对应的编号(注意:上下不要有空行,左右不要有空格)
vim myid
注意:添加myid文件,一定要在Linux里面创建,在notepad++里面很可能乱码。
启动前需要关闭防火墙(生产环境需要打开对应端口)。
# 分别启动三个节点的zookeeper server
bin/zkServer.sh start
# 查看集群状态
bin/zkServer.sh status
官方介绍:https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_4lw
ZooKeeper支持某些特定的四字命令与其交互,用户获取ZooKeeper服务的当前状态及相关信息,用户在客户端可以通过telenet或者nc(netcat)向ZooKeeper提交相应的命令。
安装nc命令:
# centos
yum install nc
命令格式:
echo [command] | nc [ip] [port]
常用四字命令:
四字命令 | 功能描述 |
---|---|
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版本引入的。输出可用于检测集群健康状态的变量列表 |
开启四字命令:
方法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选举过程。
(1)每台server发出一个投票,由于是初始情况,server1和server2都将自己作为leader服务器进行投票,每次投票包含所推举的服务器myid、zxid、epoch(纪元),使用(myid,zxid)表示,此时server1投票为(1,0),server2投票为(2,0),然后将各自投票发送给集群中其他机器。
(2)接收来自各个服务器的投票。集群中的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自LOOKING状态的服务器。
(3)分别处理投票。针对每一次投票,服务器都需要将其他服务器的投票和自己的投票进行对比,对比规则如下:
a. 优先比较epoch
b. 检查zxid,zxid比较大的服务器优先作为leader
c. 如果zxid相同,那么就比较myid,myid较大的服务器作为leader服务器
(4)统计投票。每次投票后,服务器统计投票信息,判断是都有过半机器接收到相同的投票信息。server1、server2都统计出集群中有两台机器接受了(2,0)的投票信息,此时已经选出了server2为leader节点。
(5)改变服务器状态。一旦确定了leader,每个服务器响应更新自己的状态,如果是follower,那么就变更为 FOLLOWING,如果是Leader,变更为LEADING。此时server3继续启动,直接加入变更自己为FOLLOWING。
当集群中leader服务器出现宕机或者不可用情况时,整个集群无法对外提供服务,进入新一轮的leader选举。
(1)变更状态。leader挂后,其他非Oberver服务器将自身服务器状态变更为LOOKING。
(2)每个server发出一个投票。在运行期间,每个服务器上zxid可能不同。
(3)处理投票。规则同启动过程。
(4)统计投票。与启动过程相同。
(5)改变服务器状态。与启动过程相同。
在Zookeeper中,主要依赖ZAB协议来实现分布式数据一致性。
ZAB协议分为两部分:
- 消息广播
- 崩溃恢复
ZooKeeper使用单一的主进程Leader来接收和处理客户端所有事务请求,并采用ZAB协议的原子广播协议,将事务请求以Proposal提议广播到所有Follower节点,当集群中有过半的Follower服务器进行正确的ACK反馈,那么Leader就会再次向所有的Follower服务器发送commit消息,将此次提案进行提交。这个过程可以简称为2PC事务提交,整个流程可以参考下图,注意Observer节点只负责同步Leader数据,不参与2PC数据同步过程。
在正常情况消息下广播能运行良好,但是一旦Leader服务器出现崩溃,或者由于网络原理导致Leader服务器失去了与过半Follower的通信,那么就会进入崩溃恢复模式,需要选举出一个新的Leader服务器。在这个过程中可能会出现两种数据不一致性的隐患,需要ZAB协议的特性进行避免。
ZAB协议的恢复模式使用了以下策略: