搭建集群的模式有三种
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 root@node01
因为node02有一种操作是node02的ZKFC把node01的active NN关闭,所以需要免密登陆
2.删除之前四台虚拟机的所有hadoop包,我们重新配置
重新解压后修改以下配置文件
hdfs-site.xml
<property>
<!--两个NN的逻辑名-->
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<!--两个NN