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服务器上以独立模式运行。
从apache官网下载zookeeper稳定版,上传至服务器nn1。将zookeeper包发送至所有的节点(zookeeper机器)上。
在所有zookeeper机器上,将压缩包解压至/usr/local/。(可以创建软链接)将/usr/local/zookeeper的权限改为770
修改每个机器上zookeeper的配置:
- zookeeper/bin是执行脚本所在的位置
1
2
3
4
5
6-- zkCleanup.sh
-- zkcli.cmd
-- zkcli.sh
-- zkEnv.cmd
-- zkEnv.sh
-- zkServer.cmd - zookeeper/conf是配置文件目录 可将zookeeper的可执行脚本文件添加进命令行路径:
1
2
3-- configuration.xsl
-- log4j.properties
-- zoo_sample.cfg #这个是重要的配置文件在运行zookeeper服务之前,需要创建配置文件,习惯上命名为/zookeeper/conf/zoo.cfg。这是一个标注Java属性文件。常用的配置文件内容为:1
2export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.9
export PATH=$PATH:$ZOOKEEPER_HOME/bin1
2
3
4
5
6ticktime=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
- zookeeper/bin是执行脚本所在的位置
配置好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
3echo ruok | telnet localhost 2181
第一次运行时出现问题,connection problem在每个机器上创建/data目录,并把权限改成hadoop:hadoop
在新建的/data目录下生成myid文件(注意这个只能手动在每个机器的/data目录下创建,不能使用批量脚本)
给每个机器设置好环境变量:
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加执行权限。
在每个机器上启动zookeeper服务并查看启动结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
211. 注意要使用免密登录,要注意用户权限的问题
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 | ZK服务命令 |
ZooKeeper 示例
- 一组服务器用于为客户端提供某种服务。我们希望每个客户端都能找到其中一台服务器。那么问题在于如何维护这组服务器的成员列表。
ZooKeeper中的组成员关系
将zk看做一个具有高可用性特征的文件系统。该文件系统中没有文件和目录,而是统一使用”节点“(node),znode。znode既可以作为保存数据的容器(如文件),也可以作为保存其他znode的容器(目录)。所有的znode构成一个层次化的命名空间。
创建一个以组名为节点名的znode为父节点,然后以组成员名(服务器名)为节点名来创建作为子节点的znode。