这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战
一、前言
HDFS其实本质说白了就是个分布式文件系统。比较学习法:那就得考虑一下,比如跟
fastdfs之类的Java架构领域的一些分布式文件系统相比,其特点和优势在哪儿呢?
先简单了解下,Hadoop 由三个模块组成:
- 分布式存储
HDFS - 分布式计算
MapReduce - 资源调度引擎
Yarn
HDFS 整体架构设计理念:
- 支持超大数据集
- 绝对能够应对硬件的故障:可以自动探查到集群中某一台机器故障了,然后可以自动对故障进行恢复。
- 流式数据处理:用这个所谓的流式数据处理,其实主要就是为了保证高吞吐量的文件读写,而不是低延迟的文件读写。
- 简化的数据一致性模型:一个文件只能一次写入,然后之后就只能追加,不能随便改之前的数据了,这样就没有数据读写并发冲突,以及数据如何维护一致性的问题了。
- 尽量移动计算,但是不要移动数据:如果要对分布在多台机器上的数据,进行分布式计算,使用比如
mapreduce或者是spark都可以,那么此时尽可能让计算任务是靠近这个数据,而不是说在集群里通过网络胡乱传输数据,那样会导致性能极差。
其理念会整成图,如下:
分布式系统中有很多架构,其中最经典的是:
master-slave模式(主从模式)。
HDFS 作为一种分布式的数据存储系统,也是用的 master-slave 模式:
-
master主节点:NameNode进程,在一个普通的HDFS集群架构里只有一个,可以理解为整个集群的指挥中心。 -
slave从节点:DataNode进程,每台机器上都会有,负责对这台机器上的数据进行存储。
HDFS 架构图,如下:
NameNode 和 DataNode 用文件系统来打比方,就是:
-
NameNode:主要存放文件系统命名空间(filesystem namespace),即目录与文件的嵌套关系文件
test.txt存储在目录/a/b/c/下,其完整路径为:/a/b/c/test.txt -
DataNode:负责存储数据,每台机器都会部署一个DataNode节点举个栗子:一个大文件会被拆分成3个部分,每个部分为一个文件块(
block),会存储在不同机器上DataNode就会负责管理自己那些文件
那么读取文件过程就很清晰了:
- 先去
NameNode问下,我要读取text.txt文件,这个文件对应哪几个block?都在哪几个DataNode上存储? - 然后与各个
DataNode通信,读取对应的block
1. 文件系统元数据的管理机制
HDFS 的 NameNode 的元数据存储机制,是通过 fsimage 和 edits log 来实现的。
主要管理过程有:
-
NameNode修改元数据:接收请求,修改元数据 -
NameNode重启:NameNode重启,元数据重建过程 -
NameNode修改元数据
举个栗子:创建一个目录过程如下:
-
客户端发起请求,创建一个目录
hadoop fs -mkdir /usr/dir-test -
NameNode先在内存中生成对应的元数据/usr/dir-test -
再往日志文件
edits log追加一行日志:创建了一个目录:/usr/dir-test -
NameNode重启
情景还原:
-
客户端频繁修改数据,
NameNode也会相应操作内存中的元数据,edits log会变得越来越大。 -
此时,重启了
NameNode,那么会加载磁盘文件fsimage和edits log加载到内存中,生成对应的元数据。 -
同时,生成完成元数据之后,会写回
fsimage中去,同时将edits log删除
2. Hadoop 1.x 中的 SecondaryNameNode
如果两次 NameNode 重启间隔特别长:
- 那么,
edits log会变得无比巨大,那么下次重启NameNode的速度会很慢,因为要把edits log和fsimage进行合并。 - 那如何避免
NameNode重启时间过长呢?
这时候,在 Hadoop 1.x 的时候,有 SecondaryNameNode 的 check point 机制:
- 会将
NameNode的edits log和fsimage拉取到本地磁盘 - 把
edits log和fsimage加载到内存进行合并,合并出最新的元数据 - 再将最新的元数据写到磁盘中
fsimage - 再将最新的
fsimage推回NameNode,替换原先的fsimage - 再通知
NameNode清空旧的edits log
SecondaryNameNode 的 check point 触发机制:
- 定时:每隔
1h edits log一定量时
当然
SecondaryNameNode就相当于NameNode的一个冷备份。
3. Hadoop 1.x 中的 BackupNode
貌似没有多少人用这个。
简单提下。
BackupNode 过程如下:
- 每当
NameNode修改元数据,不落本地磁盘,直接发给BackupNode BackupNode每隔一段时间进行check point:- 将自己内存中的元数据直接写入到
fsimage - 删除旧的
edits log
- 将自己内存中的元数据直接写入到
4. Hadoop 2.x 中的双实例 HA 高可用机制
为了高可用,引入了如下组件:
active NameNode:活跃的NameNodestandby NameNode:备份NameNodejournal node:一般为3台,保证大部分节点写入edits log即可
如果感知到 active NameNode 宕机,立马切换 standby NameNode。
组件同步过程:
active NameNode:写入本地edits log同时,同步数据流给journal nodejournal node:接收edits log,同步数据流给standby NameNodestandby NameNode:接收edits log
那么如何实时感知 active NameNode 状况?如何故障转移和切换?
引入组件:
ZKFailoverController进程:简称ZKFC,每个NameNode节点上均有,会不断的监控两个NameNode,同时在zookeeper集群上(至少3个节点)维护NameNode的状态。ZKFC的HealthMonitor进程:检测NameNode是否挂了ZKFC的FailoverController进程:通知NameNode状态,找ActiveStandbyElector组件说要主备重新选举。
HA 过程如下,当 active NameNode 宕机时:
ZKFC的HealthMonitor进程 检测active NameNode宕机了,通知给FailoverControllerFailoverController找ActiveStandbyElector组件说要主备重新选举ActiveStandbyElector就会基于zk集群完成主备选举,会选举出来standby namenode作为主zk会通知standby机器上的ZKFC中的ActiveStandbyElector组件,ActiveStandbyElector通知FailoverController要切换standby为active了,然后FailoverController再通知standby namenode切换为active namenode
checkpoint 是怎么执行的呢?
- 在
standy namenode上,会运行一个CheckpointerThread后台线程,他默认是要么1小时一次,要么是有100万条edits log没有合并到fsimage去了,此时就会执行一个checkpoint操作。 - 将内存中最新的那份
fsimage写到磁盘文件上的fsimage文件里去,同时清空掉edits log - 最新的
fsimage文件发送到active namenode上去覆盖之前旧的fsimage,同时将active namenode的edtis logs给清空掉
5. 分布式存储机制
datanode 需要向 namenode 同步信息:
- 健康状况:发送心跳
- 数据分布状态:
block数据块对应,发送block report
6. 数据副本的容错机制
一个文件拆成 10 个 block数据块,分布在 10台机器上,每台机器存储1个 block,如果其中一台机器故障了呢?
机器故障:磁盘故障、网络故障、内存耗尽、
CPU耗尽、或者机器宕机。
为了对集群中的各种机器的故障进行容错,有一个关键的机制,就是副本机制:
replication factor复制因子:这是一个可以设置的关键性的参数
副本机制实现过程,假设每个 block 3个副本:
namenode会根据复制算法挑选出3个datanode,每个datanode存放一个block,返回给客户端- 客户端先往第一个
datanode写入一个block,接着datanode将这个block复制给第二个datanode,然后第二个datanode再将block复制给第三个datanode。
namenode 在分配 block 到 datanode 时候,有一个关键性的机制,叫做机架感知特性(rack aware)。
同一个机架上的机器之间通信速度,要比不同机架上的机器之间的通信速度快的多了。
namenode比如默认一般一个block是3个副本,这样可以把2个副本放在一个机架上,然后第3个副本放在另外一个机架上。