02-Zookeeper介绍及安装

1 Zookeeper介绍

ZooKeeper是为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务: 分布式锁服务。分布式应用可以基于它实现更高级的服务,实现诸如同步服务、配置维护和集群管理或者命名的服务。
Zookeeper服务自身组成一个集群,2n+1个(奇数)服务允许n个失效,集群内一半以上机器可用,Zookeeper就可用。
 

1.1 数据模型

1)ZooKeeper本质上是一个分布式的小文件存储系统;
2)Zookeeper表现为一个分层的文件系统目录树结构(不同于文件系统的是,节点可以有自己的数据,而文件系统中的目录节点只有子节点), 每个节点可以存少量的数据(1M左右)。
3)每个节点称做一个ZNode。 每个ZNode都可以通过其路径唯一标识。
4)ZooKeeper中的每个节点存储的数据要被原子性的操作。也就是说   读操作将获取该节点相关的所有数据,写操作也将替换掉节点的所有数据。
5)在zookeeper创建顺序节点(create -s ),节点路径后加编号,这个计数对于此节点的父节点来说是唯一的。
        /app/
              /s100000000001
              /s100000000002
6)ZooKeeper中的节点有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。
① 临时节点:在客户端用 create -e创建,该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然可以也可以手动删除。每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。
② 永久节点:在客户端用create 创建,该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。
 
7) 客户端可以给节点设置watch,我们称之为监视器。当节点状态发生改变时(Znode的增、删、改)将会触发watch所对应的操作。当watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知。
 
zookeeper 是如何进行高可用协调的?
 

1.2 主要角色

领导者(leader),负责进行投票的发起和决议,更新系统状态(数据同步),发送心跳。
学习者(learner),包括跟随者(follower)和观察者(observer)。
         跟随者(follower),用于接受客户端请求、向客户端返回结果,在选主过程中参与投票。
         观察者(Observer),可以接受客户端请求,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了 扩展系统,提高读取速度。
 
 
1)leader失效后会在follower中重新选举新的leader
2)每个follower都和leader有连接,接受leader的数据更新操作
3)客户端可以连接到每个server,每个server的数据完全相同
4)每个节点的服务Server,记录事务日志和快照到持久存储
 
 

1.3 工作原理

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。
Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。
恢复模式:
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,恢复模式不接受客户端请求,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
广播模式:
一旦Leader已经和多数的Follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。这时候当一个Server加入ZooKeeper服务中,它会在恢复模式下启动,发现Leader,并和Leader进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper的广播状态一直到Leader崩溃了或者Leader失去了大部分的Followers支持。
 
1)Zookeeper节点数据操作流程
写操作
1)在Client向Follwer 或 Observer 发出一个写的请求;
2)Follwer 或 Observer 把请求发送给Leader;
3)Leader接收到以后向所有follower发起提案;
4)Follwer收到提案后执行写操作,然后把操作结果发送给Leader;
5)当多数follower返回提案结果后,leader会commit该提议,通知其他Follower 和 Observer 同步信息;
6)Follwer 或Observer把请求结果返回给Client。
 
读操作
1)在Client向Follwer 或 Observer 发出一个读的请求;
2)Follwer 或 Observer 把请求结果返回给Client;
 

1.4 主要特点

最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的特性;
可靠性:具有简单、健壮、良好的性能,如果消息被某一台服务器接受,那么它将被所有的服务器接受;
实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。 但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口;
等待无关(wait-free):慢的或者失效的client,不得干预快速的client的请求,使得每个client都能有效的等待;
原子性:更新只能成功或者失败,没有中间状态;
顺序性:按照客户端发送请求的顺序更新数据;
 

1.5 应用场景

数据发布与订阅
发布与订阅即所谓的 配置管理,顾名思义就是将数据发布到ZK节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。
应用配置集中到节点上,应用启动时主动获取,并在节点上注册一个watcher,每次配置更新都会通知到应用。
 
命名空间服务
分布式命名服务,创建一个节点后, 节点的路径就是全局唯一的,可以作为全局名称使用。
 
分布式通知/协调
不同的系统都监听同一个节点,一旦有了更新,另一个系统能够收到通知。
 
分布式锁
Zookeeper能保证数据的强一致性,用户任何时候都可以相信集群中每个节点的数据都是相同的。
锁的两种体现方式:
1)保持独占
一个用户创建一个节点作为锁,另一个用户检测该节点,如果存在,代表别的用户已经锁住,如果不存在,则可以创建一个节点,代表拥有一个锁。
2)控制时序
有一个节点作为父节点,其底下是带有编号的子节点,所有要获取锁的用户,需要在父节点下创建带有编号的子节点,编号最小的会持有锁;当最小编号的节点被删除后,锁被释放,再重新找最小编号的节点来持有锁,这样保证了全局有序。
 
集群管理
每个加入集群的机器都创建一个节点,写入自己的状态。监控父节点的用户会收到通知,进行相应的处理。离开时删除节点,监控父节点的用户同样会收到通知。
 

2 Zookeeper安装

2.1 规划  

nn1、nn2、s1 。
其中:一个是leader,剩余的是Follower
 

2.2 zookeeper 批量分发脚本安装

1)zookeeper 为什么是奇数
zookeeper有这样一个特性: 集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。也就是说如果有2个zookeeper,那么只要有1个挂了zookeeper就不能用了,因为1没有过半,所以2个zookeeper的死亡容忍度为0;同理,要是有3个zookeeper,一个死了,还剩下2个正常的,过半了,所以3个zookeeper的容忍度为1。
 
2)zookeeper 多机操作脚本
用之前的多机脚本拷贝一套zookeeper 多机操作脚本,然后修改成 zookeeper 用的多机操作脚本。
拷贝脚本
 
<wiz_code_mirror>
 
 
 
 
 
 
 
cp ips ips_zookeeper
vim ips_zookeeper  # 将机器名称写三个
cp scp_all.sh scp_all_zookeeper.sh
cp ssh_all.sh ssh_all_zookeeper.sh
cp ssh_root.sh ssh_root_zookeeper.sh
 
 
修改脚本
 
<wiz_code_mirror>
 
 
 
 
 
 
 
vim scp_all_zookeeper.sh
vim ssh_all_zookeeper.sh
vim ssh_root_zookeeper.sh
 
 
 
 
 
3)把zookeeper的安装包分发到每个zookeeper机器上
<wiz_code_mirror>
 
 
 
 
 
 
 
#将zookeeper的安装包【zookeeper-3.4.8.tar.gz】上传到/home/hadoop/up 目录下
rz
#将安装包分发到每个zookeeper 机器的 /tmp/ 目录下
./scp_all_zookeeper.sh ~/up/zookeeper-3.4.8.tar.gz /tmp/
#查看是否分发成功
./ssh_all_zookeeper.sh "ls /tmp | grep zo*"
 
 
 
4)在所有机器上把zookeeper的tar包解压到/usr/local目录下
<wiz_code_mirror>
 
 
 
 
 
 
 
#将/tmp/zookeeper-3.4.8.tar.gz 解压到 /usr/local/ 目录
./ssh_root_zookeeper.sh tar -xzf /tmp/zookeeper-3.4.8.tar.gz -C /usr/local/
#查看是否解压成功
./ssh_root_zookeeper.sh "ls -l /usr/local/ | grep zoo"
 
 
 
5)批量把/usr/local目录下的zookeeper-3.4.8文件所有者修改成hadoop用户,并修改zookeeper-3.4.8文件目录权限为770
<wiz_code_mirror>
 
 
 
 
 
 
 
#修改每台机器的/usr/local/zookeeper-3.4.8,所属用户为hadoop
./ssh_root_zookeeper.sh chown -R hadoop:hadoop /usr/local/zookeeper-3.4.8
#修改每台机器的/usr/local/zookeeper-3.4.8的权限为770
./ssh_root_zookeeper.sh chmod -R 770 /usr/local/zookeeper-3.4.8
#查看是否修改成功
./ssh_root_zookeeper.sh "ls -l /usr/local | grep zookeeper-3.4.8"
 
 
 
6)在/usr/local目录下批量创建zookeeper-3.4.8的软链接
<wiz_code_mirror>
 
 
 
 
 
 
 
#在每台机器上给/usr/local/zookeeper-3.4.8创建zookeeper软链接
./ssh_root_zookeeper.sh ln -s /usr/local/zookeeper-3.4.8/ /usr/local/zookeeper 
#查看每台机器的软连接是否创建成功
./ssh_all_zookeeper.sh "ls -l /usr/local/ | grep zookeeper" 
 
 
 
7)修改/usr/local/zookeeper软链接所属用户组(可做可不做)
<wiz_code_mirror>
 
 
 
 
 
 
 
#修改每台机器软连接所属用户组
./ssh_root_zookeeper.sh chown -h hadoop:hadoop /usr/local/zookeeper
 
 
 

2.3 修改每个机器上的zookeeper 配置

1)zookeeper脚本所在目录——bin目录
 
2)zookeeper配置文件目录——conf目录
 
常用配置文件 conf/zoo.cfg,常用配置说明及示例(将zookeeper_simple.cfg  更改为 zoo.cfg)
 
3)备份zookeeper的conf 目录
<wiz_code_mirror>
 
 
 
 
 
 
 
#备份原来的配置目录
./ssh_all_zookeeper.sh cp -a /usr/local/zookeeper/conf /usr/local/zookeeper/conf_back
 
 
 
4)删除原有zoo_sample.cfg 配置文件,上传zoo.cfg 配置文件,并批量拷贝到每台机器
 
<wiz_code_mirror>
 
 
 
 
 
 
 
# 改名 zoo_sample.cfg 为 zoo.cfg (在 nn1 上)
mv zoo_sample.cfg zoo.cfg
# 修改为如下配置
vim zoo.cfg
#将zoo.cfg 配置文件批量拷贝到每台机器上
./scp_all_zookeeper.sh ~/up/zoo.cfg /usr/local/zookeeper/conf/
#检查是否拷贝成功
./ssh_root_zookeeper.sh ls /usr/local/zookeeper/conf/zoo.cfg 
#批量删除zoo_sample.cfg 配置文件
./ssh_root_zookeeper.sh rm -f /usr/local/zookeeper/conf/zoo_sample.cfg
#批量检查是否删除成功
./ssh_root_zookeeper.sh ls /usr/local/zookeeper/conf/
 
 
zoo.cfg 配置文件内容:
2181: 供外界访问
2888: ledal 和 foler 之间通信使用
3888: 投票用 
 
5)修改输出日志配置文件所在目录
修改zookeeper/bin/zkEnv.sh 脚本,在脚本中给 ZOO_LOG_DIR 设置日志所在目录
在最上面添加就好
 
<wiz_code_mirror>
 
 
 
 
 
 
 
#拷贝zkEnv.sh到每台机器的zookeeper的bin目录下
./scp_all_zookeeper.sh /usr/local/zookeeper/bin/zkEnv.sh /usr/local/zookeeper/bin/ 
# 检查下(查看文件大小)
./ssh_all_zookeeper.sh 'ls -l /usr/local/zookeeper/bin | grep zkEnv.sh'
 
 
 
6)在每个机器上创建/data目录,并把data目录所有者修改为hadoop用户
<wiz_code_mirror>
 
 
 
 
 
 
 
#5个机器一起创建 /data目录,因为以后安装hadoop的时候也使用
./ssh_root.sh mkdir /data 
#把每个机器上的/data目录所有者修改为hadoop用户
./ssh_root.sh chown hadoop:hadoop /data 
#批量验证
./ssh_root.sh "ls -l / | grep data"
 
 
 
7)在新建的/data目录下生成myid文件(这个只能手动,不能使用批量脚本)
<wiz_code_mirror>
 
 
 
 
 
 
 
#在每个机器的/data目录下创建myid文件
./ssh_all_zookeeper.sh touch /data/myid 
 
 
每台机器都需要单独执行
 
<wiz_code_mirror>
 
 
 
 
 
 
 
# 第一台:
echo "1" > /data/myid 
# 第二台:
echo "2" > /data/myid 
# 第三台:
echo "3" > /data/myid
# 查看方式一:
cat /data/myid
# 查看方式二:
./ssh_all_zookeeper.sh cat /data/myid
 
 
补充:
正常服务器,data目录是挂载到实体硬盘的
虚拟机的data目录是找不到挂载点的,所以他就是放在"/"目录下的一个文件夹
 

2.4 给5个机器设置好环境变量

在root用户上
env 查看当前shell环境下已有环境变量
/etc/profile整个系统的
~/.bash_profile当前用户的
加载顺序是先加载系统,再加载自己的
 
配置hadoop软件生态系统所使用的环境变量
<wiz_code_mirror>
 
 
 
 
 
 
 
export JAVA_HOME=/usr/java/jdk1.8.0_144
#/usr/bin/java 连接到 /usr/java/jdk1.8.0_144,可用/usr/bin/java 配置JAVA_HOME
#set Hadoop Path
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_COMMON_HOME=${HADOOP_HOME}
export HADOOP_HDFS_HOME=${HADOOP_HOME}
export HADOOP_MAPRED_HOME=${HADOOP_HOME}
export HADOOP_YARN_HOME=${HADOOP_HOME}
export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop
export HDFS_CONF_DIR=${HADOOP_HOME}/etc/hadoop
export YARN_CONF_DIR=${HADOOP_HOME}/etc/hadoop
export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native:/usr/lib64
export HBASE_HOME=/usr/local/hbase
export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HBASE_HOME/bin:$HIVE_HOME/bin:/usr/local/zookeeper/bin
 
 
 
追加到/etc/profile文件的底部,并且确认保存,注意使用root用户操作,再切换一个用户或者退出就会重新加载刚才的设置,再加env验证一下是否配置正确
<wiz_code_mirror>
 
 
 
 
 
 
 
#用root用户登录,拷贝/etc/profile 文件到 ~hadoop/up
su - root
# 修改下(追加以上内容)
vim /etc/profile
cp /etc/profile ~/hadoop/up
#将~hadoop/up/profile 拷贝到其他机器 /tmp 目录下
./scp_all.sh ~/up/profile /tmp/
#批量验证
./ssh_all.sh ls -l /tmp/ 
#批量拷贝到/etc/profile
./ssh_root.sh mv /tmp/profile /etc/
#批量验证
./ssh_root.sh tail /etc/profile
#批量source使配置生效
./ssh_root.sh source /etc/profile
 
 
 
查看每个机器的JAVA 版本
<wiz_code_mirror>
 
 
 
 
 
 
 
./ssh_root.sh java -version 
 
 
 
 

2.5 在每个机器上启动zookeeper服务并查看启动结果

1)nohup command & 命令
当执行nohup command & 命令时,即使退出账户、终端关闭,程序依然运行,nohup   就是不挂起的意思( n ohang up); (后台运行)
它把标准输出(STDOUT)和标准错误(STDERR)结果输出到nohup.txt文件这个看似很方便,但是当输出很大的时候,nohup.txt文件会非常大,或者多个后台命令的时候大家都会输出到nohup.txt文件,不利于查找结果和调试程序。
可以利用输入输出重定向将标准输出和错误输出重定向到指定文件或 /dev/null,这是一个无底洞,任何东西都可以定向到这里,但是却无法打开。
<wiz_code_mirror>
 
 
 
 
 
 
 
#一般很大的stdou 和stderr 当你不关心的时候可以利用stdout 和stderr 定向到这里
./command.sh >/dev/null 2>&1 &
 
 
当一个脚本f1.sh调用另一个脚本f2.sh时,如果不加nohup & , 需要等到f2.sh 执行完(阻塞执行),再执行。
如果加了nohup &,不阻塞,继续执行f1.sh 剩下的部分。
 
/usr/local/zookeeper/bin/zkServer.sh start
 
org.apache.zookeeper.server.quorum.QuorumPeerMain
执行shell脚本,在脚本中调用某个类的main()来执行。
 
2)在每个机器上启动zookeeper服务
<wiz_code_mirror>
 
 
 
 
 
 
 
#批量启动
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh start
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh status
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh stop
#批量查看java进程用jps
./ssh_all_zookeeper.sh jps
#或者用ps 查看
ps aux | grep zookeeper 或  ps -ef|grep zookeeper
 
 
开启zookeeper
查看状态 status
 
 
3)查看ZK输出日志
<wiz_code_mirror>
 
 
 
 
 
 
 
#日志输出文件
cat /data/zookeeper.out
 
 
由于ZooKeeper集群启动的时候,每个结点都试图去连接集群中的其它结点,先启动的肯定连不上后面还没启动的,所以上面日志前面部分的异常是可以忽略的。通过后面部分可以看到,集群在选出一个Leader后,最后稳定了。
通过  JPS  查看进程ID,进入进程ID文件,再到FD目录就能查看到当前进程所使用的管道信息
cd /proc/id/fd
 
zookeeper_server.pid 存当前ZK服务的进程ID的
 
 

3 zookeeper使用

 

 

 

3.1 ZooKeeper服务命令

  • 启动ZK服务: sh bin/zkServer.sh start
  • 查看ZK服务状态: sh bin/zkServer.sh status
  • 停止ZK服务: sh bin/zkServer.sh stop
  • 重启ZK服务: sh bin/zkServer.sh restart
<wiz_code_mirror>
 
 
 
 
 
 
 
#查看每个机器ZK运行的状态
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh status
#整体停止服务
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh stop 
 
 
查看状态结果:
 

3.2 zk客户端命令

显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
删除文件: delete /zk 将刚才创建的 znode 删除
退出客户端: quit
帮助命令: help
<wiz_code_mirror>
 
 
 
 
 
 
 
#启动zkclient,并连接zookeeper集群
/usr/local/zookeeper/bin/zkCli.sh -server nn1.hadoop:2181,nn2.hadoop:2181,s1.hadoop:2181
 
 
cZxid:创建节点时的事务id
pZxid:子节点列表最后一次被修改的事务id
cversion:节点版本号
dataCersion:数据版本号
aclVerson:acl权限版本号
 
如何查看是临时节点还是永久节点?
        当get 节点信息时,其中有一个字段是ephemeralOwner意思是这个节点的临时拥有者。
        当ephemeralOwner 值不为0时,表明这个节点是临时节点,值为会话id。
        当ephemeralOwner 值为0时,表明这个节点是持久节点。.
 

猜你喜欢

转载自www.cnblogs.com/zss0520/p/10802155.html