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)
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
</property>
Secondary NameNode 进程启动位置的配置
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node-02:9868</value>
</property>
Secondary NameNode 保存元数据文件的目录配置
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value> /root/apps/hadoop-3.2.1/data/namesecondary</value>
</property>
Secondary NameNode 最多重试次数(默认3次)
<property>
<name>dfs.namenode.checkpoint.max-retries</name>
<value>3</value>
</property>
Secondary NameNode 两次 CheckPoint 之间间隔时长(默认 1 小时)
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
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)信息(通过心跳信息上报)
<!-- 设置 datanode 向 namenode 报告 block 信息的时间间隔(默认6小时)
<property>
<name>dfs.blockreport.intervalMsec</name>
<value>21600000</value>
<description>Determines block reporting interval in milliseconds.</description>
</property>
DataNode 掉线时限参数设置
DateNode 以固定周期向 NameNode 发送心跳,NameNode 如果一段时间内没有收到心跳,就会标记 DateNode 为故障宕机,这段时间叫做 DataNode 超时时长。
timeout = rtbeat.recheck.interval + 10 * dfs.heartbeat.interval
- DataNode 核查心跳间隔时长(默认 5 分钟)
<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
<description>This time decides the interval to check for expired datanodes. With this value and dfs.heartbeat.interval, the interval of deciding the datanode is stale or not is also
calculated.The unit of this configuration is millisecond.
</description>
</property>
- DataNode 心跳检测间隔时长(默认 3 秒)
<property>
<name>dfs.heartbeat.interval</name>
<value>3</value>
<description>Determines datanode heartbeat interval in seconds. Can use the following suffix (case insensitive): ms(millis), s(sec), m(min), h(hour), d(day) to specify the time (such as 2s, 2m, 1h, etc.). Or provide complete number in seconds (such as 30 for 30 seconds).
</description>
</property>
DataNode 目录结构
与 NameNode 不同,DataNode 存储目录是初始阶段自动创建的,不需要额外的格式化
VERSION(datanode/current/)
[root@node-01 data]# cat datanode/current/VERSION
storageID=DS-89dfa113-a168-4eed-87c5-c25d024e49e0
clusterID=CID-a1afedaf-49ed-4219-bae3-7b7268fca624
cTime=0
datanodeUuid=a39bf511-8b1f-4da8-8c1f-3c4201be87cd
storageType=DATA_NODE
layoutVersion=-57
- storageID:磁盘存储 ID
- clusterID:集群 ID (全局唯一)
- cTime:标记 DataNode 存储系统的创建时间,对于刚格式化的存储系统属性值为 0
- datanodeUuid:datanode 的唯一识别码
- storageType:存储类型
- layoutVersion:是一个负数(通常只有 HDFS 增加新特性才会更新这个版本号)
VERSION(datanode/current/BP-593175008-192.168.229.21-1616685687133/current)
[root@node-01 data]# cat datanode/current/BP-593175008-192.168.229.21-1616685687133/current/VERSION
namespaceID=1064465530
cTime=1616685687133
blockpoolID=BP-593175008-192.168.229.21-1616685687133
layoutVersion=-57
- namespaceID:DataNode 首次访问 NameNode 时从 NameNode 获取的 storageID(对每个 DataNode 是唯一的,但对单个 DataNode 中所有存储目录则是相同的),NameNode 可用这个属性来区别不同的 DataNode
- cTime:标记 DataNode 存储系统的创建时间
- blockpoolID:一个 block pool id 用于标识一个 block pool,并且是跨集群的全局唯一
- layoutVersion:一个负整数,通常只有 HDFS 增加新特性才会更新版本号
HDFS 内部工作机制的更多相关文章
- spring 内部工作机制(二)
本章节讲Spring容器从加载配置文件到创建出一个完整Bean的作业流程及参与的角色. Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表, ...
- Spring容器技术内幕之内部工作机制
引言 Spring容器就像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式工作.如果将Spring容器比作一辆车,那么可以将BeanFactory看成汽车的发动机,而A ...
- 【转】Java学习---HashMap和HashSet的内部工作机制
[原文]https://www.toutiao.com/i6593863882484220430/ HashMap和HashSet的内部工作机制 HashMap 和 HashSet 内部是如何工作的? ...
- 图文详解 HDFS 的工作机制及其原理
大家好,我是大D. 今天开始给大家分享关于大数据入门技术栈--Hadoop的学习内容. 初识 Hadoop 为了解决大数据中海量数据的存储与计算问题,Hadoop 提供了一套分布式系统基础架构,核心内 ...
- 大数据学习之HDFS的工作机制07
1:namenode+secondaryNameNode工作机制 2:datanode工作机制 3:HDFS中的通信(代理对象RPC) 下面用代码来实现基本的原理 1:服务端代码 package it ...
- (spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
前面讲过,spring的生命周期为:实例化前奏-->实例化-->实例化后期-->初始化前期-->初始化-->初始化后期-->bean的具体调用-->销毁前-- ...
- spring 内部工作机制(一)
Spring内部机制的内容较多,所以打算多分几个阶段来写. 本章仅探索Spring容器启动做了哪些事: 前言: 都说Spring容器就像一台构造精妙的机器,此话一点不假,我们通过配置文件向机器传达控制 ...
- Hadoop HDFS NameNode工作机制
Secondary namenode 首先,我们假设如果存储在Namenode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然是效率过低.因此,元数据需要存放在内存中.但如果只存在内存中 ...
- 实例说明C++的virtual function的作用以及内部工作机制初探
C++为何要引入virtual function? 来看一个基类的实现: 1 class CBase 2 { 3 public: 4 CBase(int id) : m_nId(id), m_pBas ...
- 浏览器详谈及其内部工作机制 —— web开发必读
浏览器介绍 如今,浏览器格局基本上是五分天下,分别是:IE.Firefox.Safari.Chrome.Opera,而浏览器引擎就更加集中了,主要是四大巨头:IE的浏览器排版引擎Trident,目前随 ...
随机推荐
- application.yaml
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root url: j ...
- js导出数据为excel表
1.接口数据后端写, 2.代码如下: var params={ "filters":[ {"propertyCode":"sequenceNo&quo ...
- Python的入门学习Day 22~24——form”夜曲编程“
Day 22 time:2021.8.19. 顺着歌曲的旋律,内心一下子就安静了呢.终于,我可以好好写日记了,徜徉在一片金色的花海里.今天主要学习了匿名函数.这是一种很有趣的函数呢,像孙悟空会72 ...
- Java基础学习:10、封装和继承和super、方法重载、多态、动态绑定
封装: 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.意义: 只能通过规定的方法访问数据. 隐藏类的实例细节,方便修改和实现 ...
- KingbaseES V8R3集群维护案例之---pcp_node_refresh应用
案例说明: 在一次KingbaseES V8R3集群切换分析中,运维人员执行了pcp_node_refresh,导致集群发生了failover的切换.此文档对pcp_node_refresh工具做了应 ...
- vue ref用法
<div class="myClass" ref="diva"></div> // 给dom节点添加ref this.$refs.div ...
- 性能测试-dstat以及sar(网络相关数据查看)
1.dstat参数说明 # 安装 yum install dstat -y dstat命令不加任何参数时,会收集CPU.磁盘.网络.分页.系统的数据信息,每秒收集一次.缺省参数时相当于dstat -c ...
- Python学习笔记(三)数据类型转换
一.输入输出函数 1.input() 输入函数,内置函数,用来获取用户输入数据,返回值为字符串 运行到此函数会阻塞或暂停程序 示例: 1 str_data = input('请输入数据:') 2 st ...
- python 操作 ES 二、mappings
环境 python:3.8 es:7.8.0 环境安装 pip install elasticsearch==7.8.0 from elasticsearch import Elasticsearch ...
- JUC续
设计模式,保护性暂停.解耦 生产者消费者模式 park.unpark 线程状态转换 锁超时 锁超时可以解决哲学家就餐问题 公平锁 条件变量 线程控制顺序
