ZooKeeper分布式协调服务-超简单的使用方法

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 马瘦风的博客

您的支持是对博主的极大鼓励, 感谢您的阅读.

本文版权归博主所有, 欢迎转载, 但未经博主同意必须保留此段声明, 且在文章页面明显位置给出原文链接, 否则博主保留追究法律责任的权利.

猜你喜欢

转载自blog.csdn.net/ma_shou_feng/article/details/82263507