Hadoop ZooKeeper初步

Hadoop zookeeper

zookeeper是Hadoop的分布式协调服务,可以用来构建一般的分布式应用。

写分布式应用的主要困难在于会出现”部分失败“。当一条消息在网络中的两个节点之间传送时,如果出现网络错误,发送者无法知道接收者是否已经收到这条消息。接收者可能在网络出错之前已经收到了这条消息,也有可能没收到,或者接收者进程已经死掉。发送者能够获得真实情况的唯一途径就是重新连接接收者,并发送询问。这种情况就是部分失败。

部分失败是分布式系统固有的特征。zookeeper提供一组工具,使你的构建分布式应用时能够对部分失败进行正确处理。

zookeeper具有以下特点:

  • zookeeper是简单的。 zookeeper的核心是一个精简的文件系统,提供一些简单的操作和一些额外的抽象操作(如排序和通知)
  • zookeeper是富有表现力的。 zookeeper的基本操作是一组丰富的”构件“(building block),可用于实现多种协调数据结构和协议。
  • zookeeper具有高可用性。
  • zookeeper采用松耦合交互方式。在zookeeper支持的交互过程中,参与者不需要彼此了解。一个进程可以在zookeeper中留下一条信息,在该进程结束后,另外一个进程还可以读取这条消息。
  • zookeeper是一个资源库,提供了一个通用协调模式实现方法的开源共享库,使程序员免于写这类通用的协议。

zookeeper的节点为什么设置为基数:
zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。如果有2个zookeeper,那么只要有1个死了zookeeper就不能用了,因为1没有过半,所以2个zookeeper的死亡容忍度为0;同理,要是有3个zookeeper,一个死了,还剩下2个正常的,过半了,所以3个zookeeper的容忍度为1。

zookeeper的安装与运行

首次尝试使用zookeeper,最简单的方式是在一台zookeeper服务器上以独立模式运行。

  1. 从apache官网下载zookeeper稳定版,上传至服务器nn1。将zookeeper包发送至所有的节点(zookeeper机器)上。

  2. 在所有zookeeper机器上,将压缩包解压至/usr/local/。(可以创建软链接)将/usr/local/zookeeper的权限改为770

  3. 修改每个机器上zookeeper的配置:

    • zookeeper/bin是执行脚本所在的位置
      1
      2
      3
      4
      5
      6
      -- zkCleanup.sh
      -- zkcli.cmd
      -- zkcli.sh
      -- zkEnv.cmd
      -- zkEnv.sh
      -- zkServer.cmd
    • zookeeper/conf是配置文件目录
      1
      2
      3
      -- configuration.xsl
      -- log4j.properties
      -- zoo_sample.cfg #这个是重要的配置文件
      可将zookeeper的可执行脚本文件添加进命令行路径:
      1
      2
      export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.9
      export PATH=$PATH:$ZOOKEEPER_HOME/bin
      在运行zookeeper服务之前,需要创建配置文件,习惯上命名为/zookeeper/conf/zoo.cfg。这是一个标注Java属性文件。常用的配置文件内容为:
      1
      2
      3
      4
      5
      6
      ticktime=2000 #指定zookeeper中的基本时间单元(ms) 
      dataDir=/data/ #数据目录,zookeeper存储持久数据的本地文件系统位置
      clientPort=2181 #client提供服务的端口号,zookeeper监听客户端连接的端口
      server.1=nn0.hadoop:2888:3888 #server提供服务的端口号
      server.2=nn1.hadoop:2888:3888
      server.3=s1.hadoop:2888:3888
  4. 配置好conf之后,我们可以启动一个本地zookeeper服务器。

    1
    2
    3
    4
    [root@nn1 zookeeper]# zkServer.sh start
    ZooKeeper JMX enabled by default
    Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
    Starting zookeeper ... STARTED

    同时可以用以下命令来监听端口:

    1
    2
    3
    echo ruok | telnet localhost 2181

    第一次运行时出现问题,connection problem
  5. 在每个机器上创建/data目录,并把权限改成hadoop:hadoop

  6. 在新建的/data目录下生成myid文件(注意这个只能手动在每个机器的/data目录下创建,不能使用批量脚本)

  7. 给每个机器设置好环境变量:
    env 查看当前shell环境下已有的环境变量
    1) /etc/profile 全局环境变量,针对整个系统
    2) ~/.bash_profile 当前用户的环境变量
    加载顺序是先加载系统,再加载自己的环境变量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    使用hadoop软件生态环境所使用的环境变量
    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

    将上述环境变量导入每台机器。可以通过将profile和op.sh批量复制到各台机器上然后再批量执行op.sh。注意要给op.sh加执行权限。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    1. 注意要使用免密登录,要注意用户权限的问题
    2. 批量操作

    % [hadoop@nn1 ssh_learning]$ ./ssh_all.sh /usr/local/zookeeper/bin/zkServer.sh start

    # 报错信息,找不到zoo.cfg文件,说明之前没有更改zoo.cfg
    ssh hadoop@s1.hadoop "/usr/local/zookeeper/bin/zkServer.sh start"
    ZooKeeper JMX enabled by default
    Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
    grep: /usr/local/zookeeper/bin/../conf/zoo.cfg: No such file or directory
    mkdir: cannot create directory ‘’: No such file or directory
    Starting zookeeper ... /usr/local/zookeeper/bin/zkServer.sh: line 149: /zookeeper_server.pid: Permission denied
    FAILED TO WRITE PID
    FAIL

    # 将zoo.cfg导入后通过
    ssh hadoop@s1_hadoop /usr/local/zookeeper/bin/zkServer.sh
    ZooKeeper JMX enabled by default
    Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
    Usage: /usr/local/zookeeper/bin/zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
    OK
  • 查看java程序进程 jps 或查看进程命令 ps aux | grep zookeeper
  • 查看zk输出日志 /data/zookeeper.out
  • /data/zookeeper_server.pid 是存储当前zk服务的进程id

zookeeper的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ZK服务命令
% zkServer.sh status 查看机器zk运行的状态
% zkServer.sh stop 整体停止服务
% zkServer.sh restart 重启zk服务
% zkServer.sh status 查看zk服务状态

ZK客户端命令
% zkCli.sh -server 启动zkclient,并连接集群
(1)显示根目录下文件: ls
(2)显示根目录下文件:ls2 查看当前节点数据并能看到更新次数等数据
(3)创建文件,并设置初始内容:create /zk "test"创建一个新的znode节点”zk“ 以及与它关联的字符串
(4)获取文件内容:get /zk 确认znode是否包含我们所创建的字符串
(5)修改文件内容:set /zk "zkbzk" 对zk所关联的字符串进行设置
(6)删除文件:delete /zk 将刚才创建的znode删除
(7)退出客户端: quit
(8)帮助命令:help

ZooKeeper 示例

  • 一组服务器用于为客户端提供某种服务。我们希望每个客户端都能找到其中一台服务器。那么问题在于如何维护这组服务器的成员列表。

ZooKeeper中的组成员关系

将zk看做一个具有高可用性特征的文件系统。该文件系统中没有文件和目录,而是统一使用”节点“(node),znode。znode既可以作为保存数据的容器(如文件),也可以作为保存其他znode的容器(目录)。所有的znode构成一个层次化的命名空间。

创建一个以组名为节点名的znode为父节点,然后以组成员名(服务器名)为节点名来创建作为子节点的znode。