学习目标 #
- 了解什么是分布式文件系统,即大文件如何存储在集群中?
- 掌握HDFS常见面试题(切片机制、心跳检测、负载均衡、副本机制)
- 了解HDFS中的常见命令(上传、下载、复制、剪切、删除)
- HDFS读文件流程
- HDFS写文件流程
- 了解HDFS小文件归档模式
什么是分布式文件系统 #
- 大白话:你出5毛,我出5毛,一起凑成1块的过程
- 专业版:相当于把多个机器的磁盘给打通,然后对外提供统一的访问端口,从而实现跨机存储。
HDFS存储数据的时候,会对文件进行切块(Block数据块,hadoop2.x 中128Mb为一块)
- namenode:元数据
- datanode:实际数据
- 问题1:分布式存储优点是什么?
- 答案:无限扩展支撑海量数据存储(横向扩容)
- 问题2:元数据记录的功能是什么?
- 答案:整个集群的文件信息,每个文件Block块存储的位置,快速定位文件位置遍历查找
- 问题3:文件分块存储的好处是什么?
- 答案:针对块并行操作提高效率
- 问题4:设置副本备份的作用是什么?
- 答案:冗余存储保障数据安全
HDFS设计目标 #
- 硬件故障是常态,HDFS将有成百上干的服务器组成,每一个组成部分都有可能出现故障。因此故障的检测和自动快速恢复是HDFS的核心架构目标。
- HDFS上的应用与一般的应用(主要是以流式读取数据)不同。HDFS被设计成适合批量处理,而不是用户交互式的。相较于数据访问的反应时间,更注重数据访问的高吞吐量。
流式读取 => 把数据像水流一样进行读取,HDFS侧重于数据的读写,HDFS无法做到低延迟。
有时,读一个数据可能需要很长的时间。
- 典型的HDFS文件大小是GB到TB的级别。所以,HDFS被调整成支持大文件。它应该提供很高的聚合数据带宽,一个集群中支持数百个节点,一个集群中还应该支持干万级别的文件。
HDFS适合存储GB级别及以上大小文件
- 大部分HDFS应用对文件要求的是 write-one-read-many 访问模型。一个文件一旦创建、写入、关闭之后就 不需要修改了。这一假设简化了数据一致性问题,使高吞吐量的数据访问成为可能。
HDFS不支持文件的修改操作,所以其设计理念:一次写入,多次读取
- 移动计算的代价比之移动数据的代价低。一个应用请求的计算,离它操作的数据越近就越高效,这在数据达到海量级别的时候更是如此。将计算移动到数据附近,比之将数据移动到应用所在显然更好。
网络拓扑+机架感知原理:把数据放置在离计算最近的地方
- 在异构的硬件和软件平台上的 可移植性。这将推动需要大数据集的应用更广泛地采用HDFS作为平台。
HDFS重要特性 #
- 首先,它是一个文件系统,用于存储文件,通过统一的命名空间目录树来定位文件;
- 其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
- HDFS: namenode节点(存放元数据)
- datanode节点(存放具体数据块)
- secondarynamenode(2nn)辅助管理元数据
master/slave架构(一主多从架构) #
HDFS采用master/slave架构。一般一个HDFS集群是有一个Namenode和一定数目的Datanode组成。Namenode是HDFS集群主节点,Datanode是HDFS集群从节点,两种角色各司其职,共同协调完成分布式的文件存储服务。
分块存储(面试题:切片机制) #
HDFS中的文件在物理上是分块存储(block)的,块的大小可以通过配置参数来规定,默认大小在hadoop2.x版本中是128M。
- hadoop1.x版本中,客户端切片大小,每64MB为一片(Block)
- hadoop2.x/hadoop3.x版本中,客户端切片大小,每128MB为一片(Block)
问题:Hadoop切片大小为什么设置为128MB,此大小是否可以调整?
- 这个参数与硬盘文件寻址有关,可以调整,但是很少有调整的需求.由于目前位置大多数的硬盘,平均速率大概时候100MB/S。
命令空间 #
HDFS支持传统的层次型文件组织结构(树状结构)。用户或者应用程序可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。
Namenode负责维护文件系统的名字空间,任何对文件系统名字空间或属性的修改都将被Namenode记录下来。
HDFS会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
。
举个例子:hdfs://node1:8020/itheima.txt
。
Namenode元数据管理 #
我们把目录结构及文件分块位置信息叫做元数据。Namenode负责维护整个hdfs文件系统的目录树结构,以及每一个文件所对应的block块信息(block的id,及所在的datanode服务器)。
Datanode数据存储 #
文件的各个block的具体存储管理由datanode节点承担。每一个block都可以在多个datanode上。Datanode需要定时向Namenode汇报自己持有的block信息。
面试题1. 心跳检测机制
namenode与datanode是如何通信的,如果datanode宕机了,namenode是如何知晓并转移数据的?
- 心跳检测机制:了解namenode运行状态,即datanode要定时(3秒)给namenode发送自己的心跳消息,这样做的目的是:
- 让namenode知道datanode还活着,如果超时(如果某一次心跳数据没有接收,datanode还会频繁发送,发送10次=>30s)未发送心跳消息,namenode会认为datanode进入到假死的状态。如果超过最大间隔时间(10分钟)还未发送心跳消息,则认为该datanode宕机了。10分钟+30s =>(namenode => datanode宕机了)
- 当检测到某个datanode宕机后,namenode会将该datanode存储的所有数据重新找新机器(活跃的)备份。
- 汇报机制:元数据的块信息是存储在namenode的内存中的。
- 当HDFS集群重新启动的时候,所有的datanode都要向namenode汇报自己的节点信息,每个datanode重启也会主动汇报自己保存的文件块信息。
- 当集群在正常工作的时候,间隔一定的时间(6小时),datanode也会向namenode汇报一次自己的块信息。
面试题2:负载均衡机制
即让集群中所有的节点(服务器)的利用率及副本数尽量都保持一致或者在同一个水平线上,从而使利用率均衡,降低单台压力,每个节点利用率以及副本数量尽量平均(保障整个集群平稳运行)
副本机制(面试题:副本机制) #
为了容错,文件的所有block都会有副本。每个文件的block大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。
副本数量也可以通过参数设置 dfs.replication
,默认是3。
- 当某个块的副本不够3份的时候,namenode会新增副本;
- 当某个块的副本超过3份的时候,namenode会删除副本;
- 当某个块的副本数不够3份且无法新增的时候,此时集群就会强制进入安全模式,只能读,不能写。
hadoop-hdfs配置文件:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
面试题3:机架感知原理+网络拓扑结构实现副本摆放
- 第1副本:优先本机,否则就近随机
- 第2副本:就近不同机架的某一个服务器上
- 第3副本:和第2副本同一个机架的不同服务器上
一次写入,多次读出 #
HDFS是设计成适应一次写入,多次读出的场景,且不支持文件的修改。
正因为如此,HDFS适合用来做大数据分析的底层存储服务,并不适合用来做网盘等应用,因为,修改不方便,延迟大,网络开销大,成本太高。
HDFS基本操作 #
官方文档:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/FileSystemShell.html
Shell命令行客户端 #
Hadoop提供了文件系统的shell命令行客户端,使用方法如下:
hadoop fs <args>
文件系统shell包括与Hadoop分布式文件系统(HDFS)以及Hadoop支持的其他文件系统(如本地FS,HFTP FS,S3 FS等)直接交互的各种类似shell的命令。所有FS shell命令都将路径URI作为参数。
URI格式为scheme://authority/path。对于HDFS,该scheme是hdfs,对于本地FS,该scheme是file。scheme和authority是可选的。如果未指定,则使用配置中指定的默认方案。
对于HDFS,命令示例如下:
hadoop fs -ls hdfs://namenode:host/parent/child
hadoop fs -ls /parent/child
注:fs.defaultFS中有配置
对于本地文件系统,命令示例如下:
hadoop fs -ls file:///root/
如果使用的文件系统是HDFS,则使用hdfs dfs也是可以的,此时
hadoop fs <args> = hdfs dfs <args>
特别说明:关于HDFS的Shell操作,前缀写法有两种形式:
hadoop fs # 适用于所有的文件系统,hdfs://node1:8020/ file:///
hdfs dfs # 更适用于HDFS分布式文件系统
Shell命令选项 #
选项名称 | 使用格式 | 含义 |
---|---|---|
-ls | -ls <路径> | 查看指定路径的当前目录结构 |
-lsr | -lsr <路径> | 递归查看指定路径的目录结构 |
-du | -du <路径>,统计文件夹需要添加-s | 统计目录下个文件大小 |
-dus | -dus <路径> | 汇总统计目录下文件(夹)大小 |
-count | -count [-q] <路径> | 统计文件(夹)数量 |
-mv | -mv <源路径> <目的路径> | 移动 |
-cp | -cp <源路径> <目的路径> | 复制 |
-rm | -rm [-skipTrash] <路径> | 删除文件/空白文件夹 |
-rmr | -rmr [-skipTrash] <路径> | 递归删除 |
-put | -put <多个linux上的文件> <hdfs路径> | 上传文件 |
-copyFromLocal | -copyFromLocal <多个linux上的文件> <hdfs路径> | 从本地复制 |
-moveFromLocal | -moveFromLocal <多个linux上的文件> <hdfs路径> | 从本地移动 |
-getmerge | -getmerge <源路径> <linux路径> | 合并到本地 |
-cat | -cat <hdfs路径> | 查看文件内容 |
-text | -text <hdfs路径> | 查看文件内容 |
-copyToLocal | -copyToLocal [-ignoreCrc] [-crc] [hdfs源路径] [linux目的路径] | 从本地复制 |
-moveToLocal | -moveToLocal [-crc] <hdfs源路径> <linux目的路径> | 从本地移动 |
-mkdir | -mkdir <hdfs路径> | 创建空白文件夹 |
-setrep | -setrep [-R] [-w] <副本数> <路径> | 修改副本数量 |
-touchz | -touchz <文件路径> | 创建空白文件 |
-stat | -stat [format] <路径> | 显示文件统计信息 |
-tail | -tail [-f] <文件> | 查看文件尾部信息 |
-chmod | -chmod [-R] <权限模式> [路径] | 修改权限 |
-chown | -chown [-R] [属主][:[属组]] 路径 | 修改属主 |
-chgrp | -chgrp [-R] 属组名称 路径 | 修改属组 |
-help | -help [命令选项] | 帮助 |
Shell常用命令介绍 #
-ls(重点) #
使用方法:hadoop fs -ls [-h] [-R]
功能:显示文件、目录信息。
示例:hadoop fs -ls /user/hadoop/file1
-mkdir(重点) #
使用方法:hadoop fs -mkdir [-p]
功能:在hdfs上创建目录,-p表示会创建路径中的各级父目录。
示例:hadoop fs -mkdir –p /user/hadoop/dir1
-put:上传(重点) #
使用方法:hadoop fs -put [-f] [-p] [ -|
功能:将单个src或多个srcs从本地文件系统复制到目标文件系统。
-p:保留访问和修改时间,所有权和权限。
-f:覆盖目的地(如果已经存在)
示例:hadoop fs -put -f localfile1 localfile2 /user/hadoop/hadoopdir
-get:下载(重点) #
使用方法:hadoop fs -get [-ignorecrc] [-crc] [-p] [-f]
-ignorecrc:跳过对下载文件的CRC检查。
-crc:为下载的文件写CRC校验和。
功能:将文件复制到本地文件系统。
示例:hadoop fs -get hdfs://host:port/user/hadoop/file localfile
-appendToFile #
使用方法:hadoop fs -appendToFile
功能:追加一个文件到已经存在的文件末尾(两个文件内容合并)
示例:hadoop fs -appendToFile localfile /hadoop/hadoopfile
HDFS强调一次写入,多次读取。数据一旦写入成功,就不建议修改了!
如果想对数据修改有没有办法?答:目前官方提供了一个唯一方案,不是修改方案,是追加文件
-cat(重点) #
使用方法:hadoop fs -cat [-ignoreCrc] URI [URI …]
功能:显示文件内容到stdout
示例:hadoop fs -cat /hadoop/hadoopfile
-tail(重点) #
使用方法:hadoop fs -tail [-f] URI
功能:将文件的最后一千字节内容显示到stdout。
-f选项将在文件增长时输出附加数据。
示例:hadoop fs -tail /hadoop/hadoopfile
-chgrp:group简写,更改文件所属组 #
使用方法:hadoop fs -chgrp [-R] GROUP URI [URI …]
功能:更改文件组的关联。用户必须是文件的所有者,否则是超级用户。
-R将使改变在目录结构下递归进行。
示例:hadoop fs -chgrp othergroup /hadoop/hadoopfile
-chmod:更改权限(重点) #
功能:改变文件的权限。使用-R将使改变在目录结构下递归进行。
示例:hadoop fs -chmod 666 /hadoop/hadoopfile
-chown:更改文件拥有者 #
功能:改变文件的拥有者。使用-R将使改变在目录结构下递归进行。
示例:hadoop fs -chown someuser:somegrp /hadoop/hadoopfile
-cp(重点) #
功能:从hdfs的一个路径拷贝hdfs的另一个路径
示例: hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2
-mv(重点) #
功能:在hdfs目录中移动文件
示例: hadoop fs -mv /aaa/jdk.tar.gz /
-getmerge #
功能:合并下载多个文件
示例:比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,…
hadoop fs -getmerge /aaa/log.* ./log.sum
-rm(重点) #
功能:删除指定的文件。只删除非空目录和文件。-r 递归删除。
示例:hadoop fs -rm -r /aaa/bbb/
-df(重点) #
功能:统计文件系统的可用空间信息
示例:hadoop fs -df -h /
-du(重点) #
功能:显示目录中所有文件大小,当只指定一个文件时,显示此文件的大小。
示例:hadoop fs -du /user/hadoop/dir1
-setrep #
功能:改变一个文件的副本系数。-R选项用于递归改变目录下所有文件的副本系数。
示例:hadoop fs -setrep -w 3 -R /user/hadoop/dir1
实际工作中,一般不会使用此命令,而是通过配置文件设置副本数
特别说明:-touch
HDFS基本原理 #
NameNode概述 #
- NameNode是HDFS的核心。
- NameNode也称为Master。
- NameNode仅存储HDFS的元数据(文件系统中所有文件的目录树),并跟踪整个集群中的文件。
- NameNode不存储实际数据或数据集。数据本身实际存储在DataNodes中。
- NameNode知道HDFS中任何给定文件的块列表及其位置。使用此信息NameNode知道如何从块中构建文件。
- NameNode并不持久化存储每个文件中各个块所在的DataNode的位置信息,这些信息会在系统启动时从数据节点重建。
- NameNode对于HDFS至关重要,当NameNode关闭时,HDFS/ Hadoop集群无法访问。
- NameNode是Hadoop集群中的单点故障。
- NameNode所在机器通常会配置有大量内存(RAM)。
元数据存放在内存中,默认情况下,每个文件的元数据大概有150B字节。
DataNode概述 #
- DataNode负责将实际数据存储在HDFS中。
- DataNode也称为Slave。
- NameNode和DataNode会保持不断通信(心跳机制)。
- DataNode启动时,它将自己发布到NameNode并汇报自己负责持有的块列表。
- 当某个DataNode关闭时,它不会影响数据或群集的可用性。NameNode将安排由其他DataNode管理的块进行副本复制。
- DataNode所在机器通常配置有大量的硬盘空间。因为实际数据存储在DataNode中。
- DataNode会定期(
dfs.heartbeat.interval
配置项配置,默认是3秒)向NameNode发送心跳,如果NameNode长时间没有接受到DataNode发送的心跳,NameNode就会认为该DataNode失效(10分钟+30s)。 - block汇报时间间隔取参数
dfs.blockreport.intervalMsec
,参数未配置的话默认为6小时。
小结:
- namenode => HDFS核心组件=>负责管理整个HDFS集群不保存具体数据,主要保存元数据=>放置在内存,所以在配置时需要大量的内存
- datanode => HDFS组件=>负责具体数据/数据集存储,需要占用大量磁盘空间,某个机器故障并不影响整个集群的使用,datanode需要每个3s发送一次心跳信息。
- datanode启动时会自动向namenode汇报1次本节点的块文件信息。
- datanode实现数据冗余存储(副本机制)。
HDFS写数据流程(简化为十步走) #
HDFS读数据流程(简化为五步走) #
HDFS其他功能 #
1、不同集群之间的数据复制 #
cluster1 => hadoop集群(测试环境)
cluster2 => hadoop集群(生产环境)
在我们实际工作当中,极有可能会遇到将测试集群的数据拷贝到生产环境集群,或者将生产环境集群的数据拷贝到测试集群,那么就需要我们在多个集群之间进行数据的远程拷贝,hadoop自带也有命令可以帮我们实现这个功能。
2、集群内部文件拷贝scp #
上传:
scp 本地文件 用户名@主机名称:拷贝路径
scp -r 本地文件夹 用户名@主机名称:拷贝路径
下载:
scp 用户名@主机名称:远程文件路径 本地路径
scp -r 用户名@主机名称:远程文件夹路径 本地路径
3、跨集群之间的数据拷贝distcp #
[root@cluster1 ~] # hadoop distcp hdfs://cluster1:8020/jdk-8u141-linux-x64.tar.gz hdfs://cluster2:8020/
4、Archive档案的使用(Hadoop归档模式) #
HDFS并不擅长存储小文件,因为每个文件最少一个block,每个block的元数据都会在NameNode占用内存,如果存在大量的小文件,它们会吃掉NameNode节点的大量内存。
Hadoop Archives可以有效的处理以上问题,它可以把多个文件归档成为一个文件,归档成一个文件后还可以透明的访问每一个文件。
1 如何创建Archive
Usage: hadoop archive -archiveName name -p <parent> <src>* <dest>
-archiveName:归档后的文件名称
-p:指定要归档父文件夹,所有需要归档的文件都在此目录
其中-archiveName是指要创建的存档的名称。比如test.har,archive的名字的扩展名应该是.har*。 -p参数指定文件存档文件(src)的相对路径。
举个例子:-p /foo/bar a/b/c e/f/g
这里的/foo/bar
是a/b/c
与e/f/g
的父路径,
所以完整路径为/foo/bar/a/b/c
与/foo/bar/e/f/g
例如:如果你只想存档一个目录/input下的所有文件:
hadoop archive -archiveName test.har -p /input /outputdir
这样就会在/outputdir目录下创建一个名为test.har的存档文件。
2 如何查看Archive
首先我们来看下创建好的har文件。使用如下的命令:
hadoop fs -ls /outputdir/test.har
这里可以看到har文件包括:两个索引文件,多个part文件(本例只有一个)以及一个标识成功与否的文件。part文件是多个原文件的集合,根据index文件去找到原文件。
例如上述的三个小文件1.txt 2.txt 3.txt内容分别为1,2,3。进行archive操作之后,三个小文件就归档到test.har里的part-0一个文件里。
archive作为文件系统层暴露给外界。所以所有的fs shell命令都能在archive上运行,但是要使用不同的URI。
Hadoop Archives的URI是:
har://scheme-hostname:port/archivepath/fileinarchive
scheme-hostname格式为hdfs-域名:端口,如果没有提供scheme-hostname,它会使用默认的文件系统。这种情况下URI是这种形式:
har:///archivepath/fileinarchive
如果用har uri去访问的话,索引、标识等文件就会隐藏起来,只显示创建档案之前的原文件:
案例:把/test目录下的1.txt、2.txt、3.txt进行归档操作
数据集准备:
归档:
查看归档包内容:har://hdfs-集群名称
查看归档包中文件的内容:
解压归档包
① 删除1.txt/2.txt/3.txt
② 解压归档包
3 如何解压Archive
按顺序解压存档(串行):
Hadoop fs -cp har:///user/zoo/foo.har/dir1 hdfs:/user/zoo/newdir
要并行解压存档,请使用DistCp:
hadoop distcp har:///user/zoo/foo.har/dir1 hdfs:/user/zoo/newdir
4 Archive注意事项
- Hadoop archives是特殊的档案格式。一个Hadoop archive对应一个文件系统目录。Hadoop archive的扩展名是*.har;
- 创建archives本质是运行一个Map/Reduce任务,所以应该在Hadoop集群上运行创建档案的命令;
- 创建archive文件要消耗和原文件一样多的硬盘空间(归档并没有压缩);
- archive文件不支持压缩,尽管archive文件看起来像已经被压缩过;
- archive文件一旦创建就无法改变,要修改的话,需要创建新的archive文件。事实上,一般不会再对存档后的文件进行修改,因为它们是定期存档的,比如每周或每日;
- 当创建archive时,源文件不会被更改或删除;
HDFS元数据管理机制 #
- namenode:管理元数据
- datanode:管理实际数据
- secondarynamenode:辅助namenode管理元数据
元数据管理概述 #
HDFS元数据,按类型分,主要包括以下几个部分:
-
持久化存储(HDFS集群中的文件的元数据信息):
- 文件、目录自身的属性信息,例如文件名,目录名,修改信息等。
- 文件记录的信息的存储相关的信息,例如存储块信息,分块情况,副本个数等。
-
非持久化存储:
- 记录HDFS的Datanode的信息,用于DataNode的管理。
按形式分为内存元数据和元数据文件两种,分别存在内存和磁盘上。
HDFS磁盘上元数据文件分为两类,用于持久化存储(① 文件自身属性 ② 文件存储相关信息):
- fsimage 镜像文件:是元数据的一个持久化的检查点,包含Hadoop文件系统中的所有目录和文件元数据信息,但不包含文件块位置的信息。文件块位置信息只存储在内存中,是在 datanode加入集群的时候,namenode询问datanode得到的,并且间断的更新。
fsimage镜像文件:保存整个HDFS集群的元数据信息,不包含datanode节点信息。因为datanode数据都是放在内存元数据。
- edits 编辑日志:存放的是Hadoop文件系统的所有更改操作(文件创建,删除或修改)的日志,文件系统客户端执行的更改操作首先会被记录到edits文件中。
edits编辑日志:我们客户端向Hadoop的所有更改(增、删、改),都会被记录下来
fsimage和edits文件都是经过序列化的,在NameNode启动的时候,它会将fsimage文件中的内容加载到内存中,之后再执行edits文件中的各项操作,使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作,也是最完整的元数据。
例子:
上面两者内容合并得到下面的最新数据:
当客户端对HDFS中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存元数据中。因为fsimage文件一般都很大(GB级别的很常见),如果所有的更新操作都往fsimage文件中添加,这样会导致系统运行的十分缓慢。
HDFS这种设计实现着手于:一是内存中数据更新、查询快,极大缩短了操作响应时间;二是内存中元数据丢失风险颇高(断电等),因此辅佐元数据镜像文件(fsimage)+编辑日志文件(edits)的备份机制进行确保元数据的安全。
NameNode维护整个文件系统元数据。因此,元数据的准确管理,影响着HDFS提供文件存储服务的能力。
在Hadoop的HDFS首次部署好配置文件之后,并不能马上启动使用,而是先要对文件系统进行格式化。需要在NameNode(NN)节点上进行如下的操作:
$HADOOP_HOME/bin/hdfs namenode -format
在这里要注意两个概念,一个是文件系统,此时的文件系统在物理上还不存在;二就是此处的格式化并不是指传统意义上的本地磁盘格式化,而是一些清除与准备工作。
格式化完成之后,将会在$dfs.namenode.name.dir/current
目录下创建如下的文件结构,这个目录也正是namenode元数据相关的文件目录:
其中的dfs.namenode.name.dir
是在hdfs-site.xml文件中配置的,默认值如下:
namespaceID/clusterID/blockpoolID
这些都是HDFS集群的唯一标识符。标识符被用来防止DataNodes意外注册到另一个集群中的namenode上。这些标识在联邦(federation)部署中特别重要。联邦模式下,会有多个NameNode独立工作。每个的NameNode提供唯一的命名空间(namespaceID),并管理一组唯一的文件块池(blockpoolID)。clusterID将整个集群结合在一起作为单个逻辑单元,在集群中的所有节点上都是一样的。
storageType
说明这个文件存储的是什么进程的数据结构信息(如果是DataNode,storageType=DATA_NODE);
cTime
NameNode存储系统创建时间,首次格式化文件系统这个属性是0,当文件系统升级之后,该值会更新到升级之后的时间戳;
layoutVersion
表示HDFS永久性数据结构的版本信息,是一个负整数。
补充说明:
格式化集群的时候,可以指定集群的cluster_id,但是不能与环境中其他集群有冲突。如果没有提供cluster_id,则会自动生成一个唯一的ClusterID。
$HADOOP_HOME/bin/hdfs namenode -format -clusterId <cluster_id>
seen_txid
$dfs.namenode.name.dir/current/seen_txid非常重要,是存放transactionId的文件,format之后是0,它代表的是namenode里面的edits_*文件的尾数
,namenode重启的时候,会按照seen_txid的数字,循序从头跑edits_0000001~到seen_txid的数字。所以当你的hdfs发生异常重启的时候,一定要比对seen_txid内的数字是不是你edits最后的尾数。
Fsimage & edits
$dfs.namenode.name.dir/current目录下在format的同时也会生成fsimage和edits文件,及其对应的md5校验文件。
面试题-fsimage是干什么的?里面保存的哪些数据?是否可以直接查看?
fsimage
文件其实是Hadoop文件系统元数据的一个永久性的检查点,其中包含Hadoop文件系统中的所有目录和文件idnode的序列化信息;
fsimage包含Hadoop文件系统中的所有目录和文件idnode的序列化信息;对于文件来说,包含的信息有修改时间、访问时间、块大小和组成一个文件块信息等;而对于目录来说,包含的信息主要有修改时间、访问控制权限等信息。
面试题-edits是干什么的?里面保存的哪些数据?是否可以直接查看?
edits
文件存放的是Hadoop文件系统的所有更新操作的路径,文件系统客户端执行的所以写操作首先会被记录到edits文件中。
面试题-为什么要对两者之间进行合并操作呢?
答:为了得到最新的元数据
NameNode起来之后,HDFS中的更新操作会重新写到edits文件中,因为fsimage文件一般都很大(GB级别的很常见),如果所有的更新操作都往fsimage文件中添加,这样会导致系统运行的十分缓慢,但是如果往edits文件里面写就不会这样,每次执行写操作之后,且在向客户端发送成功代码之前,edits文件都需要同步更新。如果一个文件比较大,使得写操作需要向多台机器进行操作,只有当所有的写操作都执行完成之后,写操作才会返回成功,这样的好处是任何的操作都不会因为机器的故障而导致元数据的不同步。
内容查看
元数据存储位置:/export/data/hadoop-3.3.0/dfs/name/current
fsimage、edits两个文件中的内容使用普通文本编辑器是无法直接查看的,幸运的是hadoop为此准备了专门的工具用于查看文件的内容,这些工具分别为oev
和oiv
,可以使用hdfs调用执行。
oev是offline edits viewer(离线edits查看器)的缩写
,该工具只操作文件因而并不需要hadoop集群处于运行状态。
hdfs oev -i edits_0000000000000000081-0000000000000000089 -o edits.xml
-i,--inputFile <arg>
-o,--outputFile <arg> Name of output file
在输出文件中,每个RECORD记录了一次操作,示例如下:
oiv是offline image viewer的缩写
,用于将fsimage文件的内容转储到指定文件中以便于阅读,该工具还提供了只读的WebHDFS API以允许离线分析和检查hadoop集群的命名空间。oiv在处理非常大的fsimage文件时是相当快的,如果该工具不能够处理fsimage,它会直接退出。该工具不具备向后兼容性,比如使用hadoop-2.4版本的oiv不能处理hadoop-2.3版本的fsimage,只能使用hadoop-2.3版本的oiv。同oev一样,就像它的名称所提示的(offline),oiv也不需要hadoop集群处于运行状态。
hdfs oiv -i fsimage_0000000000000000115 -p XML -o fsimage.xml
示例如下:
secondary namenode #
NameNode职责是管理元数据信息,DataNode的职责是负责数据具体存储,那么SecondaryNameNode的作用是什么?对很多初学者来说是非常迷惑的。它为什么会出现在HDFS中。从它的名字上看,它给人的感觉就像是NameNode的备份。但它实际上却不是。
大家猜想一下,当HDFS集群运行一段事件后,就会出现下面一些问题:
- edit logs文件会变的很大,怎么去管理这个文件是一个挑战。
- NameNode重启会花费很长时间,因为有很多改动要合并到fsimage文件上。
- 如果NameNode挂掉了,那就丢失了一些改动。因为此时的fsimage文件非常旧。
因此为了克服这个问题,我们需要一个易于管理的机制来帮助我们减小edit logs文件的大小和得到一个最新的fsimage文件,这样也会减小在NameNode上的压力。这跟Windows的恢复点是非常像的,Windows的恢复点机制允许我们对OS进行快照,这样当系统发生问题时,我们能够回滚到最新的一次恢复点上。
SecondaryNameNode就是来帮助解决上述问题的,它的职责是合并NameNode的edit logs到fsimage文件中。
Checkpoint(2NN合并元数据文件过程) #
每达到触发条件,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint),如下图所示:
- NameNode管理着元数据信息,其中有两类持久化元数据文件:edits操作日志文件和fsimage元数据镜像文件。新的操作日志不会立即与fsimage进行合并,也不会刷到NameNode的内存中,而是会先写到edits中(因为合并需要消耗大量的资源),操作成功之后更新至内存。
- 有dfs.namenode.checkpoint.period和dfs.namenode.checkpoint.txns 两个配置,只要达到这两个条件任何一个,secondarynamenode就会执行checkpoint的操作。
- 当触发checkpoint操作时,NameNode会生成一个新的edits即上图中的edits.new文件,同时SecondaryNameNode会将edits文件和fsimage复制到本地(HTTP GET方式)。
- secondarynamenode将下载下来的fsimage载入到内存,然后一条一条地执行edits文件中的各项更新操作,使得内存中的fsimage保存最新,这个过程就是edits和fsimage文件合并,生成一个新的fsimage文件即上图中的Fsimage.ckpt文件。
- secondarynamenode将新生成的Fsimage.ckpt文件复制到NameNode节点。
- 在NameNode节点的edits.new文件和Fsimage.ckpt文件会替换掉原来的edits文件和fsimage文件,至此刚好是一个轮回,即在NameNode中又是edits和fsimage文件。
- 等待下一次checkpoint触发SecondaryNameNode进行工作,一直这样循环操作。
Checkpoint触发条件
Checkpoint操作受两个参数控制,可以通过core-site.xml进行配置:
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
<description>
两次连续的checkpoint之间的时间间隔。默认1小时
</description>
</property>
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>
最大的没有执行checkpoint事务的数量,满足将强制执行紧急checkpoint,即使尚未达到检查点周期。默认设置为100万。
</description>
</property>
从上面的描述我们可以看出,SecondaryNamenode根本就不是Namenode的一个热备,其只是将fsimage和edits合并。其拥有的fsimage不是最新的,因为在他从NameNode下载fsimage和edits文件时候,新的更新操作已经写到edit.new文件中去了。而这些更新在SecondaryNamenode是没有同步到的!当然,如果NameNode中的fsimage真的出问题了,还是可以用SecondaryNamenode中的fsimage替换一下NameNode上的fsimage,虽然已经不是最新的fsimage,但是我们可以将损失减小到最少!
HDFS安全模式 #
安全模式概述 #
安全模式
是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求
,是一种保护机制
,用于保证集群中的数据块的安全性。
1个Block块会产生3个副本 => 必须保证有充足datanode节点进行存储。
在NameNode主节点启动时,HDFS首先进入安全模式,集群会开始检查数据块的完整性。DataNode在启动的时候会向Namenode汇报可用的block信息,当整个系统达到安全标准时,HDFS自动离开安全模式。
假设我们设置的副本数(即参数dfs.replication)是5,那么在Datanode上就应该有5个副本存在,假设只存在3个副本,那么比例就是3/5=0.6。在配置文件hdfs-default.xml中定义了一个最小的副本的副本率(即参数dfs.namenode.safemode.threshold-pct)0.999
。
hdfs-default.xml官方默认配置,我们本地配置hdfs-site.xml
我们的副本率0.6明显小于0.99,因此系统会自动的复制副本到其他的DataNode,使得副本率不小于0.999.如果系统中有8个副本,超过我们设定的5个副本,那么系统也会删除多余的3个副本。
如果HDFS处于安全模式下,不允许HDFS客户端进行任何修改文件的操作
,包括上传文件,删除文件,重命名,创建文件夹,修改副本数等操作。
安全模式配置 #
与安全模式相关主要配置在hdfs-site.xml文件中,主要有下面几个属性:
dfs.namenode.replication.min: 每个数据块最小副本数量,默认为1。在上传文件时,达到最小副本数,就认为上传是成功的。
dfs.namenode.safemode.threshold-pct: 达到最小副本数的数据块的百分比。默认为0.999f。当小于这个比例,那就将系统切换成安全模式,对数据块进行复制;当大于该比例时,就离开安全模式,说明系统有足够的数据块副本数,可以对外提供服务。
0.999f/1(1:1),3个副本=3个datanode节点
所以dfs.namenode.safemode.threshold-pct此参数必须是大于0且小于1,如果值<=0,不进入安全模式;值=1,一直处于安全模式之间,临界值(特殊值),0代表不进入安全模式,=1代表直接进入安全模式!
dfs.namenode.safemode.min.datanodes: 离开安全模式的最小可用datanode数量要求,默认为0。也就是即使所有datanode都不可用,仍然可以离开安全模式。
dfs.namenode.safemode.extension: 当集群可用block比例,可用datanode都达到要求之后,如果在extension配置的时间段之后依然能满足要求,此时集群才离开安全模式。单位为毫秒,默认为30000.也就是当满足条件并且能够维持30秒之后,离开安全模式。 这个配置主要是对集群稳定程度做进一步的确认。避免达到要求后马上又不符合安全标准。
总结一下,要离开安全模式,需要满足以下条件:
1)达到副本数量要求的block比例满足要求;
2)可用的datanode节点数满足配置的数量要求;
3)1、2 两个条件满足后维持的时间达到配置的要求
安全模式命令 #
手动进入安全模式
hdfs dfsadmin -safemode enter
手动进入安全模式对于集群维护或者升级的时候非常有用,因为这时候HDFS上的数据是只读的。手动退出安全模式可以用下面命令:
hdfs dfsadmin -safemode leave
如果你想获取到集群是否处于安全模式,可以用下面的命令获取:
hdfs dfsadmin -safemode get