1 ZooKeeper概述
ZooKeeper直译就是动物园管理员, 它是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)等的管理员(这些都是Apache软件基金组织旗下大数据方面的技术框架), Apache Hbase和Apache Solr的分布式集群都用到了ZooKeeper.
百度百科中的说明:
ZooKeeper是一个高可用、分布式的程序协调服务, 是Google的Chubby一个开源的实现, 是Hadoop和Hbase的重要组件. 它是一个为分布式应用提供一致性服务的软件, 提供的功能包括: 配置维护、域名服务、分布式同步、组服务等.
ZooKeeper的目标就是封装好复杂易出错的关键服务, 将简单易用的接口和性能高效、功能稳定的系统提供给用户.
- ZooKeeper的基本运转流程:
(1) 选举Leader;
(2) 同步数据;
(3) 选举Leader过程中算法有很多, 但要达到的选举标准是一致的;
(4) Leader要具有最高的执行ID, 类似root权限;
(5) 集群中大多数的机器得到响应并接受选出的Leader.
2 ZooKeeper的功能
2.1 配置管理
项目开发中大多会涉及到各种配置信息, 比如JDBC的连接信息等. 一般将这些信息配置到特定的文件中, 在代码中引入相关配置文件即可. — 这是单服务器应用中常用的做法. 当应用很大、配置文件很多, 尤其是在分布式项目中, 多台服务器的配置需要保持一致, 而如果配置信息会被频繁地修改, 这个时候还使用配置文件就不是个好主意了 — 你总不能手动一个一个去修改吧, 且不说太多的重复性劳动, 手动修改出错的可能性更高, 后期维护成本太大.
这种情况下往往需要寻找一种集中管理配置的方法 — 在这个集中的地方修改了配置, 所有对该配置有依赖的服务都可以获得变更. 需要考虑的是, 由于多台服务器上的项目都依赖了这个配置, 为了应用的可靠运行, 需要这个集中提供配置服务的应用具备非常高的可靠性.
基于上述分析, 我们可以通过集群来提供配置服务, 保证系统的可靠性. 此时遗留的问题是, 如何保证配置在集群中的一致性呢?
为了提供这种一致性, 牛人们提出了一致性协议, 实现此协议的服务就有ZooKeeper —它使用Zab这种一致性协议来保证一致性.
应用场景:
○ HBase中, 客户端就是连接一个ZooKeeper, 它获得HBase集群的必要配置信息, 然后才可以进一步操作.
○ 开源消息队列Kafka中, 使用ZooKeeper来维护broker的信息.
○ Alibaba开源的SOA框架Dubbo中广泛使用ZooKeeper管理配置信息, 实现服务治理.
2.2 命名服务
场景: 为了通过网络访问一个系统, 我们需要知道对方的IP地址, 但由于IP地址是一串数字, 难以记忆, 对用户并不友好. 这时人们想出通过域名来访问指定的IP地址.
但计算机并不能识别域名. 为了解决这一问题, 设计者们提出了在每台电脑中都存储一份”域名到IP地址的映射”的方案. 问题又来了, 如果域名对应的IP地址发生了变化, 又该如何映射呢? 牛人们设计了DNS(Domain Name System, 域名系统). 我们只需要先访问一个众所周知的(known)的节点, DNS通过该节点告诉我们当前访问的域名对应的IP地址是什么. 即DNS提供统一的访问接口.
在应用开发中也会存在这类问题, 特别是应用中存在大量服务时, 如果我们将服务的地址保存在本地, 其他用户是不好获取这些地址并访问的. 但是如果我们为用户提供统一的入口, 在本地对各种用户请求作相应的映射处理, 即可解决此类问题.
2.3 分布式锁
ZooKeeper是一个分布式协调服务, 我们可以利用ZooKeeper来协调多个分布式进程之间的活动. 比如在一个分布式环境中, 为提高系统的可靠性, 集群中的每台服务器都部署了相同的服务. 这些相同的服务都要执行相同的任务, 为了保证数据的一致性, 集群之间就要互相协调, 常规的编程方案解决协调问题是非常复杂繁琐的.
通常的做法是: 使用分布式锁, 在某个时刻只有一个服务在工作, 当这台服务出了问题锁就立即释放, 并 fail over 到其他服务. 这种设计被称作叫 Leader Election (leader选举). 比如 HBase 的 Master 就采用了这种机制.
注意: 分布式锁与进程锁是有区别的, 使用时要更加谨慎.
2.4 集群管理
在分布式集群应用中, 存在诸如软硬件故障、断电、网络等问题, 存在节点出入现象, 即新节点加入集群, 老节点退出集群. 出现这种情况时, 集群中其他节点要能感知到这种变化, 然后根据这种变化做出对应的决策.
应用场景:
○ 在分布式存储系统中, 有一个中央控制节点负责存储的分配, 有新的存储节点加入进来时, 需要根据集群状态来动态分配存储节点, 这需要实时感知集群的状态.
○ 在分布式SOA架构中, 服务由某一集群提供, 当消费者访问某个服务时, 需要采用某种机制发现集群中有哪些节点可以提供该服务(这也称之为服务发现, 比如Alibaba开源的SOA框架Dubbo就采用了ZooKeeper作为服务发现的底层机制).
○ 开源的消息队列Kafka中, 通过ZooKeeper对Consumer的上下线进行管理.
3 部署ZooKeeper集群
3.1 下载并解压安装包
ZooKeeper下载地址: http://hadoop.apache.org/zookeeper/releases.html.
# 下载后, 上传至特定目录, 这里上传至/usr/local下:
cd /usr/local
# 解压ZooKeeper安装包:
tar -zxf zookeeper-3.4.10.tar.gz
3.2 创建data和datalog目录
# 进入ZooKeeper安装目录
cd zookeeper-3.4.10
# data为ZooKeeper数据存放目录, datalog为ZooKeeper日志存放目录
# 若不指定datalog, 默认与数据存放目录一致
mkdir data datalog
# 赋予当前用户写权限
chmod 644 data datalog
3.3 创建myid文件
在data目录下创建myid文件, 文件中只包含一行内容: 该节点对应的server.id的id编号. 如server.1节点中myid文件的内容为1.
# 将编号写入到myid文件中
echo 1 > /usr/local/zookeeper-3.4.10/data/myid
# 查看写入是否成功
cat /usr/local/zookeeper-3.4.10/data/myid
3.4 准备配置文件zoo.cfg
cd /usr/local/zookeeper-3.4.10/conf
# 拷贝文件, 重命名为zoo.cfg
cp zoo_sample.cfg zoo.cfg
# 修改zoo.cfg文件:
vim zoo.cfg
# 添加如下内容:
dataDir=/usr/local/zookeeper-3.4.10/data
dataLogDir=/usr/local/zookeeper-3.4.10/logs
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
- 配置完成的zoo.cfg文件如下:
# 基本事件单元(毫秒), 用来控制心跳和超时.
tickTime=2000
# 集群中有多台Server, 其中一台为Leader, 其余Server为Follower. initLimit参数指定Follower连接并同步到Leader的初始化心跳时间(即最长通信时间), 以tickTime的倍数表示, 超过该时间则连接失败.
initLimit=5
# Leader与Follower之间发送消息时, 请求和应答的最大时间, 是tickTime的倍数. 如果Follower在设置的时间内不能与Leader建立通信, 此Follower将被丢弃.
syncLimit=2
# 存放ZooKeeper运行时数据的目录, 需要提前建立.
dataDir=/usr/local/zookeeper-3.4.10/data
# log目录, 如果没有设置该参数, 默认使用dataDir的目录, 需要提前建立.
# 应当谨慎选择日志目录, 使用专用的日志存储设备能很大程度提高系统的性能.
dataLogDir=/usr/local/zookeeper-3.4.10/datalog
# 监听client连接的端口号.
clientPort=2181
# 设置连接到ZooKeeper的客户端的最大数量(限制并发连接的数量, 它通过IP来区分不同的客户端). 此配置选项可以用来阻止某些类别的Dos攻击, 将它设置为0或不设置将会取消对并发连接的限制.
maxClientCnxns=0
# 最小的会话超时时间, 默认为 2 * tickTme 时间
minSessionTimeout=4000
# 最大的会话超时时间默认情况下为 20 倍的会话超时时间
maxSessionTimeout=10000
# 集群中各个节点的信息(server.id=ip:port1:port2)
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
关于
server.id=host:port1:port2
的说明:id 是每个ZooKeeper节点的编号, 保存在dataDir目录下的myid文件中;
zoo1~zoo3表示各个ZooKeeper节点的hostname或IP地址, 映射关系在系统文件
/etc/hosts
中设置;port1指定该Server与集群中的Leader通信所使用的端口;
port2指定集群选举Leader时所用的端口.
常见错误说明:
○ clientPort 不能与port1、port2相同, 否则集群将启动不了.
○ 若采用伪分布式配置方式(即在一台服务器上模拟配置集群), 则各个Server的port1与port2不能相同.
○ 如果采用伪分布式配置方式, dataDir与dataLogDir也需要作不同的配置.
3.5 其他节点上服务的部署
# 拷贝ZooKeeper文件夹到其他服务器(zoo2和zoo3):
scp -r /usr/local/zookeeper-3.4.10 zoo2:/usr/local/
scp -r /usr/local/zookeeper-3.4.10 zoo2:/usr/local/
# 修改zoo2与zoo3服务器上ZooKeeper的myid:
echo 2 > /usr/local/zookeeper-3.4.10/data/myid
echo 2 > /usr/local/zookeeper-3.4.10/data/myid
4 启动ZooKeeper集群
4.1 关闭防火墙
ZooKeeper客户端使用2181端口号, 为了能对外正常使用Zookeeper, 需要开放2181端口号, 或者关闭防火墙:
- CentOS 7之前系统的命令:
# 查看防火墙状态:
service iptable status
# 临时关闭防火墙:
service iptables stop
# 永久关闭防火墙(禁止开机启动):
chkconfig iptables off
- CentOS 7开始使用systemctl来管理服务和程序, 包括service和chkconfig:
# 查看防火墙状态:
systemctl status firewalld.service
# 临时关闭防火墙:
systemctl stop firewalld.service
# 永久关闭防火墙(禁止开机启动):
systemctl disable firewalld.service
4.2 启动ZooKeeper集群:
# 依次进入三台服务器, 执行下述命令:
cd /usr/local/zookeeper-3.4.10/bin
./zkServer.sh start
# 查看ZooKeeper运行状态:
./zkServer.sh status
说明: 在查看ZooKeeper的状态时, 可能会发现控制台抛出错误:
[root@bogon bin]# ./zkServer.sh status JMX enabled by default Using config: /usr/local/zookeeper-3.4.10/bin/../conf/zoo.cfg Error contacting service. It is probably not running
错误原因: 这里部署的是集群, 其他服务器尚未启动, 当前节点在根据zoo.cfg中配置的服务列表发起选举Leader的请求, 由于无法与集群中的其他节点进行通信, 所以抛出错误.
错误解决: 在启动第二台ZooKeeper服务后, Leader将被选出, 错误就会消失. 因为在ZooKeeper集群中, 如果有2n+1台服务器, 它允许n台服务挂掉而不影响服务.
4.3 ZooKeeper常用命令
# 启动服务:
sh zkServer.sh start
# 查看服务状态:
sh zkServer.sh status
# 停止服务:
sh zkServer.sh stop
# 重启服务:
sh zkServer.sh restart
版权声明
作者: ma_shoufeng(马瘦风)
出处: CSDN 马瘦风的博客
您的支持是对博主的极大鼓励, 感谢您的阅读.
本文版权归博主所有, 欢迎转载, 但未经博主同意必须保留此段声明, 且在文章页面明显位置给出原文链接, 否则博主保留追究法律责任的权利.