基于zookeeper的hadoop HA实现

转:http://blog.csdn.net/everl_1/article/details/52303011

非HA弊端

HDFS集群的分布式存储是靠namenode节点(namenode负责响应客户端请求)来实现。在非HA集群中一旦namenode宕机,虽然元数据不会丢失,但整个集群将无法对外提供服务,导致HDFS服务的可靠性不高,这在实际应用场景中显然是不可行的。

HA机制

已知导致服务可靠性不高的原因是namenode节点宕机,那么怎么才能避免这个namenode节点宕机呢?一个容易想到的解决方案是部署两台namenode节点,形成主备模式(active/standby模式),这样一旦active节点宕机,standby节点立即切换到active模式。事实上HA机制就是采取的这种方案。要想实现该机制,需要解决以下问题:

1.为什么选择主备模式,而不是主主模式(active/active模式),也即让两个namenode节点都响应客户端的请求

        一个显然的前提是,两台namenode节点需要保存一致的元数据。

        我们知道namenode节点是用来管理这些元数据的,响应客户端请求时(上传)需要增加元数据信息,如果使用主主模式,那么两个节点都将对元数据进行写操作,怎么同步是个很困难的问题。因此,只能有一台机器响应请求,也即处在active状态的节点(可称为主节点),而另一台namenode在主节点正常工作情况下仅用来同步active节点的元数据信息,这个namenode称为备用节点(处在standby状态),可见,要解决的问题主要是怎么同步active节点的元数据信息。

2.怎么同步两个namenode节点的元数据

      响应客户端请求的是active节点,因此只有active节点保存了最新的元数据。元数据分为两部分,一部分是刚写入新的元数据(edits),另一部分是合并后的较旧的(fsimage)。HA机制解决同步问题的方法是将active节点新写入的edits元数据放在zookeeper集群上(zookeeper集群主要功能是实现少量数据的分布式同步管理),standby节点在active节点正常情况下只需要将zookeeper集群上edits文件同步到自己的fsimage中就可以。

       Hadoop框架为这个集群专门写了个分布式应用qjournal(依赖zookeeper实现),实现qjournal的节点称为journalnode。

3.怎么感知active节点是否宕机,并将standby节点快速切换到active状态?

        解决方案是专门在namenode节点上启动一个监控进程,时刻监控namenode的状态。对于处在active状态的namenode,如果发现不正常就向zookeeper集群中写入一些数据。对于处在standby状态的namenode,监控进程从zookeeper集群中读数据,从而感知到active节点是否正常。如果发现异常,监控进程负责将standby状态切换到active状态。这个监控进程在hadoop中叫做zkfc(依赖zookeeper实现)。

4.如何在状态切换时避免brain split(脑裂)?

        脑裂:active namenode工作不正常后,zkfc在zookeeper中写入一些数据,表明异常,这时standby namenode中的zkfc读到异常信息,并将standby节点置为active。但是,如果之前的active namenode并没有真的死掉,出现了假死(死了一会儿后又正常了,哈哈,是不是很搞笑),这样,就有两台namenode同时工作了。这种现象称为脑裂。

        解决方案:standby namenode感知到主用节点出现异常后并不会立即切换状态,zkfc会首先通过ssh远程杀死active节点的 namenode进程(kill -9 进程号)。但是(这样还不行,惊讶),如果kill指令没有执行成功咋办??如果在一段时间内没有收到执行成功的回执,standby节点会执行一个自定义脚本,尽量保证不会出现脑裂问题!这个机制在hadoop中称为fencing(包括ssh发送kill指令,执行自定义脚本两道保障)


解决上诉问题以后,基本上就实现了hadoop HA 。

HA实现
1.HA集群规划

   

机名	软件	进程
hadoop01	jdk,hadoop,zookeeper	QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop02	jdk,hadoop,zookeeper	QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop03	jdk,hadoop,zookeeper	QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop04	jdk,hadoop	namenode,zkfc(active)
hadoop05	jdk,hadoop	namenode,zkfc
hadoop06	jdk,hadoop	resourcemanager
hadoop07	jdk,hadoop	resourcemanager


(注:datanode,nodemanager一般放到一起。journalnode依赖zookeeper来实现,因此QuorumPeerMain(zookeeper),journalnode必须放一起!)


2.集群安装前的环境检查

时间同步:

在命令行中做如下操作,来安装ntpdate
yum install -y ntp
继续在命令行中操作,进行同步时间
ntpdate 210.72.145.44 #中国国家授时中心


关闭防火墙:

systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动


设置主机名映射(root用户)

机器之间的主机名和IP建立映射关系

192.168.169.129 hadoop01
192.168.169.130 hadoop02
192.168.169.131 hadoop03
192.168.169.132 hadoop04
192.168.169.133 hadoop05
192.168.169.134 hadoop06
192.168.169.135 hadoop07

创建专有的用户(root用户)


一般是建专有的hadoop用户,不在root用户上面搭建
创建组和用户

这里每台虚拟主机都应该有hadoop用户

#先创建组cloud
groupadd cloud
#创建用户并加入组cloud
useradd -g cloud hadoop
#修改用户hadoop的密码
passwd hadoop

将hadoop用户加到sodu列表

1、查看/etc/sudoers的权限

ls -l /etc/sudoers

这里写图片描述

可以看的是只读权限,如果我们要修改就必须先改变该文件的权限

2、修改权限

chmod 777 /etc/sudoers

这里写图片描述

3、将hadoop添加root权限

vim /etc/sudoers

这里写图片描述

在root下加入下面hadoop用户


4、还原权限
chmod 440 /etc/sudoers


拷贝/etc/sudoers到其它主机
scp /etc/sudoers hadoop02:/etc/
scp /etc/sudoers hadoop03:/etc/
scp /etc/sudoers hadoop04:/etc/
scp /etc/sudoers hadoop05:/etc/
scp /etc/sudoers hadoop06:/etc/
scp /etc/sudoers hadoop07:/etc/


配置免密码登录(hadoop用户)

切换hadoop用户

su hadoop
进入到当前用户的根目录

cd ~
查看所有文件

ls –la

进入.ssh目录

cd .ssh
生产公钥和私钥(四个回车)

ssh-keygen -t rsa


执行完这个命令后,会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)

这里写图片描述

将公钥拷贝到要免登陆的机器上

ssh-copy-id hadoop01
ssh-copy-id hadoop02
ssh-copy-id hadoop03
ssh-copy-id hadoop04
ssh-copy-id hadoop05
ssh-copy-id hadoop06
ssh-copy-id hadoop07
这时会在hadoop02 主机的.ssh/下产生一个名为authorized_keys的文件,这时通过 ssh hadoop02时可以直接免登陆进入主机 
如下:



同理可以给其他机器也设置免密码登录。


准备软件


在/home/hadoop/下创建cloud文件夹,用来安装相关软件,同时所用安装包放在cloud下的soft-install文件夹下,如:

cd /home/hadoop
mkdir cloud
mkdir soft-install


上传我们所需要的软件到这个目录
安装jdk

解压

tar -zxvf jdk-8u91-linux-x64.tar.gz -C /home/hadoop/cloud/
配置环境变量

# 修改配置文件
sudo vi /etc/profile
# 在最后下添加

export JAVA_HOME=/home/hadoop/cloud/jdk1.8.0_91
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# 刷新配置文件
source /etc/profile
将jdk和环境变量分别拷贝到其他主机上

可以直接将cloud文件夹复制过去

scp -r cloud/ hadoop02:/home/hadoop/
scp -r cloud/ hadoop03:/home/hadoop/
scp -r cloud/ hadoop04:/home/hadoop/
scp -r cloud/ hadoop05:/home/hadoop/
scp -r cloud/ hadoop06:/home/hadoop/
scp -r cloud/ hadoop07:/home/hadoop/

将环境变量拷贝到其他主机下

sudo scp /etc/profile hadoop02:/etc/
sudo scp /etc/profile hadoop03:/etc/
sudo scp /etc/profile hadoop04:/etc/
sudo scp /etc/profile hadoop05:/etc/
sudo scp /etc/profile hadoop06:/etc/
sudo scp /etc/profile hadoop07:/etc/

刷新环境变量

source /etc/profile
安装zookeeper


如果不懂Zookeeper请参考:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/


下载地址:http://mirrors.hust.edu.cn/apache/zookeeper/
安装

前面我们已经安装的jdk,现在我们在hadoop01、hadoop02、hadoop03上安装Zookeeper

1、解压

tar -zxvf zookeeper-3.4.9.tar.gz -C /home/hadoop/cloud/

2、修改Zookeeper的默认配置 conf/zoo_sample.cfg

mv zoo_sample.cfg zoo.cfg
vi zoo.cfg

配置如下:

#修改dataDir指向我们数据
dataDir=/home/hadoop/cloud/zookeeper-3.4.9/data
#并在最后添加
server.1=hadoop01:2888:3888
server.2=hadoop02:2888:3888
server.3=hadoop03:2888:3888

3、在/home/hadoop/cloud/zookeeper-3.4.9/目录下创建data文件夹

mkdir data
4、在data文件夹下创建myid文件指明本机id

vi myid
id 分别对应为hadoop01为1,hadoop02为2,hadoop03为3 后面我们再统一拷贝


5、复制zookeeper-3.4.8到hadoop02、hadoop03机器上并修改相应的myid

scp -r zookeeper-3.4.9/ hadoop02:/home/hadoop/cloud/zookeeper-3.4.9/
scp -r zookeeper-3.4.9/ hadoop03:/home/hadoop/cloud/zookeeper-3.4.9/

启动Zookeeper


分别在hadoop01、hadoop02、hadoop03上启动Zookeeper

#执行/home/hadoop/cloud/zookeeper-3.4.9/bin目录下的脚本启动
./zkServer.sh start

查看zookeeper的状态

./zkServer.sh status


在bin/目录下运行,运行结果如下说明成功(此时至少运行2台)

其实我们可以找到leader 然后stop,会发现Zookeeper会立即切换Leader


安装hadoop
安装(现在hadoop01安装,然后复制其他机器)

解压

tar -zxvf hadoop-2.7.3.tar.gz -C /home/hadoop/cloud/


配置环境变量

# 修改配置文件
sudo vi /etc/profile
# 在最后下添加

export HADOOP_HOME=/home/hadoop/cloud/hadoop-2.7.3
export PATH=$PATH:$HADOOP_HOME/bin

# 刷新配置文件
source /etc/profile

测试:

which hadoop


修改配置文件(6个)

#hadoop2.x的配置文件全部在$HADOOP_HOME/etc/hadoop下
cd /home/hadoop/cloud/hadoop-2.7.3/etc/hadoop

hadoop-env.sh

# The java implementation to use.
export JAVA_HOME=/home/hadoop/cloud/jdk1.8.0_91

core-site.xml

<configuration>

    <!-- 指定hadoop运行时产生文件的存储路径 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop/cloud/hadoop-2.7.3/tmp</value>
    </property>

    <!-- 指定hdfs的nameservice为ns1 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://ns1</value>
    </property>

    <!-- 指定zookeeper地址,多个用,分割 -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
    </property>

</configuration>

hdfs-site.xml

<configuration>
    <!-- dfs.nameservices 命名空间的逻辑名称,多个用,分割 -->
    <property>
      <name>dfs.nameservices</name>
      <value>ns1</value>
    </property>

    <!-- 指定ns1下有两个namenode,分别是nn1,nn2 -->
    <property>
      <name>dfs.ha.namenodes.ns1</name>
      <value>nn1,nn2</value>
    </property>

    <!-- 指定nn1的RPC通信地址 -->
    <property>
      <name>dfs.namenode.rpc-address.ns1.nn1</name>
      <value>hadoop04:8020</value>
    </property>

    <!-- 指定nn1的HTTP通信地址 -->
    <property>
      <name>dfs.namenode.http-address.ns1.nn1</name>
      <value>hadoop04:50070</value>
    </property>

    <!-- 指定nn2的RPC通信地址 -->
    <property>
      <name>dfs.namenode.rpc-address.ns1.nn2</name>
      <value>hadoop05:8020</value>
    </property>

    <!-- 指定nn2的HTTP通信地址 -->
    <property>
      <name>dfs.namenode.http-address.ns1.nn2</name>
      <value>hadoop05:50070</value>
    </property>

    <!-- 指定namenode的元数据存放的Journal Node的地址,必须基数,至少三个 -->
    <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03:8485/ns1</value>
    </property>

    <!--这是JournalNode进程保持逻辑状态的路径。这是在linux服务器文件的绝对路径-->
    <property>
      <name>dfs.journalnode.edits.dir</name>
      <value>/home/hadoop/cloud/hadoop-2.7.3/journal/</value>
    </property>

    <!-- 开启namenode失败后自动切换 -->
    <property>
      <name>dfs.ha.automatic-failover.enabled</name>
      <value>true</value>
    </property>

    <!-- 配置失败自动切换实现方式 -->
    <property>
      <name>dfs.client.failover.proxy.provider.ns1</name>
      <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>

    <!-- 配置隔离机制方法,多个机制用换行分割 -->
    <property>
      <name>dfs.ha.fencing.methods</name>
      <value>
        sshfence
        shell(/bin/true)
      </value>
    </property>

    <!-- 使用sshfence隔离机制时需要ssh免登陆 -->
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value>
    </property>

    <!-- 配置sshfence隔离机制超时时间30秒 -->
    <property>
       <name>dfs.ha.fencing.ssh.connect-timeout</name>
       <value>30000</value>
    </property>
</configuration>

mapred-site.xml.template
需要重命名: mv mapred-site.xml.template mapred-site.xml

<configuration>
    <!-- 通知框架MR使用YARN -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

yarn-site.xml

<configuration>
		<!-- 开启RM高可用 -->
		<property>
		   <name>yarn.resourcemanager.ha.enabled</name>
		   <value>true</value>
		</property>
		<!-- 指定RM的cluster id -->
		<property>
		   <name>yarn.resourcemanager.cluster-id</name>
		   <value>yrc</value>
		</property>
		<!-- 指定RM的名字 -->
		<property>
		   <name>yarn.resourcemanager.ha.rm-ids</name>
		   <value>rm1,rm2</value>
		</property>
		<!-- 分别指定RM的地址 -->
		<property>
		   <name>yarn.resourcemanager.hostname.rm1</name>
		   <value>hadoop06</value>
		</property>
		<property>
		   <name>yarn.resourcemanager.hostname.rm2</name>
		   <value>hadoop07</value>
		</property>
		<!-- 指定zk集群地址 -->
		<property>
		   <name>yarn.resourcemanager.zk-address</name>
		   <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
		</property>
		<property>
		   <name>yarn.nodemanager.aux-services</name>
		   <value>mapreduce_shuffle</value>
		</property>
	</configuration>

修改/home/hadoop/cloud/hadoop-2.7.3/etc/hadoop/slaves文件

slaves文件是指定子节点的位置

要在hadoop4上启动hdfs,按照集群配置,需要指定datanode在hadoop01,hadoop02,hadoop3上
要在hadoop6上启动yarn,按照集群配置,需要指定nodemanager在hadoop01,hadoop02,hadoop3上。

vi   slaves
#子节点的位置
hadoop01
hadoop02
hadoop03

并在 hadoop-2.7.3文件下 创建tmp文件:
mkdir tmp


将配置好的文件拷贝到其他主机

scp -r hadoop-2.7.3/ hadoop02:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop03:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop04:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop05:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop06:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop07:/home/hadoop/cloud/hadoop-2.7.3/

将环境变量拷贝到其他主机下

sudo scp /etc/profile hadoop02:/etc/
sudo scp /etc/profile hadoop03:/etc/
sudo scp /etc/profile hadoop04:/etc/
sudo scp /etc/profile hadoop05:/etc/
sudo scp /etc/profile hadoop06:/etc/
sudo scp /etc/profile hadoop07:/etc/

刷新环境变量

source /etc/profile

启动


启动的时候注意启动顺序


1、启动zookeeper(在hadoop01、02、03)

./zkServer.sh start 
  查看zookeeper状态:./zkServer.sh status, 正确的状态是一个leader,两个follower。

2、启动journal node(在hadoop01、02、03)

#hadoop-2.7.3/sbin下
./sbin/hadoop-daemon.sh start journalnode
启动成功后会多出一个JournalNode进程。


3.格式化HDFS

 在hadoop04上执行格式化指令:./bin/hadoop namenode -format

并把/home/hadoop/cloud/hadoop-2.7.3/tmp 文件夹拷贝到另一台namenode的目录下

scp -r /home/hadoop/cloud/hadoop-2.7.3/tmp hadoop05:/home/hadoop/cloud/hadoop-2.7.3/

4.格式化zkfc

在hadoop4上执行格式化指令:./bin/hdfs zkfc -formatZK
    格式化成功后会在zookeeper集群建立新的文件路径(该路径下存放zkfc监控namenode节点的信息)


5、启动zkfc来监控NN状态(在hadoop04、05)

./sbin/hadoop-daemon.sh start zkfc

6、启动HDFS(namenode)(在hadoop04即可)

#hadoop-2.7.3/sbin下
./sbin/start-dfs.sh

7、启动YARN


在hadoop06上执行./sbin/start-yarn.sh
在hadoop07上执行./sbin/yarn-daemon.sh start resourcemanager


通过浏览器测试如下:
http://192.168.169.132:50070/

http://192.168.169.133:50070/

可以看出hadoop04的namenode是处于一种standby状态,那么hadoop05应该是处于active状态

hdfs haadmin -getServiceState nn1


hdfs haadmin -getServiceState nn2


把hadoop05(192.168.169.133)的namenode 进程kill掉


hdfs haadmin -getServiceState nn1


hdfs haadmin -getServiceState nn2


可以看出hadoop04的namenode是处于一种active状态,hadoop05不能访问

重新启动hadoop05的namenode

./sbin/hadoop-daemon.sh start namenode

hadoop05会变成standby状态


查看YARN的状态

http://192.168.169.134:8088/


输入:http://192.168.169.135:8088/ 会跳转到 http://hadoop06:8088/














 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值