文章目录
1.什么是ZooKeeper
ZooKeeper直译就是动物园管理员, 它是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)等的管理员(这些都是Apache软件基金组织旗下大数据方面的技术框架), Apache Hbase和Apache Solr的分布式集群都用到了ZooKeeper.
(1) 百度百科中的说明:
ZooKeeper是一个高可用、分布式的程序协调服务, 是Google的Chubby一个开源的实现, 是Hadoop和Hbase的重要组件.
它是一个为分布式应用提供一致性服务的软件, 提供的功能包括: 配置维护、域名服务、分布式同步、组服务等.
ZooKeeper的目标就是封装好复杂易出错的关键服务, 将简单易用的接口和性能高效、功能稳定的系统提供给用户.
(2) ZooKeeper的基本运转流程:
① 选举Leader;
② 同步数据;
③ 选举Leader过程中算法有很多, 但要达到的选举标准是一致的;
④ Leader要具有最高的执行ID, 类似root权限;
⑤ 集群中大多数的机器得到响应并接受选出的Leader.
2.ZooKeeper的功能
2.1 配置管理
项目开发中大多会涉及到各种配置信息, 比如JDBC的连接信息等. 一般将这些信息配置到特定的文件中, 在代码中引入相关配置文件即可.
—— 这是单服务器应用中常用的做法. 当应用很大、配置文件很多, 尤其是在分布式项目中, 多台服务器的配置需要保持一致,
而如果配置信息会被频繁地修改, 这个时候还使用配置文件就不是个好主意了.扫描二维码关注公众号,回复: 9465048 查看本文章—— 你总不能手动逐个修改吧? 不仅重复性劳动太多, 而且出错的可能性更大, 后期维护成本太大.
这种情况下往往需要寻找一种集中管理配置的方法 —— 在这个集中的地方修改了配置, 所有对该配置有依赖的服务都可以获得变更.
需要考虑的是, 由于多台服务器上的项目都依赖了这个配置, 为了应用的可靠运行, 需要这个集中提供配置服务的应用具备非常高的可靠性.
基于上述分析, 我们可以通过集群来提供配置服务, 保证系统的可靠性. 此时遗留的问题是, 如何保证配置在集群中的一致性呢?
为了提供这种一致性, 前辈们提出了一致性协议, 实现此协议的服务就有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.
#下载后, 上传至特定目录, 这里上传至/data/zookeeper下:
mkdir -p /data/zookeeper && cd /data/zookeeper
#解压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 > /data/zookeeper/data/myid
#查看写入是否成功
cat /data/zookeeper/data/myid
3.4 修改配置文件zoo.cfg
(1) 修改过程如下:
cd /data/zookeeper/zookeeper-3.4.10/conf
#拷贝文件, 重命名为zoo.cfg
cp zoo_sample.cfg zoo.cfg
#修改zoo.cfg文件:
vim zoo.cfg
#添加如下内容:
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/datalog
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
(2) 配置完成的zoo.cfg文件如下:
# 基本事件单元(毫秒), 用来控制心跳和超时.
tickTime=2000
# 集群中有多台Server, 其中一台为Leader, 其余Server为Follower. initLimit参数指定Follower连接并同步到Leader的初始化心跳时间(即最长通信时间), 以tickTime的倍数表示, 超过该时间则连接失败.
initLimit=5
# Leader与Follower之间发送消息时, 请求和应答的最大时间, 是tickTime的倍数. 如果Follower在设置的时间内不能与Leader建立通信, 此Follower将被丢弃.
syncLimit=2
# 存放ZooKeeper运行时数据的目录, 需要提前建立.
dataDir=/data/zookeeper/data
# log目录, 如果没有设置该参数, 默认使用dataDir的目录, 需要提前建立.
# 应当谨慎选择日志目录, 使用专用的日志存储设备能很大程度提高系统的性能.
dataLogDir=/data/zookeeper/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
(3) 关于 server.id=host:port1:port2 的说明:
id 是每个ZooKeeper节点的编号, 保存在dataDir目录下的myid文件中;
zoo1~zoo3表示各个ZooKeeper节点的hostname或IP地址, 映射关系在系统文件 /etc/hosts 中设置;
port1指定该Server与集群中的Leader通信所使用的端口;
port2指定集群选举Leader时所用的端口.
(4) 常见错误说明:
○ clientPort 不能与port1、port2相同, 否则集群将启动不了.
○ 若采用伪分布式配置方式(即在一台服务器上模拟配置集群), 则各个Server的port1与port2不能相同.
○ 如果采用伪分布式配置方式, dataDir与dataLogDir也需要作不同的配置.
3.5 部署其他节点上的服务
#拷贝ZooKeeper文件夹到其他服务器(zoo2和zoo3) --- 需要确保相应的路径/data/zookeeper存在:
scp -r /data/zookeeper zoo2:/data/
scp -r /data/zookeeper zoo2:/data/
#分别在zoo2和zoo3服务器上修改ZooKeeper的myid:
echo 2 > /data/zookeeper/zookeeper-3.4.10/data/myid
echo 3 > /data/zookeeper/zookeeper-3.4.10/data/myid
4 启动ZooKeeper集群
4.1 关闭防火墙
ZooKeeper客户端使用2181端口号, 为了能对外正常使用Zookeeper, 需要开放2181端口号, 或者关闭防火墙:
(1) CentOS 7之前系统的命令:
#查看防火墙状态:
service iptable status
#临时关闭防火墙:
service iptables stop
#永久关闭防火墙(禁止开机启动):
chkconfig iptables off
(2) CentOS 7开始使用systemctl来管理服务和程序, 包括service和chkconfig:
#查看防火墙状态:
systemctl status firewalld.service
#临时关闭防火墙:
systemctl stop firewalld.service
#永久关闭防火墙(禁止开机启动):
systemctl disable firewalld.service
4.2 启动ZooKeeper集群
(1) 启动步骤:
#依次进入三台服务器, 执行下述命令:
cd /usr/local/zookeeper-3.4.10/bin
./zkServer.sh start
#查看ZooKeeper运行状态:
./zkServer.sh status
(2) 常见错误: 在查看ZooKeeper的状态时, 可能会发现控制台抛出错误:
[root@localhost bin]# ./zkServer.sh status
JMX enabled by default
Using config: /data/zookeeper/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