Hadoop HDFS升级HA,Hive旧的库表元数据需同步更新

  • Post author:
  • Post category:其他


一、配置HDFS HA


简介:

任意时刻只有一个NameNode处于Active状态,为集群操作提供服务。其他NameNode全部处于Standby状态,他们维护足够的状态信息,以便在Active Failover时,快速提供服务切换。

为了快速切换NameNode,Standby NameNode需要实时更新DataNode的Block信息,因此,DataNode上会配置所有的NameNode,并想所有的NameNode发送HeartBeat和Block信息。


硬件准备:

1、需要准备多台配置一样的设备,每台的具体配置和不采用HA时的NameNode一致即可。

2、运行JournalNode的设备,JournalNode进程资源占用较少,可以与其他Hadoop服务运行在同一台机器上,需要有>=3的奇数个副本。


部署:

1、修改配置文件,先修改hdfs-site.xml

<!-- HA With JournalNodes 
        需要在所有运行 JournalNode的节点上创建数据目录
        xshell.sh "mkdir -p /data/namenode_ha/journal/node/"
    -->
    <!-- 配置集群nameservice名称 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>

    <!-- 配置nameservice对应的NameNode IDs -->
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2, nn3</value>
    </property>

    <!-- 配置各个NameNode ID对应的RPC地址 -->
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>nn1:8020</value>
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>nn2:8020</value>
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn3</name>
        <value>nn3:8020</value>
    </property>

    <!-- 配置各个NameNode ID对应的NameNode -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>nn1:9870</value>
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>nn2:9870</value>
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn3</name>
        <value>nn3:9870</value>
    </property>

    <!-- 配置各个NameNode共享的qjournal的存储位置,使用逗号分隔。只有HA模式下可以配置该属性,否则报错 -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://nn1:8485;nn2:8485;nn3:8485/mycluster</value>
    </property>

    <!-- 配置Client连接Active NameNode的Java类 -->
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>

    <!-- 在NameNode切换时隔离失败NameNode的脚本 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>shell(/bin/true)</value>
    </property>

    <!-- 配置JournalNode保存edit文件的目录 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/namenode_ha/journal/node/</value>
    </property>

然后在core-site.xml中修改如下配置:

    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value>
    </property>

2、在所有JournalNode上创建数据目录:

mkdir -p /data/namenode_ha/journal/node/

3、将原来在唯一namenode上的current目录文件夹,同步到其他NameNode节点。我是采用的批量同步脚本

xrsync.sh /data/hdfs/name/ /data/hdfs/name/

4、初始化JournalNode的数据目录:

hdfs namenode -initializeSharedEdits

二、搭建故障自动切换

依赖两个组件:Zookeeper集群、ZKFailoverController进程

Zookeeper作用:

1、失败检测

集群中每个NameNode都会维持一个与Zookeeper的会话,如果NameNode挂掉,Zookeeper的会话就会终止,触发NameNodes之间的故障转移

2、Active选举

Zookeeper提供了一个简单的Active NameNode选举机制。当Active挂掉之后,其他NameNodes会抢占Zookeeper上的排它锁,谁抢到谁就是下一个Active NameNode。

ZKFailoverController作用:

ZKFailoverController是一个Zookeeper的客户端,可以监视和管理NameNode的状态,有以下作用:

1、健康检查。它会间隔的向当前NameNode发送健康检查指令。如果NameNode超时未返回状态或返回了unhealthy的状态,就会将NameNode标记为“unhealthy”

2、当前NameNode健康的时候,ZKFC会维护一个与Zookeeper的会话。如果当前NameNode是Active的话,它会持有一个lock的znode,这是Zookeeper支持的一种短期node,如果会话过期,这个节点就会被自动删除

3、基于Zookeeper的选举。如果ZKFC本地的NameNode是健康的,并且发现没有其他节点持有lock znode,ZKFC就会尝试从Zookeeper获取锁,如果成功,就表示赢得了选举,本地NameNode状态修改为Active。故障转移的步骤与手动切换时基本一致,首先执行前一个节点的后续fence操作,然后当前NameNode切换到Active状态。

详细切换过程参考:HDFS-2185

注意:

截止Hadoop3.1.2,并不支持运行时从手动故障切换升级为自动切换,需要先停止dfs集群。

配置:

1、修改hdfs-site.xml

    <property>
        <!--启用自动故障切换-->
        <name>dfs.ha.automatic-failover.enabled.mycluster</name>
        <value>true</value>
    </property>

2、修改core-site.xml

    <!-- 配置保存 HA 状态的Zookeeper -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>nn1:2181,nn2:2181,nn3:2181</value>
    </property>

部署:

1、在Zookeeper各个节点启动Zookeeper

zkServer.sh start

2、在NameNode执行脚本

hdfs zkfc -formatZK

3、在所有NameNode节点启动ZKFC进程

hdfs --daemon start zkfc

4、启动HDFS

start-dfs.sh

此时,打开各个NameNode的http web界面,即可看到节点状态:

目前为止,HDFS的HA已经搭建成功。

Hive元数据同步更新

此时,打开hive终端,查询从前创建的库表,会发现报异常:

hive (default)> show tables;
OK
tab_name
users
Time taken: 4.05 seconds, Fetched: 1 row(s)
hive (default)> select * from users;
FAILED: SemanticException Unable to determine if hdfs://m.hadoop.com:9000/warehouse/users is encrypted: org.apache.hadoop.hive.ql.metadata.HiveException: java.net.ConnectException: Call From m.hadoop.com/192.168.10.11 to m.hadoop.com:9000 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused
hive (default)> 

这是由于HA之后,访问hdfs的默认链接改为了:http://nameservice-id,所以我们需要手动进入存储Hive元数据的MySQL库,将旧的数据目录更新为“http://nameservice-id/user/hive”的样式:

UPDATE DBS SET DB_LOCATION_URI=REPLACE (DB_LOCATION_URI,'m.hadoop.com:9000', 'nameservice-id');

UPDATE SDS SET LOCATION=REPLACE (LOCATION,'m.hadoop.com:9000', 'nameservice-id');

这样就可以正常访问Hive数据表了:

hive (default)> show tables;
OK
tab_name
users
Time taken: 4.05 seconds, Fetched: 1 row(s)
hive (default)> select * from users;
FAILED: SemanticException Unable to determine if hdfs://m.hadoop.com:9000/warehouse/users is encrypted: org.apache.hadoop.hive.ql.metadata.HiveException: java.net.ConnectException: Call From m.hadoop.com/192.168.10.11 to m.hadoop.com:9000 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused
hive (default)> select * from users;
OK
users.name      users.age
Ytc     25
Tom     24
Jery    12
Time taken: 1.443 seconds, Fetched: 3 row(s)
hive (default)> 

参考文献:


http://blog.itpub.net/31451369/viewspace-2153698/



版权声明:本文为sunrising_hill原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。