文章整理自尚硅谷B站视频:https://www.bilibili.com/video/BV1Qp4y1n7EN?t=7&p=39
〇、要点
- 1.2 HDFS 的优缺点
- 1.3 HDFS NameNode 的作用
- 1.3 HDFS DataNode 的作用
- 1.3 HDFS SecondaryNameNode 的作用
- 1.4 HDFS 的文件块大小
- 1.4 HDFS 的文件块为什么不能太小或太大?
- 2.2 HDFS 的 Shell 操作命令大全
- 3 HDFS API 参数的优先级
- 4 HDFS 的读写流程
- 4.1 HDFS 写数据流程
- 4.1.2 HDFS 节点间距离计算
- 4.2 HDFS 读数据流程
- 5.1 HDFS NameNode 和 SecondaryNameNode 的工作机制
- 5.2 HDFS Fsimage 和 Edits 文件解析
- 5.3 HDFS CheckPoint 时间设置
- 6.1 HDFS DataNode 的工作机制
- 6.2 HDFS 如何保证数据完整性
- 6.3 HDFS 掉线时限参数设置
一、HDFS 概述
1.1 HDFS 的产生背景和定义
HDFS管理多台机器上的文件,通过目录树的方式定位文件
HDFS是分布式的,由很多服务器联合起来实现其功能
HDFS适合一次写入多次读出的使用场景,即上传之后不再修改原数据,可以追加
1.2 HDFS 的优缺点
优点:
- 高容错性:数据自动保存多个副本。它可以增加副本的形式,提高容错性。某一副本丢失后,它可以自动恢复。
- 适合处理大数据:GB、TB、PB,
- 可构建在廉价的机器上,通过多副本机制,提高可靠性
缺点:
- 不适合低延时数据访问
- 无法高效地对大量小文件进行存储:存储小文件时,会占用NameNode大量的内存来存储文件目录和块信息;小文件存储的寻址时间会超过读取时间,违反了HDFS的设计目标
- 不支持并发写入和文件随机修改:不允许多线程同时写,仅支持数据追加不支持修改
1.3 HDFS 的组成
- NameNode
- 管理HDFS的名称空间(元数据)
- 配置副本策略(文件的副本数量)
- 管理数据块(block)映射信息
- 处理客户端的读写请求
- DataNode
- 存储实际的数据块
- 执行数据块的读写操作
- Secondary NameNode
- 辅助nn,分担其工作量,比如定期合并Fsimage和Edits,并推送给nn
- 在紧急情况下,可辅助恢复nn
- Client:客户端
- 文件切分,文件上传HDFS的时候,Client将文件切块
- 与nn交互,获取文件的位置信息
- 与dn交互,读取或者写入数据
- 提供一些命令来管理HDFS,比如nn的格式化
- 可以通过一些命令访问HDFS,比如对HDFS增删改查的操作(浏览器页面就是个客户端,Shell命令也是个客户端)
1.4 HDFS 的文件块大小
-
HDFS中的文件在物理上分块存储,块的大小可以通过
hdfs-default.xml
中的dfs.blocksize
来规定,默认大小在2.x和3.x中为128M,1.x中为64M -
如果寻址时间(查找到目标block的时间)约为10ms:
- 寻址时间为传输时间的1%时,则为最佳状态,因此,传输时间=10ms/0.01=1s
- 目前磁盘的传输速率普遍为100MB/s,因此块大小设置为128M;传输速率达到200MB/s或300MB/s时,可将块大小设置为256M
为什么块大小不能设置太小或太大?
- 块设置太小,会增加寻址时间,程序一直在找块的开始位置
- 块设置太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间,导致程序处理这块数据时非常慢,不利于并发运算
- 总结:HDFS的块大小主要取决于磁盘传输速率
二、HDFS 的 Shell 操作
2.1 基本语法
-
hadoop fs
+具体命令 -
hdfs dfs
+具体命令
2.2 命令大全
https://hadoop.apache.org/docs/r3.2.1/hadoop-project-dist/hadoop-common/FileSystemShell.html
- 修改文件权限:
hdfs dfs -chmod -R 777 /myfile
三、HDFS 的客户端 API
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.*;
import java.net.URI;
public class MainApp {
public static void main(String[] args) throws Exception{
// 配置连接
Configuration conf = new Configuration();
// 在 core-site.xml 文件中
//conf.set("fs.defaultFS","hdfs://node102:8020");
//FileSystem fs = FileSystem.get(conf);
FileSystem fs = FileSystem.get(new URI("hdfs://node102:8020"),
conf, "hadoop");
// 1.新建目录
Path path = new Path("/myfile2/hello");
if (!fs.exists(path)){
fs.mkdirs(path);
}else{
System.out.println("路径已存在");
}
// 2.读取文件
InputStream in = fs.open(new Path("/myfile2/word.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String str;
while ((str=br.readLine())!=null){
System.out.println(str);
}
// 3.上传文件
fs.copyFromLocalFile(new Path("D:\\Program Files (x86)\\WorkspaceIDEA\\HadoopStu\\pom.xml"),
new Path("/myfile2/hello/pom.xml"));
fs.close();
System.out.println("Finished.");
}
}
- API 参数的优先级,代码里配置的优先级最高
- conf.set(“dfs.replication”, 2)
- resources下的配置文件
- hdfs-site.xml
- hdfs-default.xml
- 下载文件时,可以使用CRC校验
四、HDFS 的读写流程
4.1 HDFS 写数据流程
4.1.1 文件写入
- 客户端向nn请求上传文件
- nn响应可以上传文件
- nn检查目录树是否可以创建文件
- 检查权限
- 检查目录结构(目录是否存在)
- nn检查目录树是否可以创建文件
- 客户端请求上传第一个blick(0-128M),请求返回dn
- nn返回dn1、dn2、dn3节点,表示采用这三个节点存储数据
- nn副本存储节点选择
- 本地节点
- 其他机架一个节点
- 其他机架另一个节点
- nn副本存储节点选择
- 客户端创建一个数据流开始写数据
- 客户端和dn1请求建立block传输通道
- dn之间请求建立通道
- dn之间、dn1与客户端之间应答成功
- 传输数据单元:Packet(64k)
- packet(chunk512byte + chunksum4byte)
- 客户端和dn1请求建立block传输通道
4.1.2 网络拓扑 - 节点距离计算
在HDFS写数据的过程中,nn会选择距离待上传数据最近距离的dn接收数据。
节点距离:两个节点到达最近的共同祖先
的距离之和
4.1.3 机架感知(副本存储节点选择)
- 第一个:本地,节点距离最近,上传速度最快
- 第二个:保证数据的可靠性
- 第三个:兼顾效率(同机架传输快)
4.2 HDFS 读数据流程
- 客户端请求下载文件
- nn判断权限和文件是否存在
- nn返回目标文件的元数据
- 客户端创建一个流来读取数据(串行读取,读后追加)
- 客户端选择(节点距离最近&考虑当前节点的负载能力)的dn开始读取数据
五、nn 和 2nn
5.1 nn和2nn工作机制
nn:
- nn加载编辑日志(edits)和镜像文件(fsimage)到内存
- 客户端请求对元数据的增删改
- nn记录操作日志、更新滚动日志
- nn内存数据增删改
2nn:
- 请求是否需要CheckPoint
- CheckPoint触发条件
- 定时时间到
- Edits中的数据满了
- 请求执行CheckPoint
- nn滚动正在写的Edits
- 生成一个新的edits文件
- 将inprogress修改为完成
- 2nn将edits和fsimage拷贝
- 2nn将edits和fsimage加载到内存
- 2nn生成新的fsimage(fsimage.chkpoint)
- 2nn将fsimage.chkpoint拷贝回nn
- fsimage.chkpoint覆盖原nn中的fsimage
- 第一阶段:nn启动
- 第一次启动nn格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存
- 客户端对元数据进行增删改的请求
- nn记录操作日志,更新滚动日志
- nn在内存中对元数据进行增删改
- 第二阶段:2nn工作
- 2nn询问nn是否需要CheckPoint。直接带回nn是否检查的结果
- 2nn请求执行CheckPoint
- nn滚动正在写的edits日志
- 将滚动前的编辑日志和镜像文件拷贝到2nn
- 2nn加载编辑日志和镜像文件到内存,并合并
- 生成新的镜像文件fsimage.chkpoint
- 拷贝fsimage.chkpoint到nn
- nn将fsimage.chkpoint重新命名成fsimage(覆盖)
5.2 Fsimage和Edits解析
nn被格式化后,将在$(HADOOP_HOME)/data/tmp/dfs/name/current目录中产生如下文件:
fsimage_0000000
fsimage_0000000.md5
seen_txid
VERSION
- fsimage文件:HDFS中元数据的一个永久性的检查点,其中包含HDFS的所有目录和文件inode的序列化信息
- edits文件:存放HDFS的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中
- seen_txid文件保存一个数字,就是最后一个edits_的数字,记录最新的edits
(1)oiv查看fsimage文件
- 基本语法:
hdfs oiv -p 转换之后的文件类型 -i 镜像文件 -o 转换后文件输出路径
hdfs oiv -p XML -i fsimage_000001 -o /myfile/fsimage.xml
(2)oev查看edits文件
- 基本语法:
hdfs oev -p 转换之后的文件类型 -i 编辑日志 -o 转换后文件输出路径
hdfs oev -p XML -i edits_000000012_000000013 -o /myfile/edits.xml
5.3 CheckPoint时间设置
-
通常情况下,2nn每隔一小时执行一次
-
hdfs-defualt.xml
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600s</value> </property>
-
-
一分钟检查一次,当操作次数达到一百万时,2nn执行一次
-
hdfs-defualt.xml
<property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操作动作次数</description> </property> <property> <name>dfs.namenode.chekpoint.check.period</name> <value>60s</value> <description>1分钟检查一次操作次数</description> </property>
-
六、DataNode
6.1 dn的工作机制
- dn启动后向nn注册
- nn向dn返回注册成功
- 以后每周期(6h,
dfs.blockreport.intervalMsec
)dn向nn上报所有块信息,dn每周期(6h,dfs.datanode.directoryscan.interval
)扫描自己节点块信息 - nn和dn之间,心跳每3s一次,心跳返回结果带有nn给dn的命令
- 超过10min+30s没有收到dn的心跳,则认为该节点不可用,nn不会再允许对该dn文件块读写
6.2 数据完整性
- 当dn读取block时,它会计算CheckSum
- 如果计算后的CheckSum,与block创建时值不一样,说明block已经损坏
- Client读取其他dn上的block
- 常见的校验算法crc(32),md5(128),sha1(160)
- dn在其文件创建后周期验证CheckSum
6.3 dn掉线时限参数
-
dn进程死亡或者网络故障造成dn无法与nn通信
-
nn不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长
-
HDFS默认的超时时长为10min+30s
-
如果定义超时时间为TimeOut,则超时时长的计算公式为:
TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval
- dfs.namenode.heartbeat.recheck-interval = 5min(默认)
- dfs.heartbeat.interval = 3s(默认)