文章目录
1、前言
前面的博客中链接已经给出Hadoop3.1.2和yarn的完整部署(但还不是高可用),此篇博客将给出Hadoop的高可用部署,以及HBase高可用,为之后应用数据层开发提供底层的BigTable支持。前面的文章,我们已经深入讨论的ZooKeeper这个中间件的原理以及分布式锁的实现,事实上zookeeper使用最广泛的场景是“选举”主从角色,Hadoop以及Hbase的高可用(主从架构)正是通过ZooKeeper的临时节点机制实现。
以下的配置会跳过Hadoop3.1.2的部署,仅给出ZooKeeper分布式物理方式部署、以及HBase的部署过程、测试结果。
2、ZooKeeper与Hadoop、HBase的关系
ZooKeeper作为协调器,在大数据组件中提供:管理Hadoop集群中的NameNode、HBase中HBaseMaster的选举,节点之间状态同步等。例如在HBase中,存储HBase的Schema,实时监控HRegionServer,存储所有Region的寻址入口,当然还有最常见的功能就是保证HBase集群中只有一个Master。
3、Hadoop与HBase的关系
完整的hadoop组件环境架构图
首先HBase是一个分布式的、面向列的开源数据库,正是业务数据需要列数据库的支持以及该数据库能够支持业务超大数据集扩展存储的需求,HBase当然作为中间件选型的首选。上图描述Hadoop组件生态中的各层系统。其中,HBase位于结构化存储层,Hadoop的HDFS为HBase提供了高可靠性、分布式的底层存储支持,Hadoop MapReduce、Spark为HBase提供了高性能的计算能力,Zookeeper为HBase提供了稳定选举服务和failover机制。
此外,Pig和Hive还为HBase提供了高层语言支持,使得在HBase上进行数据统计处理变的非常简单。 Sqoop则为HBase提供了方便的RDBMS数据导入功能,使得传统数据库数据向HBase中迁移变的非常方便。
(当然本blog也会针对Hbase的架构原理做出一篇文章讨论)
其实,本博客有关大数据的多篇文章的内容,都是为了能够梳理出大数据多个组件全流程部署、架构原理、业务数据应用开发到BI的呈现的完整技术内容,以实现大数据库开发工程师必备的项目经历。
4、架构资源规划
nn | dn1 | dn2 |
---|---|---|
1vcpu,2G内存 | 1vcpu,1G内存 | 1vcpu,1G内存 |
NameNode | NameNode | |
DataNode | DataNode | DataNode |
JournalNode | JournalNode | JournalNode |
DFSZKFailoverController | DFSZKFailoverController | DFSZKFailoverController |
ResourceManager | ResourceManager | |
NodeManager | NodeManager | NodeManager |
JobHistoryServer | JobHistoryServer | |
ZooKeeper | ZooKeeper | ZooKeeper |
HBase master | HBase master | |
RegionServer | RegionServer | RegionServer |
Hadoop版本、JDK版本、HBase版本、ZooKeeper版本参考如下:
[root@nn opt]# ls
hadoop-3.1.2 jdk1.8.0_161
hbase-2.1.7 zookeeper-3.4.14
关于Hadoop与HBase的兼容性,官方已经给出Hadoop version support matrix,目前HBase2.1.x、HBase2.2.x支持Hadoop 3.1.1+(Tested to be fully-functional)。关于版本兼容分析,很多类似文章也有提到,但他们所提到的兼容比对情况已过时,故最佳途径应及时查阅官网最新发布的内容。
5、ZooKeeper集群设置
5.1 设置nn节点的zoo.conf
[root@nn conf]# pwd
/opt/zookeeper-3.4.14/conf
# 拷贝zoo_sample.cfg并重命名为zoo.cfg :
[root@nn conf]# cp zoo_sample.cfg zoo.conf
# 修改 zoo.cfg
[root@nn conf] vi zoo.cfg
# data目录需自行创建,添加:
dataDir=/opt/zookeeper-3.4.14/data
# 在该文件最后添加,指定zookeeper集群主机及端口,节点数必须为奇数
server.1=nn:2888:3888
server.2=dn1:2888:3888
server.3=dn2:2888:3888
# 在/opt/zookeeper-3.4.14/data目录下创建myid文件
[root@nn data]# pwd
/opt/zookeeper-3.4.14/data
[root@nn data]# touch myid
[root@nn data]# ls
myid
# 文件内容为1,即表示当前节点为在zoo.cfg中指定的server.1
5.2 将zookeeper目录拷贝到dn1、dn2节点上,并更改对于的myid
[root@nn opt]# scp -r zookeeper-3.4.14/ dn1:/opt
[root@nn opt]# scp -r zookeeper-3.4.14/ dn2:/opt
# 更改dn1 myid内容为2,dn2 myid内容为3
5.3 设置zk的全局环境变量
在三个节点上都要配置
[root@nn opt] vi /etc/profile
# 新增
ZOOKEEPER_HOME=/opt/zookeeper-3.4.14
export PATH=$ZOOKEEPER_HOME/bin:$PATH
source ~/.bash_profile
5.4 启动zk集群
在每个节点上运行zkServer.sh start
查看三个节点的zk角色
# nn节点
[root@nn ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower
# dn1节点
[root@dn1 opt]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: leader
# dn2节点
[root@dn2 opt]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.14/bin/../conf/zoo.cfg
Mode: follower
使用jps查看zk的进程QuorumPeerMain
QuorumPeerMain是zookeeper集群的启动入口类,用来加载配置启动QuorumPeer线程
[root@nn opt]# jps
1907 Jps
1775 QuorumPeerMain
[root@dn1 opt]# jps
16226 Jps
16201 QuorumPeerMain
[root@dn2 opt]# jps
5824 QuorumPeerMain
5861 Jps
注意:如果某个节点使用jps命令后,没有QuorumPeerMain进程,一般是因为zk的端口号2181被占用,在/opt/zookeeper-3.4.14
目录中,zookeeper.out执行日志会给相应的提示。
[root@nn zookeeper-3.4.14]# ls
bin ivy.xml README.md zookeeper-3.4.14.jar.sha1 zookeeper.out
…
以下为之前docker方式部署zk时占用了2181端口
[root@dn2 zookeeper-3.4.14]# ss -tnlp |grep 2181
LISTEN 0 128 :::2181 :::* users:(("docker-proxy",pid=1499,fd=4))
# kill docker占用的2181进程,再重新启动zk即可。
6、Hadoop HA配置详细说明
首先配置hadoop的jdk路径:
vi hadoop-env.sh
JAVA_HOME=/opt/jdk1.8.0_161
6.1 core-site.xml 加入zk服务
<configuration>
<!-- hdfs地址,单点模式值为namenode主节点名,本测试为HA模式,需设置为nameservice 的名字-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdapp</value>
</property>
<!-- 这里的路径默认是NameNode、DataNode、JournalNode等存放数据的公共目录,也可以单独指定 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop-3.1.2/tmp</value>
</property>
<!--加入zk服务,不少于三个节点-->
<property>
<name>ha.zookeeper.quorum</name>
<value>nn:2181,dn1:2181,dn2:2181</value>
</property>
</configuration>
<!--设置web访问用户,否则web端浏览hdfs文件目录会提权限不足-->
<property>
<name>hadoop.http.staticuser.user</name>
<value>hadoop</value>
</property>
6.2 hdfs-site.xml
因为要配置hadoop HA,因此这部分的属性项比较多,这部分内容参考
Apache官网HA配置,官网已经给出非常详细且易懂的描述。
<configuration>
<!-- hadoop HA 配置开始 -->
<!-- 为namenode集群起一个services name,名字和core-site.xml的fs.defaultFS指定的一致 -->
<property>
<name>dfs.nameservices</name>
<value>hdapp</value>
</property>
<!-- nameservice 包含哪些namenode,为各个namenode起名 -->
<property>
<name>dfs.ha.namenodes.hdapp</name>
<value>nn,dn2</value>
</property>
<!-- 指定nn的namenode的rpc地址和端口号,rpc用来和datanode通讯 -->
<property>
<name>dfs.namenode.rpc-address.hdapp.nn</name>
<value>nn:9000</value>
</property>
<!-- 指定dn2的namenode的rpc地址和端口号,rpc用来和datanode通讯 -->
<property>
<name>dfs.namenode.rpc-address.hdapp.dn2</name>
<value>dn2:9000</value>
</property>
<!--名为nn的namenode的http地址和端口号,用来和web客户端通讯 -->
<property>
<name>dfs.namenode.http-address.hdapp.nn</name>
<value>nn:50070</value>
</property>
<!-- 名为dn2的namenode的http地址和端口号,用来和web客户端通讯 -->
<property>
<name>dfs.namenode.http-address.hdapp.dn2</name>
<value>dn2:50070</value>
</property>
<!-- namenode间用于共享编辑日志的journal节点列表/hdapp是表示日志存储的在hdfs上根路径,为多个HA可公用服务器进行数据存储,节约服务器成本 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://nn:8485;dn1:8485;dn2:8485/hdapp</value>
</property>
<!-- journalnode 上用于存放edits日志的目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/hadoop-3.1.2/tmp/dfs/journalnode</value>
</property>
<!-- 指定该集群出现故障时,是否自动切换到另一台namenode -->
<property>
<name>dfs.ha.automatic-failover.enabled.hdapp</name>
<value>true</value>
</property>
<!-- 客户端连接可用状态的NameNode所用的代理类 -->
<property>
<name>dfs.client.failover.proxy.provider.hdapp</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 一旦需要NameNode切换,使用两方式进行操作,优先使用sshfence -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence
shell(/bin/true)
</value>
</property>
<!-- 如果使用ssh进行故障切换,使用ssh通信时指定私钥所在位置 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- ssh连接超时超时时间,30s -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
<!-- HA配置结束 -->
<!-- 设置 hdfs 副本数量,这里跟节点数量一致 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
</configuration>
注意在sshfence设置中,若ssh用户名不是root,且ssh端口不是默认22,则需改为
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence([[my_hadoop][:31900]])</value>
</property>
<property>
以上设置非常重要,涉及sshfence能否正常切换主备hadoop服务
官网给出自定义shell脚本去切换namenode进程
#shell - run an arbitrary shell command to fence the Active NameNode
#The shell fencing method runs an arbitrary shell command. It may be configured like so:
<property>
<name>dfs.ha.fencing.methods</name>
<value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>
</property>
6.3 mapred-site.xml
<!-- 采用yarn作为mapreduce的资源调度框架 -->
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 打开Jobhistory -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>nn:10020</value>
</property>
<!-- 指定nn作为jobhistory服务器 -->
<property>