大数据环境统一与zookeeper
一、集群环境准备
1. 三台虚拟机创建
第一种方式:通过iso镜像文件来进行安装(不推荐)
第二种方式:直接复制安装好的虚拟机文件(强烈推荐)
在课程资料里边已经提供了一个安装好的虚拟机node1(注意,为了大家以后环境的统一,尽量使用课程资料中提供的已经安装好的虚拟机!!!!!!),我们需要根据这个虚拟机克隆出另外两台虚拟机出来,注意,步骤如下:
1)使用VMware加载资料中虚拟机node1
![](https://i-blog.csdnimg.cn/blog_migrate/1c741af3766e76052c22a896893a0a32.png)
2)克隆第二台虚拟机,注意克隆虚拟机的时候,虚拟机必须是关闭状态
右键点击node1
![](https://i-blog.csdnimg.cn/blog_migrate/98f2d229594432e6a03fc14b65477a4b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b014d1e4cba3267e4da56ebcc1fee087.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c537750a12e83e908968779485aaea16.png)
![](https://i-blog.csdnimg.cn/blog_migrate/495bf057263f39cb8829be115b6edbae.png)
指定虚拟机名字和存放位置,三台虚拟机的存放路径尽量在一起,不在一起也没关系
![](https://i-blog.csdnimg.cn/blog_migrate/b9ffac6b2518d08a94f43e48bc2ad25d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a80142aaed002aea0383441fc61d40c3.png)
2)克隆第三台虚拟机,通过node1虚拟机克隆,克隆方式是一样的,注意修改虚拟机的名称和存放位置。
![](https://i-blog.csdnimg.cn/blog_migrate/552c7b1d4a47ce401f35d5fcd47ac968.png)
2. 设置三台虚拟机的内存
三台虚拟机再加上windows本身, 需要同时运行4台机器, 所以在分配的时候,, 每台虚拟机的内存为: 总内存 ÷ 4,比如电脑总内存为16G,则每台虚拟机内存为4G。
下面是以node1为例对内存进行配置:
![](https://i-blog.csdnimg.cn/blog_migrate/ea993a02f2fe101ff70abc34b5447607.png)
3. 配置MAC地址
node2和node3都是从node1克隆过来的,他们的MAC地址都一样,所以需要让node2和node3重新生成MAC地址,生成方式如下:
1、配置node2的MAC地址
1)使用VMware打开node2
2)右键点击node2,选择设置
![](https://i-blog.csdnimg.cn/blog_migrate/b13252a389daea3e0e421b04c2e147c2.png)
3)生成新的MAC地址
![](https://i-blog.csdnimg.cn/blog_migrate/27ab65a3606ec4d393c46512f15fd64b.png)
2、配置node3的MAC地址
node3的配置方式和node2相同,不再重复
4. 配置IP地址
三台虚拟机的IP地址配置如下:
node1: 192.168.88.161
node2 192.168.88.162
node3: 192.168.88.163
node1的IP地址已经配置好了,接下来配置node2和node3:
1:配置node2主机IP
1)修改ip配置文件,设置IP地址
vim /etc/sysconfig/network-scripts/ifcfg-ens33 |
![](https://i-blog.csdnimg.cn/blog_migrate/68bddb0cf0be0fec2797b0045bd562ff.png)
2)重启网络服务
systemctl restart network # 重启网络服务 |
![](https://i-blog.csdnimg.cn/blog_migrate/a9b56c13b3b06bacbef37334e1fcf093.png)
3)查看ip地址
ifconfig |
![](https://i-blog.csdnimg.cn/blog_migrate/47051a1186604b23fc769fc52df7ee8d.png)
4) 测试网络连接
ping www.baidu.com |
![](https://i-blog.csdnimg.cn/blog_migrate/7e0280a852471c181e8b8037857eef3c.png)
2:配置node3主机IP
node3主机IP的配置方式和node2一样,将其IP地址设置为:192.168.88.163,在这里不再重复。
![](https://i-blog.csdnimg.cn/blog_migrate/4c5110fbfbe49c38fba4ccd2cf485a47.png)
5. 使用CRT连接三台虚拟机
1、建立连接
![](https://i-blog.csdnimg.cn/blog_migrate/837c6463e33cf35b61e1570f5a53e752.png)
2、参数配置
![](https://i-blog.csdnimg.cn/blog_migrate/0e411c49193b174ab637f3118354387c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bbed6c1586aaa3b0030a9fd16cbcdbde.png)
3、设置主题,颜色和仿真
![](https://i-blog.csdnimg.cn/blog_migrate/0ec6e4d063f7f90db68112ee2cba725f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4f06bd89f6d03f547580a8edfa6e6aa0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/eb0f6c3345b82e8e3e78f4aaad2231a2.png)
6. 设置主机名和域名映射
1、配置每台虚拟机主机名:
分别编辑每台虚拟机的hostname文件,直接填写主机名,保存退出即可。
vim /etc/hostname |
第一台主机主机名为:node1
第二台主机主机名为:node2
第三台主机主机名为:node3
2、配置每台虚拟机域名映射
分别编辑每台虚拟机的hosts文件,在原有内容的基础上,填下以下内容:
注意:不要修改文件原来的内容,三台虚拟机的配置内容都一样。
vim /etc/hosts |
192.168.88.161 node1 node1.itcast.cn 192.168.88.162 node2 node2.itcast.cn 192.168.88.163 node3 node3.itcast.cn |
配置后效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/84799c227190ce55876abe21f7df8f86.png)
7. 关闭三台虚拟机的防火墙和Selinux
1、关闭每台虚拟机的防火墙
在每台虚拟机上分别执行以下指令:
systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall开机启动 |
关闭之后,查看防火墙状态:
systemctl status firewalld.service |
![](https://i-blog.csdnimg.cn/blog_migrate/d5aeb204262da8e1fecb21425f6cb32d.png)
2、关闭每台虚拟机的Selinux
1)什么是SELinux ?
1)SELinux是Linux的一种安全子系统
2)Linux中的权限管理是针对于文件的, 而不是针对进程的, 也就是说, 如果root启动了某个进程, 则这个进程可以操作任何一个文件。
3)SELinux在Linux的文件权限之外, 增加了对进程的限制, 进程只能在进程允许的范围内操作资源
2)为什么要关闭SELinux
如果开启了SELinux, 需要做非常复杂的配置, 才能正常使用系统, 在学习阶段, 在非生产环境, 一般不使用SELinux
SELinux的工作模式:
enforcing 强制模式
permissive 宽容模式
disabled 关闭
4)关闭SELinux方式
编辑每台虚拟机的Selinux的配置文件
vim /etc/selinux/config |
Selinux的默认工作模式是强制模式,配置如下:
![](https://i-blog.csdnimg.cn/blog_migrate/e75c37190bb373a312790c2876dc2125.png)
将Selinux工作模式关闭:
![](https://i-blog.csdnimg.cn/blog_migrate/487976ac345cb297431de76010e7b306.png)
5)分别重启三台虚拟机
reboot |
8. 三台机器机器免密码登录
1、为什么要免密登录
Hadoop 节点众多, 所以一般在主节点启动从节点, 这个时候就需要程序自动在主节点登录到从节点中, 如果不能免密就每次都要输入密码, 非常麻烦。
![](https://i-blog.csdnimg.cn/blog_migrate/0b1e2268cbfdda512e9571a5a8272e30.png)
2、免密 SSH 登录的原理
1. 需要先在 B节点 配置 A节点 的公钥
2. A节点 请求 B节点 要求登录
3. B节点 使用 A节点 的公钥, 加密一段随机文本
4. A节点 使用私钥解密, 并发回给 B节点
5. B节点 验证文本是否正确
![](https://i-blog.csdnimg.cn/blog_migrate/c226a827b25e28225ac0c92f8911a63c.png)
3、实现步骤
第一步:三台机器生成公钥与私钥
在三台机器执行以下命令,生成公钥与私钥
ssh-keygen -t rsa |
执行该命令之后,按下三个回车即可,然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥),默认保存在/root/.ssh目录。
![](https://i-blog.csdnimg.cn/blog_migrate/f076233d1b5429cc60e0d7245f0468c3.png)
第二步:拷贝公钥到同一台机器
三台机器将拷贝公钥到第一台机器
三台机器执行命令:
ssh-copy-id node1 |
在执行该命令之后,需要输入yes和node1的密码:
![](https://i-blog.csdnimg.cn/blog_migrate/b07a6b9adadbcb6056a8965e424ab6df.png)
第三步:复制第一台机器的认证到其他机器
将第一台机器的公钥拷贝到其他机器上
在第一台机器上指行以下命令
scp /root/.ssh/authorized_keys node2:/root/.ssh scp /root/.ssh/authorized_keys node3:/root/.ssh |
执行命令时,需要输入yes和对方的密码
第三步:测试SSH免密登录
可以在任何一台主机上通过ssh 主机名命令去远程登录到该主机,输入exit退出登录
例如:在node1机器上,免密登录到node2机器上
ssh node1 exit |
执行效果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4d0ebaae6fdafceff8bdeac0c2161a83.png)
9. 三台机器时钟同步
为什么需要时间同步
因为很多分布式系统是有状态的, 比如说存储一个数据, A节点 记录的时间是1, B节点 记录的时间是2, 就会出问题
时钟同步方式
方式一:通过网络进行时钟同步
![](https://i-blog.csdnimg.cn/blog_migrate/64487f6a9c0ed05be3d3f32cebe7b0a0.png)
通过网络连接外网进行时钟同步,必须保证虚拟机连上外网
1、启动定时任务
crontab -e |
随后在输入界面键入以下内容,每隔一分钟就去连接阿里云时间同步服务器,进行时钟同步
*/1 * * * * /usr/sbin/ntpdate -u ntp4.aliyun.com; |
方式二:通过某一台机器进行同步
![](https://i-blog.csdnimg.cn/blog_migrate/ceeb444fd19e078c69fe363958ca9b6a.png)
以192.168.88.161这台服务器的时间为准进行时钟同步
第一步:在node1虚拟机安装ntp并启动
安装ntp服务
yum -y install ntp |
启动ntp服务
systemctl start ntpd |
设置ntpd的服务开机启动
#关闭chrony,Chrony是NTP的另一种实现 systemctl disable chrony #设置ntp服务为开机启动 systemctl enable ntpd |
第二步:编辑node1的/etc/ntp.conf文件
编辑node1机器的/etc/ntp.conf
vim /etc/ntp.conf |
在文件中添加如下内容(授权192.168.88.0-192.168.88.255网段上的所有机器可以从这台机器上查询和同步时间)
restrict 192.168.88.0 mask 255.255.255.0 nomodify notrap |
注释一下四行内容:(集群在局域网中,不使用其他互联网上的时间)
#server 0.centos.pool.ntp.org #server 1.centos.pool.ntp.org #server 2.centos.pool.ntp.org #server 3.centos.pool.ntp.org |
去掉以下内容的注释,如果没有这两行注释,那就自己添加上(当该节点丢失网络连接,依然可以采用本地时间作为时间服务器为集群中的其他节点提供时间同步)
server 127.127.1.0 fudge 127.127.1.0 stratum 10 |
![](https://i-blog.csdnimg.cn/blog_migrate/7dfb228c1901b3e33a51a559da138696.png)
配置以下内容,保证BIOS与系统时间同步
vim /etc/sysconfig/ntpd |
添加一行内容
SYNC_HWLOCK=yes |
![](https://i-blog.csdnimg.cn/blog_migrate/43258cb71869ee4f698f4b4d434c3236.png)
重启ntp服务
systemctl restart ntpd |
第三步:另外两台机器与第一台机器时间同步
另外两台机器与192.168.88.161进行时钟同步,在node2和node3机器上分别进行以下操作
crontab -e |
添加以下内容:(每隔一分钟与node1进行时钟同步)
*/1 * * * * /usr/sbin/ntpdate 192.168.88.161 |
10. 三台虚拟机JDK环境安装
JDK 是个绿色软件,解压并且配置环境变量即可使用
1) JDK安装步骤
1) 在虚拟机中创建两个目录
mkdir -p /export/software 软件包放置的目录 mkdir -p /export/servers 软件安装的目录 |
2) 进入 /export/software 目录, 上传jdk的安装包: jdk-8u241-linux-x64.tar.gz
3) 解压压缩包到/export/servers目录下
tar -zxvf jdk-8u241-linux-x64.tar.gz -C /export/servers |
查看解压后的目录,目录中有 jdk1.8.0_144 为 jdk 解压的目录
![](https://i-blog.csdnimg.cn/blog_migrate/a62296e3f7c3762619c06f23284631af.png)
4) 配置 jdk 环境变量,打开/etc/profile 配置文件,将下面配置拷贝进去。export 命令用于将 shell 变量输出为环境变量
第一步: vi /etc/profile 第二步: 通过键盘上下键 将光标拉倒最后面 第三步: 然后输入 i, 将一下内容输入即可 #set java environment JAVA_HOME=/export/servers/jdk1.8.0_241 CLASSPATH=.:$JAVA_HOME/lib PATH=$JAVA_HOME/bin:$PATH export JAVA_HOME CLASSPATH PATH 第四步: esc键 然后 :wq 保存退出即可 |
5) 重新加载环境变量:
source /etc/profile |
![](https://i-blog.csdnimg.cn/blog_migrate/d407175bcdd73b0848f4e91f8b0b5196.png)
6) 配置jdk是否安装成功
java -version |
![](https://i-blog.csdnimg.cn/blog_migrate/d104a6caa122f77277318dd2a08523bd.png)
11. 三台虚拟机拍摄快照
VMware中的快照是对虚拟机在某个时间点的“拷贝”,这个“拷贝”并不是对虚拟机文件的复制,而是保持磁盘文件和系统内存在该时间点的状态,以便在出现故障后虚拟机能够恢复到该时间点。如果对某个虚拟机创建了多个快照,那么就可以有多个可恢复的时间点。
如何拍摄快照呢? 快照可以在开机时拍摄, 也可以在关机时拍摄, 建议采用关机拍摄, 这样快照文件占用磁盘相对较少
【第一步: 选择要拍摄快照的虚拟机右键】
【第二步: 点击拍摄快照】
![](https://i-blog.csdnimg.cn/blog_migrate/0faa87aa1f42097ec9c2179f2a0ed9ac.png)
【第三步: 为快照起一个名称, 然后点击拍摄 即可完成】
如何恢复快照?
【第一步: 选择要恢复快照的服务器右键】
【第二步: 选择快照-->快照管理器】
![](https://i-blog.csdnimg.cn/blog_migrate/d502e1127c782c84d59d6c69a1ee0b32.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f1486098dbd80d70d26d3d4f2d96c1ad.png)
【选择要恢复的快照节点, 然后点击转到按钮即可】
![](https://i-blog.csdnimg.cn/blog_migrate/6d528ead8cf67e9763876ae22756326d.png)
此时重新打开虚拟机, 就会发现, 虚拟机恢复到拍摄快照最初始的状态了.....
二、Apache ZooKeeper
一、Zookeeper基本知识
1. ZooKeeper概述
Zookeeper是一个分布式协调服务的开源框架。主要用来解决分布式集群中应用系统的一致性问题。
ZooKeeper本质上是一个小文件存储系统。提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理。从而用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。
2. ZooKeeper特性
- 全局数据一致:集群中每个服务器保存一份相同的数据副本,client无论连接到哪个服务器,展示的数据都是一致的,这是最重要的特征;
- 可靠性:如果消息被其中一台服务器接受,那么将被所有的服务器接受。
- 顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
- 数据更新原子性:一次数据更新要么成功(半数以上节点成功),要么失败,不存在中间状态;
- 实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。
3. ZooKeeper集群角色
![](https://i-blog.csdnimg.cn/blog_migrate/f6e0bf99c2c6885a3bed6dd21b39155f.png)
Leader:
Zookeeper集群工作的核心
事务请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性;
集群内部各个服务器的调度者。
对于create,setData,delete等有写操作的请求,则需要统一转发给leader处理,leader需要决定编号、执行操作,这个过程称为一个事务。
Follower:
处理客户端非事务(读操作)请求,转发事务请求给Leader;
参与集群Leader选举投票。
此外,针对访问量比较大的zookeeper集群,还可新增观察者角色。
Observer:
观察者角色,观察Zookeeper集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进行独立处理,对于事务请求,则会转发给Leader服务器进行处理。
不会参与任何形式的投票只提供非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
二、ZooKeeper集群搭建
Zookeeper集群搭建指的是ZooKeeper分布式模式安装。通常由2n+1台server组成。这是因为为了保证Leader选举(基于Paxos算法的实现)能过得到多数的支持,所以ZooKeeper集群的数量一般为奇数。
Zookeeper运行需要java环境,所以需要提前安装jdk。对于安装leader+follower模式的集群,大致过程如下:
l 配置主机名称到IP地址映射配置
l 修改ZooKeeper配置文件
l 远程复制分发安装文件
l 设置myid
l 启动ZooKeeper集群
如果要想使用Observer模式,可在对应节点的配置文件添加如下配置:
peerType=observer
其次,必须在配置文件指定哪些节点被指定为Observer,如:
server.1:node1:2181:3181:observer
这里,我们安装的是leader+follower模式
服务器IP | 主机名 | myid的值 |
192.168.88.161 | node1 | 1 |
192.168.88.162 | node2 | 2 |
192.168.88.163 | node3 | 3 |
1. 第一步:下载zookeeeper的压缩包,下载网址如下
http://archive.apache.org/dist/zookeeper/
我们在这个网址下载我们使用的zk版本为3.4.6
下载完成之后,上传到我们的linux的/export/software路径下准备进行安装
2. 第二步:解压
在node1主机上,解压zookeeper的压缩包到/export/server路径下去,然后准备进行安装
cd /export/software tar -zxvf zookeeper-3.4.6.tar.gz -C /export/servers/ |
3. 第三步:修改配置文件
在node1主机上,修改配置文件
cd /export/server/zookeeper-3.4.6/conf/ cp zoo_sample.cfg zoo.cfg mkdir -p /export/servers/zookeeper-3.4.6/zkdatas/ vim zoo.cfg |
修改以下内容
#Zookeeper的数据存放目录 dataDir=/export/servers/zookeeper-3.4.6/zkdatas # 保留多少个快照 autopurge.snapRetainCount=3 # 日志多少小时清理一次 autopurge.purgeInterval=1 # 集群中服务器地址 server.1=node1:2888:3888 server.2=node2:2888:3888 server.3=node3:2888:3888 |
4. 第四步:添加myid配置
在node1主机的/export/server/zookeeper-3.4.6/zkdatas/这个路径下创建一个文件,文件名为myid ,文件内容为1
echo 1 > /export/servers/zookeeper-3.4.6/zkdatas/myid |
5. 第五步:安装包分发并修改myid的值
在node1主机上,将安装包分发到其他机器
第一台机器上面执行以下两个命令
scp -r /export/servers/zookeeper-3.4.6/ node2:/export/servers/ scp -r /export/servers/zookeeper-3.4.6/ node3:/export/servers/ |
第二台机器上修改myid的值为2
echo 2 > /export/servers/zookeeper-3.4.6/zkdatas/myid |
第三台机器上修改myid的值为3
echo 3 > /export/servers/zookeeper-3.4.6/zkdatas/myid |
6. 第六步:三台机器启动zookeeper服务
三台机器分别启动zookeeper服务
这个命令三台机器都要执行
/export/servers/zookeeper-3.4.6/bin/zkServer.sh start |
三台主机分别查看启动状态
/export/servers/zookeeper-3.4.6/bin/zkServer.sh status |
三、Zookeeper数据模型
![](https://i-blog.csdnimg.cn/blog_migrate/a57108d59f73edd41f1504d616f5ecd0.png)
图中的每个节点称为一个Znode。 每个Znode由3部分组成:
ZooKeeper的数据模型,在结构上和标准文件系统的非常相似,拥有一个层次的命名空间,都是采用树形层次结构,ZooKeeper树中的每个节点被称为—Znode。和文件系统的目录树一样,ZooKeeper树中的每个节点可以拥有子节点。但也有不同之处:
- Znode兼具文件和目录两种特点,既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分,并可以具有子Znode。用户对Znode具有增、删、改、查等操作(权限允许的情况下)。
- Znode具有原子性操作,读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。另外,每一个节点都拥有自己的ACL(访问控制列表),这个列表规定了用户的权限,即限定了特定用户对目标节点可以执行的操作。
- Znode存储数据大小有限制,ZooKeeper虽然可以关联一些数据,但并没有被设计为常规的数据库或者大数据存储,相反的是,它用来管理调度数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等等。这些数据的共同特性就是它们都是很小的数据,通常以KB为大小单位。ZooKeeper的服务器和客户端都被设计为严格检查并限制每个Znode的数据大小至多1M,当时常规使用中应该远小于此值。
- Znode通过路径引用,如同Unix中的文件路径。路径必须是绝对的,因此他们必须由斜杠字符来开头。除此以外,他们必须是唯一的,也就是说每一个路径只有一个表示,因此这些路径不能改变。在ZooKeeper中,路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息。
① stat:此为状态信息, 描述该Znode的版本, 权限等信息
② data:与该Znode关联的数据
③ children:该Znode下的子节点
四、Zookeeper节点类型
Znode有两种,分别为临时节点和永久节点。
节点的类型在创建时即被确定,并且不能改变。
临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,当然可以也可以手动删除。临时节点不允许拥有子节点。 永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。
Znode还有一个序列化的特性,如果创建的时候指定的话,该Znode的名字后面会自动追加一个不断增加的序列号。序列号对于此节点的父节点来说是唯一的,这样便会记录每个子节点创建的先后顺序。它的格式为“%10d”(10位数字,没有数值的数位用0补充,例如“0000000001”)。
![](https://i-blog.csdnimg.cn/blog_migrate/6104c8c4548e630407a227b3714581a1.png)
这样便会存在四种类型的Znode节点,分别对应:
PERSISTENT:永久节点
EPHEMERAL:临时节点
PERSISTENT_SEQUENTIAL:永久节点、序列化
EPHEMERAL_SEQUENTIAL:临时节点、序列化
五、ZooKeeper的shell操作
1. 客户端连接
运行 zkCli.sh –server ip 进入命令行工具。
bin/zkCli.sh -server node01:2181 |
2. shell基本操作
l 1) 创建节点:
n 格式: create [-s][-e] path data acl
u 其中,-s 或-e 分别指定节点特性,顺序或临时节点,若不指定,则表示持 久节点;acl 用来进行权限控制。
n 【创建顺序节点】: create -s /test 123
n 【创建临时节点】 create -e /test-temp 123temp
n 【创建持久节点】 create /test-p 123p
l 2) 读取节点
n 与读取相关的命令有 ls 命令和 get 命令,ls 命令可以列出 Zookeeper 指定节点下的所有子节点,只能查看指定节点下的第一级的所有子节点;get 命令可以获取 Zookeeper 指定节点的数据内容和属性信息。
n 格式:
u ls path [watch]
u get path [watch]
u ls2 path [watch]
![](https://i-blog.csdnimg.cn/blog_migrate/b58de7ccf1dcfbc3717c72ca926e845d.gif)
dataVersion:数据版本号,每次对节点进行set操作,dataVersion的值都会增加1(即使设置的是相同的数据),可有效避免了数据更新时出现的先后顺序问题。
cversion :子节点的版本号。当znode的子节点有变化时,cversion 的值就会增加1。
cZxid :Znode创建的事务id。
mZxid :Znode被修改的事务id,即每次对znode的修改都会更新mZxid。
对于zk来说,每次的变化都会产生一个唯一的事务id,zxid(ZooKeeper Transaction Id)。通过zxid,可以确定更新操作的先后顺序。例如,如果zxid1小于zxid2,说明zxid1操作先于zxid2发生,zxid对于整个(全局)zk都是唯一的,即使操作的是不同的znode。
ctime:节点创建时的时间戳.
mtime:节点最新一次更新发生时的时间戳.
ephemeralOwner:如果该节点为临时节点, ephemeralOwner值表示与该节点绑定的session id. 如果不是, ephemeralOwner值为0.
在client和server通信之前,首先需要建立连接,该连接称为session。连接建立后,如果发生连接超时、授权失败,或者显式关闭连接,连接便处于CLOSED状态, 此时session结束。
l 3) 更新索引
n 格式: set path data [version]
u data 就是要更新的新内容,version 表示数据版本
![](https://i-blog.csdnimg.cn/blog_migrate/6c186a01795dfa50674687a2604f3d62.png)
l 4) 删除节点
n 格式: delete path [version]
u 若删除节点存在子节点,那么无法删除该节点,必须先删除子节点,再删除父节点
u rmr path: 可以递归删除节点。
l 5) 对节点进行限制: quota
n 格式1: setquota -n|-b val path
u n:表示子节点的最大个数
u b:表示数据值的最大长度
u val:子节点最大个数或数据值的最大长度
u path:节点路径
![](https://i-blog.csdnimg.cn/blog_migrate/15f6e10f12cf15f899c28a56bd8a942d.png)
n 格式2: listquota path : 列出指定节点的 quota
![](https://i-blog.csdnimg.cn/blog_migrate/5ce1df2595cf66711da8f2863459822e.png)
子节点个数为 2,数据长度-1 表示没限制
注意: 在实际操作的时候, 虽然设置了最大的节点数后,依然可以在整个节点下添加多个子节点, 只是会在zookeeper中的日志文件中记录一下警告信息
![](https://i-blog.csdnimg.cn/blog_migrate/0e6e92f1cffe0ad106bbdd3d8a2ebabf.png)
n 格式3: delquota [-n|-b] path : 删除 quota
l 6) 其他命令:
n history: 列出命令历史
![](https://i-blog.csdnimg.cn/blog_migrate/c4dc2639b24b7935d1359ffcafd0fac5.png)
n redo:该命令可以重新执行指定命令编号的历史命令,命令编号可以通过
3. ZooKeeper Watcher(监听机制)
ZooKeeper提供了分布式数据发布/订阅功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理。
ZooKeeper中,引入了Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watcher监听,当服务端的一些事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。
触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等。
总的来说可以概括Watcher为以下三个过程:客户端向服务端注册Watcher、服务端事件发生触发Watcher、客户端回调Watcher得到触发事件情况
1) Watch机制特点
一次性触发
事件发生触发监听,一个watcher event就会被发送到设置监听的客户端,这种效果是一次性的,后续再次发生同样的事件,不会再次触发。
事件封装
ZooKeeper使用WatchedEvent对象来封装服务端事件并传递。
WatchedEvent包含了每一个事件的三个基本属性:
通知状态(keeperState),事件类型(EventType)和节点路径(path)
event异步发送
watcher的通知事件从服务端发送到客户端是异步的。
先注册再触发
Zookeeper中的watch机制,必须客户端先去服务端注册监听,这样事件发送才会触发监听,通知给客户端。
2) 通知状态和事件类型
同一个事件类型在不同的通知状态中代表的含义有所不同,下表列举了常见的通知状态和事件类型。
事件封装: Watcher 得到的事件是被封装过的, 包括三个内容 keeperState, eventType, path
KeeperState | EventType | 触发条件 | 说明 |
None | 连接成功 | ||
SyncConnected | NodeCreated | Znode被创建 | 此时处于连接状态 |
SyncConnected | NodeDeleted | Znode被删除 | 此时处于连接状态 |
SyncConnected | NodeDataChanged | Znode数据被改变 | 此时处于连接状态 |
SyncConnected | NodeChildChanged | Znode的子Znode数据被改变 | 此时处于连接状态 |
Disconnected | None | 客户端和服务端断开连接 | 此时客户端和服务器处于断开连接状态 |
Expired | None | 会话超时 | 会收到一个SessionExpiredExceptio |
AuthFailed | None | 权限验证失败 | 会收到一个AuthFailedException |
其中连接状态事件(type=None, path=null)不需要客户端注册,客户端只要有需要直接处理就行了。
3) Shell 客户端设置watcher
设置节点数据变动监听:
![](https://i-blog.csdnimg.cn/blog_migrate/b2e97117423180919802aa09cd75934a.png)
通过另一个客户端更改节点数据:
![](https://i-blog.csdnimg.cn/blog_migrate/2f71a5755ba160d02260472e053fdd57.gif)
此时设置监听的节点收到通知:
![](https://i-blog.csdnimg.cn/blog_migrate/6abe8b5170a47135b3d8dc95752a974c.gif)
六、ZooKeeper Java API操作
这里操作Zookeeper的JavaAPI使用的是一套zookeeper客户端框架 Curator ,解决了很多Zookeeper客户端非常底层的细节开发工作 。
Curator包含了几个包:
curator-framework:对zookeeper的底层api的一些封装
curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器等
Maven依赖(使用curator的版本:2.12.0,对应Zookeeper的版本为:3.4.x,如果跨版本会有兼容性问题,很有可能导致节点操作失败):
1. 引入maven坐标
<dependencies> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>com.google.collections</groupId> <artifactId>google-collections</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> </dependencies> <build> <plugins> <!-- java编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> |
2. 节点的操作
/* 创建节点 */ @Test public void createZnode() throws Exception { //1:定制一个重试策略 /* param1: 重试的间隔时间 param2:重试的最大次数 */ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1); //2:获取一个客户端对象 /* param1:要连接的Zookeeper服务器列表 param2:会话的超时时间 param3:链接超时时间 param4:重试策略 */ String connectionStr = "192.168.88.161:2181,192.168.88.162:2181,192.168.88.163:2181"; CuratorFramework client = CuratorFrameworkFactory.newClient(connectionStr, 8000, 8000, retryPolicy); //3:开启客户端 client.start(); //4:创建节点 /* 节点类型: CreateMode.PERSISTENT:永久节点 CreateMode.PERSISTENT_SEQUENTIAL:永久序列化节点 CreateMode.EPHEMERAL:临时节点 CreateMode.EPHEMERAL_SEQUENTIAL:临时序列化节点 /hello2 :节点路径 world :节点数据 */ client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello2","world".getBytes()); //5:关闭客户端 client.close(); } |
七、ZooKeeper选举机制
zookeeper默认的算法是FastLeaderElection,采用投票数大于半数则胜出的逻辑。
1. 概念
服务器ID
比如有三台服务器,编号分别是1,2,3。
编号越大在选择算法中的权重越大。
选举状态
LOOKING,竞选状态。
FOLLOWING,随从状态,同步leader状态,参与投票。
OBSERVING,观察状态,同步leader状态,不参与投票。
LEADING,领导者状态。
数据ID
服务器中存放的最新数据version。
值越大说明数据越新,在选举算法中数据越新权重越大。
逻辑时钟
也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。
2. 全新集群选举
假设目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
l 服务器1启动自己,给投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking。
l 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
l 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟。
l 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟。
l 服务器5启动,后面的逻辑同服务器4成为小弟。
3. 非全新集群选举
对于运行正常的zookeeper集群,中途有机器down掉,需要重新选举时,选举过程就需要加入数据ID、服务器ID和逻辑时钟。
数据ID:数据新的version就大,数据每次更新都会更新version。
服务器ID:就是我们配置的myid中的值,每个机器一个。
逻辑时钟:这个值从0开始递增,每次选举对应一个值。 如果在同一次选举中,这个值是一致的。
这样选举的标准就变成:
1、逻辑时钟小的选举结果被忽略,重新投票;
2、统一逻辑时钟后,数据id大的胜出;
3、数据id相同的情况下,服务器id大的胜出;
根据这个规则选出leader。