一、ZooKeeper 应用场景
(1) 服务器在线感知
- 启动一个秒杀服务之后会向 ZooKeeper 进行注册操作(向 ZooKeeper 的指定文件夹写入该秒杀服务的信息,如 name、ip、port);然后 ZooKeeper 会创建当前秒杀服务的节点
- 客户端(服务调用者)连接 ZooKeeper 并获取秒杀服务的地址列表信息(① 不是每次发送请求都会获取地址列表信息,客户端会把地址列表信息缓存到本地;② 客户端会绑定节点改变事件)
- 客户端获得了秒杀服务的地址列表信息,在地址列表信息中随机选择一台秒杀服务发送请求
- 假如有秒杀服务宕机,ZooKeeper 会在注册中心移除掉该秒杀服务的地址信息并通知客户端进行地址列表信息的更新(ZooKeeper 通过心跳机制知道服务器是否宕机)
- 客户端接收到 ZooKeeper 的通知,并修改地址列表信息
(2) 主从协调
上图,两台服务器 server 01、server 02 构成集群。如果是主备集群,那台服务器一开始是 Active ?那台服务器一开始是 Standby ? 可通过 ZooKeeper 进行协调指定。
- 两台服务器启动,向 ZooKeeper 注册中心写入注册信息,并绑定对应的值绑定事件
- 两台服务器都判断一下自己写入的注册信息在 ZooKeeper 注册中心的注册信息列表中是否是第一条记录?第一条记录作为 Active 节点或 Master 节点,除第一条记录之外的都是 Standby 节点或 Slave 节点。
- ZooKeeper 的节点信息发生改变(新的服务器加入、旧的服务器宕机)之后,① 通知所有的已绑定值改变事件的客户端更新节点列表信息;② 向所有的服务器发送值改变的通知
- 所有的服务器接收到值改变通知后,执行步骤 2
(3) 配置管理
大型系统中会有很多需要配置的参数(如数据库配置、Tomcat 线程数的配置)。
如不使用统一的配置管理中心进行配置,而在每个应用服务中单独配置,出错的概率会很高,而且操作麻烦。
- 提供一个配置管理程序,用于向 ZooKeeper 中写入对应配置信息(键值对的形式)
- 所有的服务都会去读取 ZooKeeper 中的配置信息并加载使用
(4) 名称服务
通过指定的名字来获取资源或者服务的地址(119.93.266.66)
ZooKeeper 会在自己的文件系统上(树状结构)创建以路径为名称的节点,它可以指向提供服务的地址。
(5) 分布式锁
- 全部的订单服务在调用 createId 接口前都往 ZooKeeper 的注册中心的指定目录写入注册信息(如 /lock/server 01)和绑定值改变事件
- 全部的订单服务判断自己往注册中心指定目录写入的注册信息是否是全部注册信息中的第一条?如果是,调用 createId 接口(不是第一条就等着)。调用结束后,去注册中心移除自己的信息
- ZooKeeper 注册中心信息改变后,通知所有的绑定了值改变事件的订单服务执行第 2 条
二、Linux 上安装 ZooKeeper
(1) 下载安装包并上传到服务器
链接:https://pan.baidu.com/s/10VFu4fZEzWJnDDojBq8YXw
提取码:05m0
--来自百度网盘超级会员V4的分享
https://zookeeper.apache.org/
本人使用的上传工具是:FileZilla
(2) 解压到指定目录
tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz -C /study/usr/local
apache-zookeeper-3.6.0-bin.tar.gz 解压后的文件和文件夹如下图所示:
bin 目录下的 zkServer.sh 指令用于启动 ZooKeeper (在 linux 操作系统)
(3) 修改配置文件
配置文件所在的目录: apache-zookeeper-3.6.0-bin/conf
- 拷贝配置文件模板 zoo_sample.cfg,修改名字为 zoo.cfg
- 在 zoo.cfg 文件中添加如下内容:
dataDir=/root/apps/zookeeper/data
server.1=192.168.80.128:2888:3888
server.2=192.168.80.128:2887:3887
server.3=192.168.80.128:2889:3889
# 拷贝配置文件模板 zoo_sample.cfg,修改名字为 zoo.cfg
cp zoo_sample.cfg zoo.cfg
配置完成后的 zoo.cfg 文件:
# 心跳时间(单位:毫秒)
tickTime=2000
# 系统集群服务器初始启动的时间限制 (initLimit * tickTime = 20s)
# 集群服务器初始化时间
initLimit=10
# 同步数据的时间 = syncLimit * tickTime
syncLimit=5
# 数据存放目录(重新创建)
dataDir=/study/usr/local/apache-zookeeper-3.6.0-bin/data
# 连接端口 (客户端连接到 ZooKeeper 的端口)
# 类似 jdbc 连接 MySQL 或 Sqlyog 连接 MySQL 都需要 3306 端口
clientPort=2181
# 集群的服务器(方便数据同步)
# server.1、server.2 和 server.3 的【1、2、3】需要和 myid 文件中的内容一样
# myid 中的内容范围:[1, 254]
# [server.1, server.254]
server.1=111.11.137.12:2888:3888
server.2=111.11.137.12:2887:3887
server.3=111.11.137.12:2886:3886
# 3888、3887、3886 是选举端口
# 2888、2887、2886 是数据同步端口
(4) 创建标志文件 myid
myid 文件必须在 dataDir 目录中
echo 1 > myid
(5) 把安装并配置好的 zookeeper 文件拷贝到其他集群服务器
注意点:记得修改 myid 文件
注意点:记得修改 zoo.cfg 文件
注意点:zoo.cfg 文件中地址后面不能有【空格】
三台服务器的 clientPort 的值各不相同
现在可通过【zkServer.sh start】命令启动 ZooKeeper 服务器
(6) 配置 ZooKeeper 的环境变量
vi /etc/profile(修改文件)
export ZOOKEEPER_HOME=/root/apps/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin
(7) 启动服务相关命令
启动:zkServer.sh start
查看状态:zkServer.sh status
停止服务:zkServer.sh stop
重启服务:zkServer.sh restart
三、ZooKeeper 特点
ZooKeeper 是 Apache 软件基金会的软件项目。它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册服务。
ZooKeeper 的设计目标:封装那些复杂且容易出错的分布式一致性服务,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
ZooKeeper 是一个典型的分布式数据一致性的解决方案。分布式应用程序可以基于它实现诸如数据发布、数据订阅、负载均衡、命名服务、分布式协调、分布式通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
(1) ZooKeeper 的特性
- 一个 Leader,多个 Follower 组成的集群(3个节点是最佳实践)
- 每个集群服务器保存一份相同的数据副本。无论客户端连接那个服务器,数据都是一致的
- 分布式读写、更新请求、转发等由 Leader 执行
- 来自同一客户端的更新请求或写请求按其发送顺序依次执行(先发的先执行)
- 数据更新原子性。一次数据更新要么全部成功(半数以上节点成功),要么全部失败
- 实时性。在一定时间范围内(毫秒级别),客户端能读到最新数据(数据大小1M左右)
(2) ZooKeeper 数据结构
- 层次化的目录结构
- 在 ZooKeeper 中,每个节点叫做 znode,每个节点有一个唯一的路径标识
- 每个节点可存储很小量(小于1M)的数据。除了 EPHEMERAL 类型的节点外,每个节点可包含多个子节点
- 客户端应用可在节点上设置监听器
(3) 节点类型
ZooKeeper 有4种类型的节点:
① PERSISTENT:持久化节点
数据保存在硬盘中
② PERSISTENT_SEQUENTIAL:持久化顺序节点
- 顺序节点会自动附加顺序号(如 00001、00002),顺序号由父节点维护
- 在分布式系统中,顺序号可为所有的事件进行全局排序,客户端可通过顺序号推断事件的顺序
③ EPHEMERAL:临时节点
数据保存在内存中(会话关闭 - 数据消失)
④ EPHEMERAL_SEQUENTIAL:临时顺序节点
四、ZooKeeper 常用命令
(1) ZooKeeper 的监控和启动
启动:zkServer.sh start
查看状态:zkServer.sh status
停止服务:zkServer.sh stop
重启服务:zkServer.sh restart
查看 Java 进程 QuorumPeerMain:jps
netstat -natl
netstat -ntpl
(2) 客户端连接到 ZooKeeper
./zkCli.sh
zkCli.sh -server localhost:2181
help
help:查看所有可以执行的命令
(3) 创建节点 create
① 持久化节点
② 临时节点
- 临时节点在会话断开后被自动移除
- 临时节点没有子节点
查看节点
ls /
zookeeper 节点是 ZooKeeper 自带的节点
③ 顺序节点
④ 容器节点
可用来存放子节点。
特点:当它的全部子节点删除完之后,等待1分钟(系统配置)若还是没有子节点, 容器节点会自动删除。
create -c /cnode cnode
create -c /cnode/child01 child01
create -c /cnode/child02 child02
delete /cnode/child01
delete /cnode/child02
get /cnode
(4) 查看节点
① ls 查看节点信息
② get 获取节点数据
(5) 修改节点数据
(6) 删除节点
并发的时候,使用乐观锁进行删除(版本存在才删除)
(7) 绑定事件
① 一次事件监听
ls -w /pNode 会给 /pNode 节点绑定节点改变事件(只监听一次)
当 /pNode 的子节点改变的时候,会触发节点改变事件
get -w /pNode 会给 /pNode 节点绑定节点数据改变事件(只监听一次)
当 /pNode 的节点数据改变的时候,会触发 NodeDataChanged 事件
② 永久事件
持久化递归:当前节点及其子节点都会被绑定事件,当子节点改变和数据改变都会触发监听
持久化(PERSISTENT):只会给当前节点绑定子节点改变事件和数据改变事件,它的子节的子节点改变事件和数据改变事件不会被监听。
默认是绑定当前节点及其子节点的所有的事件
常见的事件类型:
NodeDataChanged - 节点数据改变事件
NodeChildrenChanged: 子节点数量改变事件
NodeCreated: 节点创建事件
数据获取一般绑定 NodeDataChanged
获取子节点列表一般绑定 NodeChildrenChanged