文章目录
ZooKeeper
一、ZooKeeper概述
- ZooKeeper是Apache Hadoop项目下的一个子项目,是一个树形目录服务
- ZooKeeper翻译过来就是动物园管理员,他是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管理员,简称zk
- ZooKeeper是一个分布式的、开源的分布式应用程序的协调服务
- ZooKeeper通过监控节点以及节点的变化来实现功能
- 配置管理
- 分布式锁
- 集群管理
二、ZooKeeper命令操作
1.ZooKeeper数据模型
- ZooKeeper是一个树形目录服务,其数据模型和Unix的文件系统目录树很类似,拥有一个层次化结构
- 这里面的每一个节点都被称为: ZNode,每个节点上都会保存自己的数据和节点信息
- 节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下
- 节点可以分为四大类
- PERSISTENT持久化节点
- EPHEMERAL临时节点:-e
- PERSISTENT_SEQUENTIAL持久化顺序节点:-s
- EPHEMERAL_SEQUENTIAL临时顺序节点:-es
2.ZooKeeper服务端常用命令
- 启动ZooKeeper服务:./zkServer.sh start
- 查看ZooKeeper服务状态:./zkServer.sh status
- 停止ZooKeeper服务:./zkServer.sh stop
- 重启ZooKeeper服务:./zkServer.sh restart
3.ZooKeeper客户端常用命令
- 连接ZooKeeper服务端
./zkCli.sh –server ip:port
- 断开连接
quit
- 设置节点值
set /节点path value
- 查看命令帮助
help
- 删除单个节点
delete /节点path
- 显示指定目录下节点
ls 目录
- 删除带有子节点的节点
deleteall /节点path
- 创建节点
create /节点path value
- 获取节点值
get /节点path
- 创建临时节点
create -e /节点path value
- 创建顺序节点
create -s /节点path value
- 查询节点详细信息
ls –s /节点path
三、ZooKeeperJavaAPI操作
1.Curator介绍
- Curator是Apache ZooKeeper的Java客户端库
- 常见的ZooKeeper Java API
- 原生Java API
- ZkClient
- Curator
- Curator项目的目标是简化ZooKeeper客户端的使用
2.Curator API常用操作
- 建立连接
- 添加节点
- 删除节点
- 修改节点
- 查询节点
- Watch事件监听
- ZooKeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是ZooKeeper实现分布式协调服务的重要特性
- ZooKeeper中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者
- ZooKeeper原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便需要开发人员自己反复注册Watcher,比较繁琐
- Curator引入了Cache来实现对 ZooKeeper服务端事件的监听
- ZooKeeper提供了三种Watcher
- NodeCache:只是监听某一个特定的节点
- PathChildrenCache:监控一个ZNode的子节点
- TreeCache:可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
- 分布式锁实现
3.分布式锁
1.分布式锁概述
- 在我们进行单机应用开发,涉及并发同步的时候,我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题,这时多线程的运行都是在同一个JVM之下,没有任何问题
- 但当我们的应用是分布式集群工作的情况下,属于多JVM下的工作环境,跨JVM之间已经无法通过多线程的锁解决同步问题
- 那么就需要一种更加高级的锁机制,来处理种跨机器的进程之间的数据同步问题——这就是分布式锁
2.分布式锁原理
- 核心思想:当客户端要获取锁,则创建节点,使用完锁,则删除该节点
- 客户端获取锁时,在节点下创建临时顺序节点
- 防止客户端宕机,节点无法被删除并释放锁
- 然后获取该节点下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。使用完锁后,将该节点删除
- 如果发现自己创建的节点并非该节点所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件
- 如果发现比自己小的那个节点被删除,则客户端的Watcher会收到相应通知,此时再次判断自己创建的节点是否是该节点的子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听
- 客户端获取锁时,在节点下创建临时顺序节点
3.Curator实现分布式锁API
- 在Curator中有五种锁方案
- InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
- InterProcessMutex:分布式可重入排它锁
- InterProcessReadWriteLock:分布式读写锁
- InterProcessMultiLock:将多个锁作为单个实体管理的容器
- InterProcessSemaphoreV2:共享信号量
四、Zookeeper集群搭建
1.ZooKeeper集群介绍
- Leader选举
- Serverid:服务器ID
- 比如有三台服务器,编号分别是1、2、3。编号越大在选择算法中的权重越大
- Zxid:数据ID
- 服务器中存放的最大数据ID值越大说明数据越新,在选举算法中数据越新权重越大
- 在Leader选举的过程中,如果某台ZooKeeper获得了超过半数的选票,则此ZooKeeper就可以成为Leader了
- Serverid:服务器ID
2.ZooKeeper集群搭建
- 3个节点的集群,从服务器挂掉,集群正常
- 3个节点的集群,2个从服务器挂掉,主服务器无法运行
- 可运行的机器没有超过集群总数量的半数
- 集群中的主服务器挂掉,集群中的其他服务器会自动进入选举状态,产生新的leader
- 当领导者产生后,再次有新服务器加入集群,不会影响到现任领导者
- 在集群模式下,建议至少部署3个zk进程,或者部署奇数个zk进程
- 如果只部署2个zk进程,当其中一个zk进程挂掉后,剩下的一个进程并不能构成一个quorum的大多数
- 部署2个进程甚至比单机模式更不可靠,因为2个进程其中一个不可用的可能性比一个进程不可用的可能性还大
五、ZooKeeper核心理论
1.ZooKeeper集群角色
- 在ZooKeeper集群服中务中有三个角色
- Leader领导者
- 处理事务请求
- 集群内部各服务器的调度者
- Follower跟随者
- 处理客户端非事务请求,转发事务请求给Leader服务器
- 参与Leader选举投票
- Observer观察者
- 处理客户端非事务请求,转发事务请求给Leader服务器
- Leader领导者
- 特点
- 一个领导者(Leader)多个跟随者(Follower)组成的集群
- 集群中只要有半数以上的节点存活,Zookeeper集群就能正常服务
- 全局数据一致,即每个Server保存一份相同的数据副本,Client无论连接到那个Server,数据是一致的
- 更新请求顺序进行,即来自同一个Client的更新请求按其发送顺序依次执行
- 数据更新原子性,即一次数据更新要么成功,要么失败
- 实时性,即在一定时间范围内,Client能读到最新数据
2.Zookeeper原理
- Zookeeper使用zab协议,该协议包括2个不断重复的阶段
- 领导者选举
- 集群所有机器一起选出一台领导者,其它机器成为跟随者,一旦半数以上的跟随者将状态同步,表示这个阶段完成(官方数据这个阶段持续200毫秒)
- Zookeeper通过复制实现高可用性,只要集群中半数以上的机器可用,就能提供服务,所以一个集群通常要奇数台机器
- 原子广播
- 所有机器将写操作转发给领导者,领导者再将更新广播给跟随者,只有半数以上的跟随者同步修改之后领导者才会提交更新,客户端才能收到更新成功的信息
- 领导者选举
- Zookeeper核心是一个精简的文件系统,形成一个树状的数据结构,统一使用节点(Znode)的概念
- 节点可以有子节点,也可以用来保存数据,并且有一个关联的ACL
- Zookeeper被设计来实现协调服务,通常使用小数据文件,所以Znode能存储的数据限制在1M以内
- Zookeeper采用斜杠分割的Unicode字符串来做引用类似文件系统路径,但必须是标准的,不支持./特殊字符,使用/Zookeeper子树来保存管理信息
- 客户端与服务器通信采用tcp长连接,客户端和服务器通过心跳来保持seesion的连接,当session失效时临时节点会被删除
- Zookeeper的生命周期有3个状态CONNECTION、CONNECTED、CLOSED
- 新产生的Zookeeper实例是CONNECTION状态,通过建立连接进入CONNECTED状态
- 当Zookeeper实例断开和重连的时候,Zookeeper实例在CONNECTED和COONECTION之间转换
- 调用close()方法或者会话超时会进入到CLOSE状态且不能恢复
3.应用场景
- Zookeeper从设计模式的角度来看是一个观察者模式的分布式服务管理框架
- 负责存储和管理大家关心的数据,然后接受观察者的注册
- 一旦这些数据发生变化,Zookeeper就会负责通知已经注册过了的那些observer做出相应的反应,从而实现集群中类似的Master、Slave管理模式
1.统一命名服务
- 分布式应用中,通常需要有一套完整的命名规则, 能够产生唯一的名称以便于识别和记住
- 通常情况下用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,既对人友好又不会重复
- Name Service是Zookeeper内置的功能,只须调用其api就可以实现
- 如调用create接口就可以容易的创建一个目录节点
2.配置管理
- 配置的管理费用在分布式应用环境中很常见
- 如同一个应用系统需要多个PC server运行, 但是它们运行的应用系统的某些配置项是相同的
- 如果要修改这些相同的的配置项,那么就必须同时修改每台运行这个应用系统的PC server,这样非常容易出错
- 将配置信息保存在Zookeeper的某个目录节点上,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台机器就会收Zookeeper的通知