Java-第十九部分-Zookeeper-概述、选举和使用

104 阅读6分钟

Zookeeper全文

概述

  • 一个基于观察者设计模式设计的分布式服务管理框架,负责存储和管理关心的数据,接受观察者注册,并且在数据更新时,可以通知注册观察者
  • 文件系统+通知机制
  1. 文件系统,也就是存储服务器或其他数据的上下线信息
  • 应用场景
  1. 统一命名服务,存储域名和对应的多个ip,类似nginx
  2. 统一配置管理,一个集群配置信息是一致的且同步快,各个客户端监听zookeeper的配置文件,发生改变,就进行配置更新
  3. 统一集群管理,掌握集群的每个节点的状态,zookeeper存储节点信息
  4. 服务器动态上下线,服务器上下线写入zookeeper,zookeeper通知客户端服务器的上下线
  5. 软负载均衡,一个服务下有多台服务器,zookeeper根据每个节点的状态,进行负载均衡

概念

  • zxid,客户端每次写操作的事务id
  • sid,服务器id,和myid一样
  • Epoch,每个Leader任期的代号;没有leader,编号都相同,每次完成投票,都会+1

集群特点

  1. 一个leader,多个follower组成的集群
  2. 一写多读,当写请求发给follower时,会将请求转发给leader,leader写完后,再进行数据同步;半数以上节点同步完成,由响应节点给客户端回ack
  3. 只要有半数以上节点存活,就能正常服务,适合安装奇数台服务器
  4. 半数以上节点同步成功,即可返回
  5. 全局数据一致,每个Server保存一份相同的数据副本
  6. 更新请求顺序执行,同一个客户端的更新请求按照发送顺序依次执行
  7. 数据更新原子性,一次数据更新要么成功,要么失败
  8. 实时性,同步时间非常快

集群写数据

  • 写请求给leader image.png
  • 写操作给follower节点 image.png

数据结构

  • 与Unix文件系统类似,整体是一棵树
  • 每个节点为ZNode,默认存储1MB的数据,存储简单的配置信息
  • 每个ZNode,都可以通过其路径确认唯一标识 image.png

节点类型

  • 持久,客户端和服务端断开连接后,不删除
  1. 持久化顺序编号目录节点,zookeeper会给该节点名称进行顺序编号,编号递增,未全局排序
  • 短暂,断开连接后,节点删除
  1. 临时顺序编号目录节点,节点后面带序号

选举

  • 一台服务器出现两种情况,进入leader选择
  1. 服务器初始化启动
  2. 服务器运行期间无法和leader保持连接
  • 当一台机器进行选举,存在两种情况
  1. 集群中已经存在leader
  2. 集群中确实不存在leader

第一次启动

  • 第一台服务器启动时,发起选举,头给自己,不够半数,那么就保持状态为LOOKING
  • 第二台服务器启动,再发起一次选择,分别投给自己,并交换选票信息
  1. 投给myid大的机器,如果超过半数,完成选举
  2. 如果没超过半数,那么都为LOOKING,等下接下来的服务器启动
  • 当选出leader后,后来启动的设备,都是follower

非第一次启动

  • 集群中已经有leader,其他服务器会告知这台服务器leader信息,并试图连接leader,进行数据同步
  • 集群中不存在leader,结合epoch/zxid/sid进行选举
  1. epoch大的胜出
  2. zxid大的胜出
  3. sid大的胜出

使用

参数解析

  • 安装zookeeper之后,conf目录下的zoo.cfg
# 通信心跳时间
tickTime=2000
# Leader 和 follower 初始化通信时间
# 10倍的心跳时间,如果没有建立,那么就建立失败
initLimit=10
# leader follower 同步通信时间,
syncLimit=5
# 数据目录
dataDir=/Users/mzx/Desktop/java/zookeeper/apache-zookeeper-3.5.9-bin/data
# 客户端连接端口
clientPort=2181
admin.serverPort=8989
#maxClientCnxns=60
#autopurge.snapRetainCount=3
#autopurge.purgeInterval=1

启动

  • bin目录下
  • 服务器zkServer.sh start
  1. 查看状态zkServer.sh status
  2. 停止zkServer.sh stop
  • 客户端zkCli.sh

退出quit

集群安装

  • 创建zkData,并创建myid,并设置变好
  • 修改数据存储路径,要指向zkData的位置
  • 增加配置server.A=B:C:D,每个节点的配置文件下都要有全部的节点该配置
  1. A 表示myid的文件中的值
  2. B 表示服务器地址
  3. C 表示这个follower与leader的交换端口
  4. D 表示Leader挂了,需要一个端口重新进行选举

脚本

  • zk.sh,并且要chmod 777 zk.sh,变成可执行文件
# !/bin/bash

case $1 in
"start") {
	for i in c1 c2 c3
	do
		echo --------- zookeeper $i start --------------
		ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh start"
	done 
}
;;

"stop") {
	for i in c1 c2 c3
	do
		echo --------- zookeeper $i stop --------------
		ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh stop"
	done 

}
;;

"status") {
	for i in c1 c2 c3
	do
		echo --------- zookeeper $i status --------------
		ssh $i "/usr/local/zookeeper/zookeeper/bin/zkServer.sh status"
	done 
}
;;
esac

客户端使用

  • 查看节点ls /ls -s /查看节点明细
// 事务id
[dubbo, services, zookeeper]cZxid = 0x0
// 创建时的毫秒值
ctime = Thu Jan 01 08:00:00 CST 1970
// 最后更新的事务
mZxid = 0x0
// 最后修改的毫秒
mtime = Thu Jan 01 08:00:00 CST 1970
// 最后更新的子节点
pZxid = 0x200
// znode子节点变化的修改次数
cversion = 7
// 数据变化号
dataVersion = 0
// 访问控制列表的变化号,权限
aclVersion = 0
// 如果是临时节点,znode拥有者的session id
ephemeralOwner = 0x0
// 数据长度
dataLength = 0
// 子节点数
numChildren = 3
  • 创建
  1. 普通创建create /test "i am test"
  2. 多目录创建create /test/son "i am test's son"
  3. 带序号创建 create -s /test/mother "i am mother"
  4. 创建临时节点 create -e /test/student "student"
  5. 创建带序号临时节点 create -e -s /test/teacher "teacher"
  • 获取值
  1. get /testget -s /test
  • 修改节点值
  1. set /test/son "i am father"
  • 删除
  1. 删除某个节点 delete /test/son
  2. 删除当前节点及所有子节点 deleteall /test
  • 查看状态信息 stat /test

监听器

  • 客户端向服务端进行注册,关注某个数据变化,数据变化时,服务端进行通知
  1. 客户端main线程,创建客户端,并且有两个线程,一个负责connect,一个负责listener
  2. connect线程将注册事件发送给服务端,服务端将注册的监听事件添加到列表中
  3. 服务端监听到有数据或路径变化,将这个消息发送给listener线程,进行处理
  • 监听某个节点数据变化 get -w /test,只注册一次监听,那么就只处理一次变化 image.png
  • 监听节点数变化ls -w /test image.png