HDFS 内部工作机制
HDFS 内部工作机制
-
HDFS集群分为两大角色:NameNode、DataNode (Secondary Namenode)
-
NameNode 负责管理整个文件系统的元数据
-
DataNode 负责管理用户的文件块(Block)
-
文件会按照固定的大小(默认 128 M)切成若干文件块(Block)后分布式存储在若干台 DataNode 服务器上
-
每一个文件块可以有多个副本,并存放在不同的 DataNode 服务器上
-
DataNode 会定期向 NameNode 汇报自身所保存的文件块(Block)信息,而 NameNode 则会负责保持文件的副本数量
HDFS 的内部工作机制对客户端保持透明,客户端通过向 NameNode 发送请求来访问 HDFS 存放的文件
HDFS 写数据流程
# 上传 file.data 到 HDFS (300M)
hadoop fs -put file.data /data/file.data
流程图
详细步骤
- 使用客户端命令行向 HDFS 上传 file.data(300M)文件时,客户端会向集群中的 NameNode 通信请求上传文件到 HDFS 目录树的 /data/file.data 路径
- NameNode 收到客户端请求后会检查 /data 目录 和 /data/file.data 文件是否存在,如果不存在则向客户端返回可以进行上传文件
- 由于上传的 file.data 文件是 300M(默认文件数据块 128M),文件需要被切分成三个文件数据库(Block)依次进行上传。客户端先向 NameNode 请求上传第一个文件数据块(Block)以及告诉 NameNode 存放文件数据块的副本数量(默认 3 个),NameNode 则会返回 3 个可以上传的 DataNode(假设是 DataNode1、DataNode2、DataNode4)
- 客户端选择与 DataNode1 建立网络连接,而 DataNode1 接着与 DataNode2 建立网络连接,DataNode2 与DataNode4 建立网络连接,(本质就是 RPC 远程调用形成 pipeline 网络连接链路通路)。通道建立完毕后,DataNode1 会向客户端作出应答,告诉客户端可以上传第一个文件数据块(Block)
- 客户端收到 DataNode1 的应答后,以 packet 包为单位向 DataNode1 上传数据流,上传的数据流是先存放到 DataNode1 的一个缓冲区,再缓冲区同时向其他 DataNode 缓冲区传,缓冲区再写到磁盘
- 上传过程中,DataNode 会进行校验,校验失败则传输失败,但是只要有一个 DataNode 传输成功即可。因为 NameNode 会判断成功的数量与备份要求的是否一致,不一致的话则会对数据进行同步使得一致。
- 第一个文件数据块(Block)上传完成后,会再重新与 NameNode 建立网络连接,请求上传第二个文件数据块(Block),即重复第3步流程,直到所有文件数据快(Block)全部上传为止。
副本放置策略 - 就近原则
挑选 DataNode 主要考虑空间与距离因素
- 第一个副本考虑选择与客户端距离最近的 DataNode(同机架)
- 第二个副本考虑跨机架选择一个 DataNode(增加副本的可靠性)
- 第三个副本挑选与第一个 DataNode 同机架的 DataNode(配置机架感知)
为了最小化全局带宽消耗和读取延迟,HDFS 试图满足来自离客户端最近的副本的读取请求。如果在与客户端相同的机架上存在一个副本,则首选该副本来满足读请求。如果 HDFS 集群跨越多个数据中心,那么驻留在本地数据中心的副本优于任何远程副本。
NameNode 安全模式(SafeMode)
- 在启动 NameNode 时,NameNode 进入一个称为 安全模式(SafeMode)的特殊状态。当 NameNode 处于该状态,不会发生文件数据块的复制。
- NameNode 从数据节点接收心跳和 BlockReport 消息。Blockreport包含DataNode托管的数据块列表。每个块都有一个指定的最小副本数量。当该数据块的最小副本数量(dfs.namenode.replication.min =1)已与
NameNode 签入时,就认为该块是安全复制的。当安全复制的数据块的可配置百分比(
dfs.namenode.safemode.threshold-pct =0.999f)通过NameNode(加上额外的30秒)检查后,
NameNode将退出安全模式状态。然后,它确定仍然少于指定副本数量的数据块列表(如果有的话)。然后
NameNode将这些块复制到其他数据节点。
安全模式(Safemode )开启时不能有写操作
安全模式(SafeMode)命令:
客户端写数据 DataNode 故障处理
- 客户端在写入文件数据块到 DataNode 发生故障时,客户端会关闭与 DataNode 之间的网络通信 pipeline 管线,以确保故障节点 pipeline 管线下游的 DataNode 不会漏掉 packet 数据包
- 客户端将故障 DataNode 通知给 NameNode,以便故障的 DataNode 在恢复后可以删除存储的部分数据块
- 客户端基于另外两个正常的 DataNode 构建一条新的 pipeline 管线,将剩下的文件数据块写入 pipeline 管线中正常的 DataNode
- 当 NameNode 注意到文件数据块副本数量不足的时候,就会在另一个 DataNode 节点上创建一个新的副本,后续的数据块则继续正常处理
HDFS 读数据流程
# 从 HDFS 下载 /data/file.data(300M) 文件到本地系统
hadoop fs -get /data/file.data ./
详细步骤
- 使用客户端命令行从 HDFS 下载 /data/file.data(300M)文件时,客户端与 NameNode 建立网络连接,并请求要下载的文件;NameNode 查看元数据,找到下载文件被切割的 3 个文件数据块(Block)所存放的 DataNode 信息,并返回给客户端
- 客户端首先下载第一个文件数据块(Block),而第一个文件数据块(Block)在 3 个 DataNode 上都有其副本,客户端根据就近原则去挑选一个 DataNode 建立网络连接,并请求读取文件数据块(Block);DataNode 读取磁盘数据流,向客户端发送数据流
- 客户端接收 DataNode 发送的数据流并暂存缓存中,然后写入到本地文件中,接着客户端重复步骤1、2 来下载第二个文件数据块(Block)(和第三个文件数据块(Block),然后数据以追加的形式写入到文件中,最终合并成一个完成的文件
客户端读数据 DataNode 故障处理
- 客户端在 DataNode 上读取文件数据块(Block)时发生故障(即客户端 与 DataNode 无法正常通信),客户端会试图从故障 DataNode 最邻近的一个保存副本的 DataNode 读取文件数据块(Block)
- 客户端会记录故障的 DataNode,以确保以后不会反复读取该故障 DataNode 节点上后续的文件数据块(Block)
- 客户端会通过校验和确认从 DataNode 读取的数据是否完整,如果发现有损坏的文件数据块(Block),客户端会试图从其他保存有副本的 DataNode 读取数据,并将被损坏的块通知给 NameNode
- NameNode 记录有损坏的文件数据块的 DataNode,通知其删除数据,并创建新的文件数据块的副本,以确保副本数量的一致
NameNode 工作机制
NameNode 职责
- 负责客户端请求的响应
- 管理元数据(即 HDFS 的目录结构及每一个文件的文件数据块(Block)信息(如 block id、block 副本数量,block 的存放位置等)
- 容错处理
NameNode 管理元数据
元数据的存储
-
内存元数据
NameNode 在内存(meta data)中保存着一份实时、完整的元数据
-
磁盘元数据镜像文件
NameNode 在磁盘中保存着某个时间点元数据在内存中的镜像 fsimage 文件(类似 redis 的 RDB)
- fsimage 包含 Hadoop 文件系统中的所有目录和文件 idnode 的序列化信息(具体而言,文件包含的信息有修改时间、访问时间、块大小和组成一个文件块信息等,目录包含的信息有修改时间、访问控制权限等)
- fsimage 并不包含 DataNode 的信息,而是包含 DataNode 上文件数据块(Block)的映射信息。
- 当一个新的 DataNode 加入到集群中,DataNode 会向 NameNode 提供文件数据块(Block)的信息,而 NameNode 会定期向 DataNode 的索取文件数据块的信息,以使得 NameNode 拥有最新的文件数据块(Block)映射信息
- 由于 fsimage 包含 Hadoop 文件系统中的所有目录和文件 idnode 的序列化信息,所以如果 fsimage 文件丢失或损坏,那么即使 DataNode 上有文件数据块(Block),也无法从 DataNode 上的获取数据
-
数据操作日志文件
NameNode 会把引起元数据变化的客户端操作记录在 edits 日志文件中(类似 redis 的 AOF)
元数据目录
-
在第一次部署好 Hadoop 集群的时候,需要在 NameNode 节点上格式化磁盘
[root@node-01 etc]# hadoop namenode -format
-
格式化完成之后,将会在 NameNode 存储路径的 current 目录下创建元数据目录
current/ |-- VERSION |-- edits_* |-- fsimage_* |-- fsimage_*.md5 |-- seen_txid
-
VERSION
namespaceID=1064465530 clusterID=CID-a1afedaf-49ed-4219-bae3-7b7268fca624 cTime=1616685687133 storageType=NAME_NODE blockpoolID=BP-593175008-192.168.229.21-1616685687133 layoutVersion=-65
- namespaceID:是文件系统的唯一标识符,在文件系统首次格式化之后生成的
- clusterID:是系统生成或手动指定的集群 ID
- cTime:NameNode 存储时间的创建时间
- storageType:说明这个文件存储的是什么进程的数据结构信息
- layoutVersion:HDFS 永久性数据结构的版本信息
- blockpoolID:针对每一个 Namespace 所对应的 blockpool 的 ID(DataNode Block 目录名)
-
seen_txid
该文件中记录的是 edits 日志滚动的序号,每次重启NameNode时,NameNode就知道要将会执行edits_0000001~ edits_seen_txid 的 edits 日志文件,已更新内存元数据
-
edits_* 查看器(OEV)
oev 是 offline edits viewer(离线 edits 查看器)的缩写,该工具可以使用 oev 工具查看 edits 日志文件和 fsimage 镜像文件内容
命令格式:hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
- -p –processor 指定输出处理器: binary (二进制格式), xml (默认,XML格式),stats
- -i –inputFile 输入edits文件(如果是xml后缀,表示XML格式,其他表示二进制)
- -o –outputFile 输出文件,如果存在,则会覆盖
[root@node-01 current]# hdfs oev -i edits_inprogress_0000000000000000081 -o edits.xml
-
images_* 查看器(OIV)
oiv 是 offline image viewer 的缩写,用于将 fsimage 文件的内容转储到指定文件里以便于阅读。OIV 在处理很大的 fsimage 文件时是相当快。
命令格式:hdfs oiv -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
- -p –processor 指定输出处理器: LS、XML、FileDistribution
- -i –inputFile 输入 fsimage 文件(如果是xml后缀,表示XML格式,其他表示二进制)
- -o –outputFile 输出文件(如果存在,则会覆盖)
[root@node-01 current]# hdfs oiv -i fsimage_0000000000000000080 -p XML -o fsimage.xml
-
元数据的内存加载
- NameNode 启动时,会将磁盘中 fsimage 文件中的内容加载到内存中,之后再执行数据操作日志 edits 文件,使得内存获得一份最新最完整的元数据
- NameNode 启动后,客户端的所有更新数据操作会同步写入到 edits 日志中(fsimage 文件一般很大,直接写入会导致系统运行缓慢)
元数据的 CheckPoint(检查点)机制
-
Secondary NameNode 会定期从 NameNode 上下载 fsimage 镜像和新生成的 edits 日志,然后加载 fsimage 镜像到内存中,接着顺序解析 edits 文件,对内存中的元数据对象进行修改整合
-
整合完成后,将内存元数据序列化成一个新的 fsimage 镜像文件,并将这个 fsimage 镜像文件上传给 NameNode
-
NameNode 接收到 Secondary NameNode 发送的新 fsimage 镜像文件后,即可将旧的 fsimage 镜像文件和 edist 日志替换掉
注1:Secondary NameNode 每次做 CheckPoint 操作时,第一次 CheckPoint 需要下载 fsimage 镜像文件,以后就不用下载,因为之前已经下载过了
注2:Namenode 和 Secondary NameNode 的工作目录存储结构完全相同,当 NameNode 故障退出需要重新恢复时,可以从 Secondary NameNode 的工作目录中将 fsimage 拷贝到 NameNode 的工作目录,以恢复NameNode 的元数据
CheckPoint(检查点)操作触发条件相关配置
CheckPoint(检查点)相关配置 hdfs-size.xml 如下:
-
Secondary NameNode 检查触发条件是否满足的频率配置(默认 60 s)
dfs.namenode.checkpoint.check.period 60 -
Secondary NameNode 进程启动位置的配置
dfs.namenode.secondary.http-address node-02:9868 -
Secondary NameNode 保存元数据文件的目录配置
dfs.namenode.checkpoint.dir /root/apps/hadoop-3.2.1/data/namesecondary -
Secondary NameNode 最多重试次数(默认3次)
dfs.namenode.checkpoint.max-retries 3 -
Secondary NameNode 两次 CheckPoint 之间间隔时长(默认 1 小时)
dfs.namenode.checkpoint.period 3600
DataNode 工作机制
- DataNode 存储管理用户的文件数据块(Block),一个文件数据块(Block)在 DataNode 上以文件形式存储在磁盘上
- DataNode 定期向 NameNode 汇报自身所持有的所有文件数据块(Block)信息(汇报间隔时间由配置项 dfs.blockreport.intervalMsec 决定)
- 心跳检测默认每 3 秒检测一次(检测间隔时间由配置项 dfs.heartbeat.interval 决定),心跳检测返回结果带有 NameNode 给 DataNode 的命令(如复制文件数据块副本到另一个 DataNode 或删除某个损坏的文件数据块)
- 如果超过限定时间没有收到某个 DataNode 的心跳,NameNode 则认为该 DataNode 不可用
- DataNode 掉线后会触发副本检查机制,NameNode 会在集群内通知正常的 DataNode 进行副本复制
- Hadoop 集群运行中可以安全加入和退出一些 DataNode 节点
DataNode 职责
-
存储管理用户的文件数据块(Block)
-
数据:用户的文件数据块(Block)
-
元数据:文件数据块(Block)长度、文件数据块校验和、时间戳等
-
-
定期向 NameNode 汇报自身所持有的文件数据块(Block)信息(通过心跳信息上报)