一:HDFS架构图
HDFS(Hadoop Distributed File System,Hadoop分布式文件系统),它是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,适合那些有着超大数据集(largedata set)的应用程序。
HDFS的设计特点:
- 大数据文件,非常适合上T级别的大文件或者一堆大数据文件的存储。
- 文件分块存储,HDFS会将一个完整的大文件平均分块存储到不同计算器上,它的意义在于读取文件时可以同时从多个主机取不同区块的文件,多主机读取比单主机读取效率要高得多。
- 流式数据访问,一次写入多次读写,这种模式跟传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。
- 廉价硬件,HDFS可以应用在普通PC机上,这种机制能够让给一些公司用几十台廉价的计算机就可以撑起一个大数据集群。
- 硬件故障,HDFS认为所有计算机都可能会出问题,为了防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其它某几个主机上,如果其中一台主机失效,可以迅速找另一块副本取文件。
Block数据块
- 基本存储单位,一般大小为64M,配置大的块主要是因为:
- 减少搜寻时间,一般硬盘传输速率比寻道时间要快,大的块可以减少寻道时间;
- 减少管理块的数据开销,每个块都需要在NameNode上有对应的记录;
- 对数据块进行读写,减少建立网络的连接成本
- 一个大文件会被拆分成一个个的块,然后存储于不同的机器。如果一个文件少于Block大小,那么实际占用的空间为其文件的大小
- 基本的读写单位,类似于磁盘的页,每次都是读写一个块
- 每个块都会被复制到多台机器,默认复制3份
NameNode
- 存储文件的metadata,运行时所有数据都保存到内存,整个HDFS可存储的文件数受限于NameNode的内存大小
- 一个Block在NameNode中对应一条记录(一般一个block占用150字节),如果是大量的小文件,会消耗大量内存。同时map task的数量是由splits来决定的,所以用MapReduce处理大量的小文件时,就会产生过多的map task,线程管理开销将会增加作业时间。处理大量小文件的速度远远小于处理同等大小的大文件的速度。因此Hadoop建议存储大文件
- 数据会定时保存到本地磁盘,但不保存block的位置信息,而是由DataNode注册时上报和运行时维护(NameNode中与DataNode相关的信息并不保存到NameNode的文件系统中,而是NameNode每次重启后,动态重建)
- NameNode失效则整个HDFS都失效了,所以要保证NameNode的可用性
Secondary NameNode
定时与NameNode进行同步(定期合并文件系统镜像和编辑日志,然后把合并后的传给NameNode,替换其镜像,并清空编辑日志,类似于CheckPoint机制),但NameNode失效后仍需要手工将其设置成主机。
DataNode
- 保存具体的block数据
- 负责数据的读写操作和复制操作
- DataNode启动时会向NameNode报告当前存储的数据块信息,后续也会定时报告修改信息
- DataNode之间会进行通信,复制数据块,保证数据的冗余性
二:Hadoop 写文件
- 客户端将文件写入本地磁盘的HDFS Client文件中
- 当临时文件大小达到一个block大小时,HDFS client通知NameNode,申请写入文件
- NameNode在HDFS的文件系统中创建一个文件,并把该block id和要写入的DataNode的列表返回给客户端
- 客户端收到这些信息后,将临时文件写入DataNodes
4.1 客户端将文件内容写入第一个DataNode(一般以4kb为单位进行传输)
4.2 第一个DataNode接收后,将数据写入本地磁盘,同时也传输给第二个DataNode
4.3 依此类推到最后一个DataNode,数据在DataNode之间是通过pipeline的方式进行复制的
4.4 后面的DataNode接收完数据后,都会发送一个确认给前一个DataNode,最终第一个DataNode返回确认给客户端
4.5 当客户端接收到整个block的确认后,会向NameNode发送一个最终的确认信息
4.6 如果写入某个DataNode失败,数据会继续写入其他的DataNode。然后NameNode会找另外一个好的DataNode继续复制,以保证冗余性
4.7 每个block都会有一个校验码,并存放到独立的文件中,以便读的时候来验证其完整性 - 文件写完后(客户端关闭),NameNode提交文件(这时文件才可见,如果提交前,NameNode垮掉,那文件也就丢失了。fsync:只保证数据的信息写到NameNode上,但并不保证数据已经被写到DataNode中)
三:Hadoop 读文件
- 客户端向NameNode发送读取请求
- NameNode返回文件的所有block和这些block所在的DataNodes(包括复制节点)
- 客户端直接从DataNode中读取数据,如果该DataNode读取失败(DataNode失效或校验码不对),则从复制节点中读取(如果读取的数据就在本机,则直接读取,否则通过网络读取)
四:HDFS 可靠性
- DataNode可以失效,DataNode会定时发送心跳到NameNode。如果一段时间内NameNode没有收到DataNode的心跳消息,则认为其失效。此时NameNode就会将该节点的数据(从该节点的复制节点中获取)复制到另外的DataNode中
- 数据可以毁坏,无论是写入时还是硬盘本身的问题,只要数据有问题(读取时通过校验码来检测),都可以通过其他的复制节点读取,同时还会再复制一份到健康的节点中
- NameNode不可靠
五:hadoop fs
- hdfs dfs: 只能操作HDFS上的文件
- hadoop fs:除了能操作HDFS上的文件还可以操作本地文件
在使用HDFS Shell时为了减少不必要的日志,建议把日志调试正INFO级别,如果是DEBUG级别每执行一个命令就会打印很多内容。
hadoop-env.sh
export HADOOP_ROOT_LOGGER=INFO,console
1. hadoop fs -help
帮助命令, 用于查看某个命令如何使用
# 查看fs所有的命令
hadoop fs -help
# 查看ls命令的用法
hadoop fs -help ls
2. hadoop fs -mkdir
# 创建多级目录
hadoop fs -mkdir -p /helloworld/input
3. hadoop fs -moveFromLocal 、hadoop fs -put、hadoop fs -copyFromLocal
上传本地文件:将本地文件上传到hdfs中。
# 上传成功后会删除本地文件
hadoop fs -moveFromLocal <本地文件路径> <HDFS目录路径>
# 上传成功后不会删除本地文件
hadoop fs -put <本地目录> <HDFS目录>
# 复制本地目录到HDFS目录, 不会删除本地文件
hadoop fs -copyFromLocal <本地目录> <HDFS目录>
# 创建两个文件
echo "hello hadoop hdfs test" > /tmp/test.txt
echo "Hadoop Distributed File System foo" > /tmp/foo.txt
cho "hdfs foobar" > /tmp/foobar.txt
# 会删除/tmp/test.txt文件
hadoop fs -moveFromLocal /tmp/test.txt /helloworld/input
# 不会删除/tmp/foo.txt文件
hadoop fs -put /tmp/foo.txt /helloworld/input
# 和put类似,不会删除本地文件
hadoop fs -copyFromLocal /tmp/foobar.txt /helloworld/input
4.列举目录内容
# 查看根目录下的内容
hadoop fs -ls <HDFS文件目录>
# -R:递归显示
hadoop fs -ls -R <HDFS文件目录>
# 列举根目录文件
hadoop fs -lsr /
# 递归列举根目录文件
hadoop fs -ls -R /
# 列举指定目录文件
hadoop fs -ls /helloworld/input
5. 查看文件内容
hadoop fs -cat <文件路径>
hadoop fs -text <文件路径>
# 显示HDFS上某文件最后1kb内容
hadoop fs -tail <HDFS文件路径>
# 显示HDFS上某文件最后1kb内容, 如果有心数据进来会实时显示
hadoop fs -tail -f <HDFS文件路径>
hadoop fs -cat /helloworld/input/foo.txt
hadoop fs -text /helloworld/input/foo.txt
hadoop fs -tail /helloworld/input/foo.txt
6. hadoop fs -cp
# 将HDFS某个文件复制到HDFS其它路径下
hadoop fs -cp <HDFS文件源路径> <HDFS文件目标路径>
hadoop fs -cp /helloworld/input/foobar.txt /helloworld/input/foobar.backup.txt
7. hadoop fs -mv
# 移动HDFS上的文件
hadoop fs -mv <HDFS文件源路径> <HDFS文件目标路径>
hadoop fs -mv /helloworld/input/foobar.backup.txt /helloworld/backup
8. hadoop fs -appendToFile
# 将本地文件的内容追加到HDFS某文件内容的末尾
hadoop fs -appendToFile <本地文件路径> <HDFS文件路径>
echo "append content" > /tmp/a.txt
hadoop fs -appendToFile /tmp/a.txt /helloworld/input/foobar.txt
hadoop fs -cat /helloworld/input/foobar.txt
9. hadoop fs -find
根据名称查找文件
# name 不区分大小写
# iname 区分大小写
# print 打印(默认)
# print0 打印在一行
hadoop fs -find <路径> -name <文件名> -print
hadoop fs -find /helloworld/input/ -name foo.txt
10. hadoop fs -count
# 统计目录文件大小
hadoop fs -count <HDFS路径>
hadoop fs -count /helloworld/input
11. hadoop fs -copyToLocal、hadoop fs -get、hadoop fs -getmerge
# 将HDFS目录下载到本地文件
hadoop fs -copyToLocal <HDFS文件路径> <本地目录>
hadoop fs -get <HDFS文件路径> <本地目录>
# 合并下载多个文件
hadoop fs -getmerge <HDFS目录路径> <本地文件路径>
hadoop fs -copyToLocal /helloworld/input /Users/mengday/Desktop/
hadoop fs -get /helloworld/input /Users/mengday/Desktop/download
hadoop fs -getmerge /helloworld/input /Users/mengday/Desktop/merge.txt
12. hadoop fs -rmdir、hadoop fs -rm
# 删除空文件夹
hadoop fs -rmdir <HDFS空文件夹>
# 递归(-r)删除文件或者文件夹
hadoop fs -rm -r <HDFS目录>
hadoop fs -rmr <HDFS目录>
hadoop fs -rm -r /helloworld/backup
13. hadoop fs -chgrp、hadoop fs -chmod、hadoop fs -chown
# 修改某目录的所有组为root用户
hadoop fs -chgrp -R root <hdfs目录>
# 修改文件权限
hadoop fs -chmod -R 777 <hdfs目录>
# 修改所有者为root用户
hadoop fs -chown -R root <hdfs目录>
六:hadoop fsck
- move: 移动损坏的文件到/lost+found目录下
- delete: 删除损坏的文件
- openforwrite: 输出检测中的正在被写的文件
- list-corruptfileblocks: 输出损坏的块及其所属的文件
- files: 输出正在被检测的文件
- blocks: 输出block的详细报告 (需要和-files参数一起使用)
- locations: 输出block的位置信息 (需要和-files参数一起使用)
- racks: 输出文件块位置所在的机架信息(需要和-files参数一起使用
# 查看HDFS中某个文件的块block分布
hadoop fsck / -files -blocks -locations -racks
# 检测存在那些坏块
hdfs fsck /
# 删除坏块
hdfs fsck / -delete