Zookeeper
1.1、概述
Zookeeper是一个开源的、分布式的,为分布式架构提供协调服务的Apache项目。
Zookeeper工作机制
从设计模式的角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接收观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的哪些观察者做出相应的反应。
1.2、Zookeeper特点
1、一个leader,多个follower组成的集群
2、集群中只要有半数以上的节点存活,Zookeeper集群就能正常服务(一般奇数台机器)。
3、全局数据一致:每个Server保存一份相同的数据副本,Client无论连到哪个Server,数据都是一致的。
4、更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。
5、数据更新原子性,一次数据更新要么成功,要么失败。
6、实时性,在一定时间范围内,Client能读到最新数据。
1.3、数据结构
Zookeeper数据模型与Unix文件系统类似,整体上可以看作是一棵树,每个节点称作一个ZNode。每个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
1.4、应用场景
提供的服务包括:统一命名服务、统一配置服务、统一集群管理、服务器节点动态上下线、软负载均衡等。
统一命名服务
统一配置管理
统一集群管理
服务器动态上下线
软负载均衡
2.1 下载安装
1、安装jdk
2、解压下载的apache-zookeeper-3.5.7-bin.tar.gz
3、修改配置,指定dataDir路径
4、操作Zookeeper
- 启动Zookeeper: bin/zkServer.sh start
- 查看是否启动成功: jps
- 查看状态: bin/zkServer.sh status
- 启动客户端: bin/zkCli.sh
- 退出客户端: quit
- 停止Zookeeper: bin/zkServer.sh stop
2.2 配置参数解读
- tickTime = 2000:通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒
- initLimit = 10:LF初始通信时限,Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量)
- syncLimit = 5:LF同步通信时限,Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。
- dataDir:保存Zookeeper中的数据
- clientPort=2181:客户端连接端口
3.1集群安装
1、将Zookeeper安装至对应目录
2、创建zkData目录,并修改配置文件指定dataDir
3、在zkData目录下创建一个myid文件
4、添加配置
1 | server.2=hadoop102:2888:3888 |
3.2 选举机制
3.3 ZNode节点数据信息
1 | hadoop102:2181(CONNECTED) 5] ls -s / : |
- czxid:创建节点的事务 zxid每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。事务 ID 是 ZooKeeper 中所有修改总的次序。每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前发生。
- ctime:znode 被创建的毫秒数(从 1970 年开始)
- mzxid:znode 最后更新的事务 zxid
- mtime:znode 最后修改的毫秒数(从 1970 年开始)
- pZxid:znode 最后更新的子节点 zxid
- cversion:znode 子节点变化号,znode 子节点修改次数
- dataversion:znode 数据变化号
- aclVersion:znode 访问控制列表的变化号
- ephemeralOwner:如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节点则是 0。
- dataLength:znode 的数据长度
- numChildren:znode 子节点数量
3.4 节点类型
3.5 监听器原理
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
3.6 客户端向服务端写数据流程
写入请求直接发送给Leader节点
请求发送给follower节点
4.1 服务器动态上下线监听
分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。
服务端代码
1 | public class DistributeServer { |
客户端代码
1 | public class DistributeClient { |
4.2 zk分布式锁
分布式锁代码
1 | public class DistributedLock { |
测试代码
1 | public class DistributedLockTest { |
4.3 Curator分布式锁案例
原生API开发存在的问题
- 会话连接是异步的,需要自己去处理。比如使用 CountDownLatch
- Watch 需要重复注册,不然就不能生效
- 开发的复杂性还是比较高的
- 不支持多节点删除和创建。需要自己去递归
官方文档:https://curator.apache.org/index.html
案例实操
1、添加依赖
1 | <dependency> |
代码实现
1 | public class CuratorLockTest { |
常见问题
1、选举机制
半数机制,超过半数的投票通过,即通过。
第一次启动选举规则:投票过半数时,服务器 id 大的胜出
第二次启动选举规则:
1 EPOCH 大的直接胜出
2 EPOCH 相同,事务 id 大的胜出
3 事务 id 相同,服务器 id 大的胜出
2、生产集群安装多少台zk合适
安装奇数台。生产经验:
- 10 台服务器:3 台 zk;
- 20 台服务器:5 台 zk;
- 100 台服务器:11 台 zk;
- 200 台服务器:11 台 zk
服务器台数多:好处,提高可靠性;坏处:提高通信延时