搭建集群的模式有三种
1.伪分布式:在一台服务器上,启动多个线程分别代表多个角色(因为角色在集群中使用进程表现的)
2.完全分布式:在多台服务器上,每台服务器启动不同角色的进程,多台服务器构成集群
3.高可用的完全分布式
本次搭建是在完全分布式的基础上搭建的,完全分布式请看 完全分布式的搭建.
.
- 首先为什么会提出高可用的完全分布式呢?
因为以往的架构,毕竟是单节点(namenode),虽有SNN为其承担部分功能(持久化到本地),但SNN毕竟不是namenode,当namenode禁不住大量用户的请求(汇报)挂掉之后,SNN并不能承担起来namenode的功能 - 高可用的完全分布式对比完全分布式有什么区别?
高可用的完全分布式没有了SNN节点,多了JournalNode集群、ZooKeeper集群和ZKFC,还有一个备用NameNode(standby)它来实现SNN的功能,并作为active NN的热备。
如图所示
- Standby NameNode的作用
- 作为Active NameNode的热备,当其崩溃时,快速地切换为Active NameNode
- 充当SNN的角色,从JournalNode集群中拿到最新的edits文件进行重演合并后形成FSImage推送给Active NameNode - JournalNode集群的作用
-存储由Active NameNode发送的edits文件 - Zookeeper集群的作用
- 来监控Active NameNode的健康状态,当其挂掉后选取新的Active NameNode,但是Active NameNode很忙没法发送自己的状态,所有又有了ZKFC
- 当Active NameNode挂掉之后,他会想Standby NameNode节点的ZKFC发送一条信息,让ZKFC把Standby NameNode变为Active NameNode - ZKFC的作用
-主动监控两个NN的状态,同时与Zookeeper相连
-根据Zookeeper的指令对NN进行状态的改变
架构的几个问题
- 为什么要使用JournalNode集群而不是JournalNode节点?
- 数据安全
- 以防JournalNode节点挂掉导致数据的丢失 - 既然Active NN与Standby NN会发生状态的变化,如何保证他们之间的数据同步,才能无缝地对外服务呢?
- 他们通过JournalNode来实现edits文件的共享,Standby NameNode重演合并后的FSImage推送给Active NN保证两者的元数据信息一致。 - Active NameNode在向JournalNode集群中上传edits文件时是否提供服务?
- 不会
- 当NameNode上传Edits文件至JournalNode集群节点的半数以上时(并行写入edits文件),而不是上传到所有的节点,这样效率太低 - 为什么Active Name Node要提交到JournalNode集群的半数以上的节点?
-JournalNode集群中有个势力范围的概念,当Journal Node集群因为网卡的原因无法同信,就会分裂成几个组织,当每个组织的节点数小于势力范围时,就会自杀,为了保证只有一个JournalNode集群,把势力范围定为半数以上的节点数
-这样才会使Standby NN一直读取到最新的edits文件
.
.
.
当两个ZFKC都挂掉之后,此时这个集群相当于孤立了Zookeeper集群,当Active NN挂掉之后,需要手动把Standby NN 变为Active NN.
.
.
.
现在了解了高可用的完全分布式的架构之后,我们开始搭建它的环境,首先是四台虚拟机分别代表的角色如下表
| … | Active NameNode | Standby NameNode | DataNode | Zookeeper | ZKFC | JournalNode |
|---|---|---|---|---|---|---|
| node01 | √ | - | - | - | √ | √ |
| node02 | - | √ | √ | √ | √ | √ |
| node03 | - | - | √ | √ | - | √ |
| node04 | - | - | √ | √ | - | - |
1.在完全分布式的基础上,需要配置node02对于node01的面密码登陆
node02上运行
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
因为node02有一种操作是node02的ZKFC把node01的active NN关闭,所以需要免密登陆
2.删除之前四台虚拟机的所有hadoop包,我们重新配置
重新解压后修改以下配置文件
hdfs-site.xml
<property>
<!--两个NN的逻辑名-->
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<!--两个NN的名字-->
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<!--Active NN的别名-->
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>node01:8020</value>
</property>
<property>
<!--Standby NN的别名-->
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node02:8020</value>
</property>
<property>
<!--Active NN的地址-->
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>node01:50070</value>
</property>
<property>
<!--Standby NN的地址-->
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>node02:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node01:8485;node02:8485;node03:8485/mycluster</value>
</property>
<property>
<!--JournalNode保存edits文件的地址-->
<name>dfs.journalnode.edits.dir</name>
<value>/var/sxt/hadoop/ha/jn</value>
</property>
<property>
<!--代理,来区分两个NN-->
<name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<!--拿自己的私钥去连接node01-->
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<property>
<!--打开ZKFC-->
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
core-site.xml
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>node02:2181,node03:2181,node04:2181</value>
</property>
<!-- 指定hadoop运行时产生临时文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/var/abc/hadoop/local</value>
</property>
slaves
node02
node03
node04
sudo vim ${HADOOP_HOME}/etc/hadoop/hadoop-env.sh
# 修改JAVA_HOME的环境配置为如下所示:
export JAVA_HOME=/opt/software/jdk1.8.0_151
把配置好的Hadoop包发送给每台机器
.
2.搭建Zookeeper集群
1.解压Zookeeper压缩包
2.修改conf路径下的zoo_sample.cfg为zoo.cfg
3.更改zoo.cfg的内容
4.记住zoo.cfg中的路径:dataDir=/var/zxj/zookeeper
5.在此路径下创建myid文件,在这个文件中写上当前节点ID号
6.将配置好的zookeeper安装包拷贝到node03 node04
7.拷贝完毕后,在各自节点上创建myid号,ID号要依次递增
zoo.cfg
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/var/zxj/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=node02:2888:3888
server.2=node03:2888:3888
server.3=node04:2888:3888
创建myid文件例如:
vim /var/zxj/zookeeper/myid
1
发送给node03,node04
scp -r zookeeper node03:`pwd`
scp -r zookeeper node04:`pwd`
搭建好后,在其的bin目录下,运行./zkServer.sh start 开启zookeeper集群
.
3.启动的流程
1.在node01、02、03中先开启Journal Node。hadoop-daemon.sh start journalnode
为什么在NN初始化之前启动它,因为NN初始化产生的edits要放在JournalNode中
2.选择一台Active NN进行格式化,hdfs namenode -format
3.启动此NN,hadoop-daemon.sh start namenode
4.在standby NN中同步Active NN的数据,hdfs namenode -bootstrapStandby
5.初始化ZKFC,hdfs zkfc -formatZK
6.关闭所有进程,stop-dfs.sh
7.启动:start-dfs.sh