大白话 Hadoop

369 阅读7分钟

这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战

一、前言

HDFS 其实本质说白了就是个分布式文件系统。

比较学习法:那就得考虑一下,比如跟 fastdfs 之类的 Java 架构领域的一些分布式文件系统相比,其特点和优势在哪儿呢?

先简单了解下,Hadoop 由三个模块组成:

  1. 分布式存储 HDFS
  2. 分布式计算 MapReduce
  3. 资源调度引擎 Yarn

HDFS 整体架构设计理念:

  1. 支持超大数据集
  2. 绝对能够应对硬件的故障:可以自动探查到集群中某一台机器故障了,然后可以自动对故障进行恢复。
  3. 流式数据处理:用这个所谓的流式数据处理,其实主要就是为了保证高吞吐量的文件读写,而不是低延迟的文件读写。
  4. 简化的数据一致性模型:一个文件只能一次写入,然后之后就只能追加,不能随便改之前的数据了,这样就没有数据读写并发冲突,以及数据如何维护一致性的问题了。
  5. 尽量移动计算,但是不要移动数据:如果要对分布在多台机器上的数据,进行分布式计算,使用比如 mapreduce 或者是 spark 都可以,那么此时尽可能让计算任务是靠近这个数据,而不是说在集群里通过网络胡乱传输数据,那样会导致性能极差。

其理念会整成图,如下:

hdfs-分布式存储架构.png

分布式系统中有很多架构,其中最经典的是:master-slave 模式(主从模式)。

HDFS 作为一种分布式的数据存储系统,也是用的 master-slave 模式:

  • master 主节点:NameNode 进程,在一个普通的 HDFS 集群架构里只有一个,可以理解为整个集群的指挥中心。

  • slave 从节点:DataNode 进程,每台机器上都会有,负责对这台机器上的数据进行存储。

HDFS 架构图,如下: 2020-02-0317:22.png

NameNodeDataNode 用文件系统来打比方,就是:

  • NameNode:主要存放文件系统命名空间(filesystem namespace),即目录与文件的嵌套关系

    文件 test.txt 存储在目录 /a/b/c/下,其完整路径为:/a/b/c/test.txt

  • DataNode:负责存储数据,每台机器都会部署一个 DataNode 节点

    举个栗子:一个大文件会被拆分成3个部分,每个部分为一个文件块(block),会存储在不同机器上 DataNode 就会负责管理自己那些文件

那么读取文件过程就很清晰了:

  1. 先去 NameNode 问下,我要读取 text.txt 文件,这个文件对应哪几个 block?都在哪几个 DataNode 上存储?
  2. 然后与各个 DataNode 通信,读取对应的 block

1. 文件系统元数据的管理机制

HDFSNameNode 的元数据存储机制,是通过 fsimageedits log 来实现的。

主要管理过程有:

  1. NameNode 修改元数据:接收请求,修改元数据

  2. NameNode 重启:NameNode 重启,元数据重建过程

  3. NameNode 修改元数据

举个栗子:创建一个目录过程如下:

  1. 客户端发起请求,创建一个目录 hadoop fs -mkdir /usr/dir-test

  2. NameNode 先在内存中生成对应的元数据 /usr/dir-test

  3. 再往日志文件 edits log 追加一行日志:创建了一个目录:/usr/dir-test hdfs-元数据管理.png

  4. NameNode 重启

情景还原:

  1. 客户端频繁修改数据,NameNode 也会相应操作内存中的元数据,edits log 会变得越来越大。

  2. 此时,重启了 NameNode,那么会加载磁盘文件 fsimageedits log 加载到内存中,生成对应的元数据。

  3. 同时,生成完成元数据之后,会写回 fsimage 中去,同时将 edits log 删除 hdfs-元数据管理-重启.png


2. Hadoop 1.x 中的 SecondaryNameNode

如果两次 NameNode 重启间隔特别长:

  • 那么,edits log 会变得无比巨大,那么下次重启 NameNode 的速度会很慢,因为要把 edits logfsimage 进行合并。
  • 那如何避免 NameNode 重启时间过长呢?

这时候,在 Hadoop 1.x 的时候,有 SecondaryNameNodecheck point 机制:

  1. 会将 NameNodeedits logfsimage 拉取到本地磁盘
  2. edits logfsimage 加载到内存进行合并,合并出最新的元数据
  3. 再将最新的元数据写到磁盘中 fsimage
  4. 再将最新的 fsimage 推回 NameNode ,替换原先的 fsimage
  5. 再通知 NameNode 清空旧的 edits log hdfs-secondNameNode.png

SecondaryNameNodecheck point 触发机制:

  1. 定时:每隔 1h
  2. edits log 一定量时

当然 SecondaryNameNode 就相当于 NameNode 的一个冷备份。


3. Hadoop 1.x 中的 BackupNode

貌似没有多少人用这个。

简单提下。

BackupNode 过程如下:

  1. 每当NameNode 修改元数据,不落本地磁盘,直接发给 BackupNode
  2. BackupNode 每隔一段时间进行check point
    1. 将自己内存中的元数据直接写入到 fsimage
    2. 删除旧的 edits log hdfs-BackupNode.png

4. Hadoop 2.x 中的双实例 HA 高可用机制

为了高可用,引入了如下组件:

  • active NameNode:活跃的 NameNode
  • standby NameNode:备份 NameNode
  • journal node:一般为3台,保证大部分节点写入 edits log 即可

如果感知到 active NameNode 宕机,立马切换 standby NameNode

组件同步过程:

  1. active NameNode :写入本地 edits log 同时,同步数据流给 journal node
  2. journal node :接收 edits log,同步数据流给 standby NameNode
  3. standby NameNode :接收 edits log hdfs-HA.png

那么如何实时感知 active NameNode 状况?如何故障转移和切换?

引入组件:

  • ZKFailoverController 进程:简称 ZKFC,每个 NameNode 节点上均有,会不断的监控两个 NameNode,同时在 zookeeper 集群上(至少3个节点)维护 NameNode 的状态。
  • ZKFCHealthMonitor进程:检测 NameNode 是否挂了
  • ZKFCFailoverController进程:通知 NameNode 状态,找 ActiveStandbyElector 组件说要主备重新选举。

HA 过程如下,当 active NameNode 宕机时:

  1. ZKFCHealthMonitor进程 检测 active NameNode 宕机了,通知给 FailoverController
  2. FailoverControllerActiveStandbyElector 组件说要主备重新选举
  3. ActiveStandbyElector 就会基于 zk 集群完成主备选举,会选举出来 standby namenode 作为主
  4. zk 会通知 standby 机器上的 ZKFC 中的 ActiveStandbyElector 组件,ActiveStandbyElector 通知FailoverController 要切换 standbyactive 了,然后 FailoverController 再通知 standby namenode 切换为 active namenode

hdfs-HA-2.png

checkpoint 是怎么执行的呢?

  1. standy namenode 上,会运行一个 CheckpointerThread 后台线程,他默认是要么1小时一次,要么是有100万条 edits log 没有合并到 fsimage 去了,此时就会执行一个 checkpoint 操作。
  2. 将内存中最新的那份 fsimage 写到磁盘文件上的 fsimage 文件里去,同时清空掉 edits log
  3. 最新的 fsimage 文件发送到 active namenode 上去覆盖之前旧的 fsimage,同时将 active namenodeedtis logs给清空掉

5. 分布式存储机制

datanode 需要向 namenode 同步信息:

  • 健康状况:发送心跳
  • 数据分布状态:block 数据块对应,发送 block report hdfs-存储机制.png

6. 数据副本的容错机制

一个文件拆成 10 个 block数据块,分布在 10台机器上,每台机器存储1个 block,如果其中一台机器故障了呢?

机器故障:磁盘故障、网络故障、内存耗尽、CPU耗尽、或者机器宕机。

为了对集群中的各种机器的故障进行容错,有一个关键的机制,就是副本机制:

  • replication factor 复制因子:这是一个可以设置的关键性的参数

副本机制实现过程,假设每个 block 3个副本:

  1. namenode 会根据复制算法挑选出3个datanode,每个 datanode 存放一个 block,返回给客户端
  2. 客户端先往第一个 datanode 写入一个 block,接着 datanode 将这个 block 复制给第二个 datanode,然后第二个 datanode 再将 block 复制给第三个 datanode

hdfs-数据副本容错机制.png

namenode 在分配 blockdatanode 时候,有一个关键性的机制,叫做机架感知特性(rack aware)。

同一个机架上的机器之间通信速度,要比不同机架上的机器之间的通信速度快的多了。namenode 比如默认一般一个 block 是3个副本,这样可以把2个副本放在一个机架上,然后第3个副本放在另外一个机架上。

hdfs-数据副本容错机制-2.png