一、概述
HDFS (Hadoop Distributed File System)是 Hadoop 下的分布式文件系统,具有高容错、高吞吐量等特性,可以部署在低成本的硬件上。
二、起因
要发展大数据,首要问题就是考虑数据存储的问题,大数据存储存在以下核心问题:
- 数据存储容量的问题,既然大数据要解决的是数以PB计的数据计算问题,而一般的服务器磁盘容量通常1-2TB,那么如何存储这么大规模的数据。
- 数据读写速度的问题,一般磁盘的连续读写速度为几十MB,以这样的速度,几十PB的数据恐怕要读写到天荒地老。
- 数据可靠性的问题,磁盘大约是计算机设备中最易损坏的硬件了,在网站一块磁盘使用寿命大概是一年,如果磁盘损坏了,数据怎么办?
在大数据技术出现之前,人们就需要面对这些关于存储的问题,对应的解决方案就是RAID技术。RAID(独立磁盘冗余阵列)技术主要是为了改善磁盘的存储容量,读写速度,增强磁盘的可用性和容错能力。目前服务器级别的计算机都支持插入多块磁盘(8块或者更多),通过使用RAID技术,实现数据在多块磁盘上的并发读写和数据备份。

1.RAID 0
数据在从内存缓冲区写入磁盘时,根据磁盘数量将数据分成N份,这些数据同时并发写入N块磁盘,使得数据整体写入速度是一块磁盘的N倍。读取的时候也一样,因此RAID0具有极快的数据读写速度,但是RAID0不做数据备份,N块磁盘中只要有一块损坏,数据完整性就被破坏,所有磁盘的数据都会损坏。
2.RAID 1
数据在写入磁盘时,将一份数据同时写入两块磁盘,这样任何一块磁盘损坏都不会导致数据丢失,插入一块新磁盘就可以通过复制数据的方式自动修复,具有极高的可靠性。
3.RAID 10
结合RAID0和RAID1两种方案,将所有磁盘平均分成两份,数据同时在两份磁盘写入,相当于RAID1,但是在每一份磁盘里面的N/2块磁盘上,利用RAID0技术并发读写,既提高可靠性又改善性能,不过RAID10的磁盘利用率较低,有一半的磁盘用来写备份数据。
4.RAID5
相比RAID3,更多被使用的方案是RAID5。RAID5和RAID3很相似,但是校验数据不是写入第N块磁盘,而是螺旋式地写入所有磁盘中。这样校验数据的修改也被平均到所有磁盘上,避免RAID3频繁写坏一块磁盘的情况。
5.RAID6
如果数据需要很高的可靠性,在出现同时损坏两块磁盘的情况下(或者运维管理水平比较落后,坏了一块磁盘但是迟迟没有更换,导致又坏了一块磁盘),仍然需要修复数据,这时候可以使用RAID6。
RAID6和RAID5类似,但是数据只写入N-2块磁盘,并螺旋式地在两块磁盘中写入校验信息(使用不同算法生成)。
| RAID 等级 | RAID0 | RAID1 | RAID3 | RAID5 | RAID6 | RAID10 |
|---|---|---|---|---|---|---|
| 别名 | 条带 | 镜像 | 专用奇偶校验条带 | 分布奇偶校验条带 | 双重奇偶校验条带 | 镜像加条带 |
| 容错性 | 无 | 有 | 有 | 有 | 有 | 有 |
| 冗余类型 | 无 | 有 | 有 | 有 | 有 | 有 |
| 热备份选择 | 无 | 有 | 有 | 有 | 有 | 有 |
| 读性能 | 高 | 低 | 高 | 高 | 高 | 高 |
| 随机写性能 | 高 | 低 | 低 | 一般 | 低 | 一般 |
| 连续写性能 | 高 | 低 | 低 | 低 | 低 | 一般 |
| 需要磁盘数 | n≥1 | 2n (n≥1) | n≥3 | n≥3 | n≥4 | 2n(n≥2)≥4 |
| 可用容量 | 全部 | 50% | (n-1)/n | (n-1)/n | (n-2)/n | 50% |
RAID技术只是在单台服务器的多块磁盘上组成阵列,大数据需要更大规模的存储空间和访问速度。因此,Hadoop结合前面的RAID技术和Google提出的GFS论文,创造了HDFS。HDFS(Hadoop分布式文件系统)是根据GFS(Google文件系统)的原理开发的,是GFS的简化版。
三、HDFS架构原理

HDFS的架构:主从架构,三大角色
- Namenode负责整个分布式文件系统的元数据(MetaData)管理,也就是文件路径名,数据block的ID以及存储位置等信息,承担着操作系统中文件分配表(FAT)的角色。HDFS为了保证数据的高可用,会将一个block复制为多份(缺省情况为3份),并将三份相同的block存储在不同的服务器上。这样当有磁盘损坏或者某个DataNode服务器宕机导致其存储的block不能访问的时候,Client会查找其备份的block进行访问。
- Datanode负责文件数据的存储和读写操作,HDFS将文件数据分割成若干块(block),每个DataNode存储一部分block,这样文件就分布存储在整个HDFS服务器集群中。
- SecondaryNamenode严格意义上来说并不属于namenode的备份节点,它主要起到的作用其实是替namenode分担压力,降低负载(元数据的编辑日志合并,也就是edits log)之用
1.心跳机制
为了保证集群的高可用性和高可靠性(HA),DataNode会通过心跳和NameNode保持通信,如果DataNode超时未发送心跳,NameNode就会认为这个DataNode已经失效,立即查找这个DataNode上存储的block有哪些,以及这些block还存储在哪些服务器上,随后通知这些服务器再复制一份block到其他服务器上,保证HDFS存储的block备份数符合用户设置的数目,即使再有服务器宕机,也不会丢失数据。

1.NameNode启动之后,会开一个ipc server。NameNode 全权管理数据块的复制,它周期性从集群中的每个 DataNode 接收心跳信号和 block 状态报告,接收到心跳信号意味着该 DataNode 节点工作正常,块状态报告包含了该 DataNode 上所有数据块的列表
2.DataNode启动,连接NameNode注册,每隔3s向NameNode发送一个心跳,并携带状态信息,周期性地向 NameNode 上报 block 报告。NameNode 返回对该 DataNode 的指令,如将数据块复制到另一台机器,或删除某个数据块等,而当某一个 DataNode 超过10min还没向 NameNode 发送心跳,此时 NameNode 就会判定该 DataNode 不可用,此时客户端的读写操作就不会再传达到该 DataNode 上。
2.安全模式
Hadoop 集群刚开始启动时会进入安全模式,就用到了心跳机制。在集群刚启动的时候,每一个 DataNode 都会向 NameNode 发送 block 报告,NameNode 会统计它们上报的总block数,除以一开始知道的总个数total,当 block/total < 99.99% 时,会触发安全模式,安全模式下客户端就没法向HDFS写数据,只能进行读数据。
Namenode感知Datanode掉线死亡时间的计算公式为:
1 | timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval |
HDFS默认超时时间为630秒,heartbeat.recheck.interval(重新检查的时间间隔) 的默认值为5分钟,而 dfs.heartbeat.interval(发送一次心跳的间隔) 默认值为3秒。
安全模式不仅仅是集群刚启动时等所有的Datanode汇报这一种情况会进入安全模式的,还有就是HDFS数据块丢失达到一个比例的时候,也会自动进入,这个比例默认是0.1%,1000个块丢1个已经很严重的事件了。
四、HDFS的使用
关于java api的说明:
FileSystem 是所有 HDFS 操作的主入口。
1 | Configuration configuration = new Configuration(); |
1. 显示当前目录结构
shell命令:
1 | 显示当前目录结构 |
java API:
1 | FileStatus[] statuses = fileSystem.listStatus(new Path("/")); |
2. 创建目录
shell命令:
1 | 创建目录 |
java API:
1 | fileSystem.mkdirs(new Path("/test0/")); |
3. 删除操作
shell命令:
1 | 删除文件 |
java API:
1 | //返会 Boolean类型 |
4. 从本地加载文件到 HDFS
shell命令:
1 | 二选一执行即可 |
java API:
1 | // 如果指定的是目录,则会把目录及其中的文件都复制到指定目录下 |
5. 从 HDFS 导出文件到本地
shell命令:
1 | 二选一执行即可 |
java API:
1 | Path src = new Path("/hdfs-api/test/kafka.tgz"); |
6. 查看文件内容
shell命令:
1 | 二选一执行即可 |
java API:
1 | FSDataInputStream inputStream = fileSystem.open(new Path("/hdfs-api/test/a.txt")); |
7. 显示文件的最后一千字节
1 | hadoop fs -tail <path> |
8. 拷贝文件
shell命令:
1 | hadoop fs -cp [src] [dst] |
9. 移动文件
shell命令:
1 | hadoop fs -mv [src] [dst] |
10. 统计当前目录下各文件大小
shell命令:
- 默认单位字节
- -s : 显示所有文件大小总和,
- -h : 将以更友好的方式显示文件大小(例如 64.0m 而不是 67108864)
1 | hadoop fs -du <path> |
11. 合并下载多个文件
shell命令:
- -nl 在每个文件的末尾添加换行符(LF)
- -skip-empty-file 跳过空文件
1 | hadoop fs -getmerge |
12. 统计文件系统的可用空间信息
shell命令:
1 | hadoop fs -df -h / |
13. 更改文件复制因子
shell命令:
1 | hadoop fs -setrep [-R] [-w] <numReplicas> <path> |
- 更改文件的复制因子。如果 path 是目录,则更改其下所有文件的复制因子
- -w : 请求命令是否等待复制完成
1 | # 示例 |
14. 权限控制
shell命令:
1 | 权限控制和Linux上使用方式一致 |
15. 文件检测
shell命令:
1 | hadoop fs -test - [defsz] URI |
可选选项:
- -d:如果路径是目录,返回 0。
- -e:如果路径存在,则返回 0。
- -f:如果路径是文件,则返回 0。
- -s:如果路径不为空,则返回 0。
- -r:如果路径存在且授予读权限,则返回 0。
- -w:如果路径存在且授予写入权限,则返回 0。
- -z:如果文件长度为零,则返回 0。
1 | 示例 |
java API:
1 | // 返会Boolean类型 |