认识HDFSHDFS是用来解决什么问题的
HDFS设计与架构
熟悉hdfs常用命令
Python操作HDFS的其他API
观察上传后的文件,上传大于128M的文件与小于128M的文件有何区别?
启动HDFS后,会分别启动NameNode/DataNode/SecondaryNameNode,这些进程的的作用分别是什么?
NameNode是如何组织文件中的元信息的,edits log与fsImage的区别?使用hdfs oiv命令观察HDFS上的文件的metadata
HDFS文件上传下载过程,源码阅读与整理。
1.认识HDFS
HDFS是用来解决什么问题的
Hadoop 附带了一个名为 HDFS(Hadoop分布式文件系统)的分布式文件系统,专门存储超大数据文件,为整个Hadoop生态圈提供了基础的存储服务。
HDFS专为解决大数据存储问题而产生的,其具备了以下特点:
1) HDFS文件系统可存储超大文件
HDFS文件的大小可以大于网络中任意一个磁盘的容量,文件的所有块并不需要存储在一个磁盘上,因此可以利用集群上任意一个磁盘进行存储,由于具备这种分布式存储的逻辑,所以可以存储超大的文件,通常G、T、P级别。
2) 一次写入,多次读取
一个文件经过创建、写入和关闭之后就不需要改变,这个假设简化了数据一致性的问题,同时提高数据访问的吞吐量。
3) 运行在普通廉价的机器上
Hadoop的设计对硬件要求低,无需昂贵的高可用性机器上,因为在HDFS设计中充分考虑到了数据的可靠性、安全性和高可用性。
不适用于HDFS的场景:
1) 低延迟
HDFS不适用于实时查询这种对延迟要求高的场景,例如:股票实盘。往往应对低延迟数据访问场景需要通过数据库访问索引的方案来解决,Hadoop生态圈中的Hbase具有这种随机读、低延迟等特点。
2) 大量小文件
对于Hadoop系统,小文件通常定义为远小于HDFS的block size(默认64MB)的文件,由于每个文件都会产生各自的MetaData元数据,Hadoop通过Namenode来存储这些信息,若小文件过多,容易导致Namenode存储出现瓶颈。
3) 多用户更新
为了保证并发性,HDFS需要一次写入多次读取,目前不支持多用户写入,若要修改,也是通过追加的方式添加到文件的末尾处,出现太多文件需要更新的情况,Hadoop是不支持的。
针对有多人写入数据的场景,可以考虑采用Hbase的方案。
4) 结构化数据
HDFS适合存储半结构化和非结构化数据,若有严格的结构化数据存储场景,也可以考虑采用Hbase的方案。
5) 数据量并不大
通常Hadoop适用于TB、PB数据,若待处理的数据只有几十GB的话,不建议使用Hadoop,因为没有任何好处。
HDFS设计与架构
HDFS是一个主/从(Master/Slave)体系架构,由于分布式存储的性质,集群拥有两类节点NameNode和DataNode。
NameNode(名字节点):系统中通常只有一个,中心服务器的角色,管理存储和检索多个DataNode的实际数据所需的所有元数据。
DataNode(数据节点):系统中通常有多个,是文件系统中真正存储数据的地方,在NameNode统一调度下进行数据块的创建、删除和复制。
2.熟悉hdfs常用命令
命令基本格式:
hadoop fs -cmd < args >
1) 打印文件列表(ls)
# 列出hdfs文件系统根目录下的目录和文件
# 标准写法:
hadoop fs -ls hdfs:/ #hdfs: 明确说明是HDFS系统路径
# 简写:
hadoop fs -ls / #默认是HDFS系统下的根目录
# 打印指定子目录:
hadoop fs -ls /package/test/ #HDFS系统下某个目录
# 列出hdfs文件系统所有的目录和文件
hadoop fs -ls -R /
2) 上传文件、目录(put、copyFromLocal)
put用法:
上传新文件:
hdfs fs -put file:/root/test.txt hdfs:/ #上传本地test.txt文件到HDFS根目录,HDFS根目录须无同名文件,否则“File exists”
hdfs fs -put test.txt /test2.txt #上传并重命名文件。
hdfs fs -put test1.txt test2.txt hdfs:/ #一次上传多个文件到HDFS路径。
hdfs file的父目录一定要存在,否则命令不会执行
上传文件夹:
hdfs fs -put mypkg /newpkg #上传并重命名了文件夹。
上传目录
hdfs dir 一定要存在,否则命令不会执行
hadoop fs -put < local file or dir >...< hdfs dir >
覆盖上传:
hdfs fs -put -f /root/test.txt / #如果HDFS目录中有同名文件会被覆盖
从键盘读取输入到hdfs file中,按Ctrl+D结束输入,hdfs file不能存在,否则命令不会执行
hadoop fs -put - < hdsf file>
copyFromLocal用法:与put相类似,也可以从键盘读取输入到hdfs file中
上传文件并重命名:
hadoop fs -copyFromLocal file:/test.txt hdfs:/test2.txt
覆盖上传:
hadoop fs -copyFromLocal -f test.txt /test.txt
moveFromLocal:与put相类似,命令执行后源文件 local src 被删除,也可以从从键盘读取输入到hdfs file中
hadoop fs -moveFromLocal < local src > ... < hdfs dst >
3) 下载文件、目录(get、copyToLocal)
get用法:
拷贝文件到本地目录:
hadoop fs -get hdfs:/test.txt file:/root/
拷贝文件并重命名,可以简写:
hadoop fs -get /test.txt /root/test.txt
# local file不能和 hdfs file名字不能相同,否则会提示文件已存在,没有重名的文件会复制到本地
拷贝多个文件或目录到本地时,本地要为文件夹路径
hadoop fs -get < hdfs file or dir > ... < local dir >
# 注意:如果用户不是root, local 路径要为用户文件夹下的路径,否则会出现权限问题,
copyToLocal用法:与get类似
拷贝文件到本地目录:
hadoop fs -copyToLocal hdfs:/test.txt file:/root/
拷贝文件并重命名,可以简写:
hadoop fs -copyToLocal /test.txt /root/test.txt
4) 拷贝文件、目录(cp)
从本地到HDFS,同put,目标文件不能存在,否则命令不能执行
hadoop fs -cp file:/test.txt hdfs:/test2.txt
从HDFS到HDFS
hadoop fs -cp hdfs:/test.txt hdfs:/test2.txt
hadoop fs -cp /test.txt /test2.txt
目标文件夹要存在,否则命令不能执行
hadoop fs -cp < hdfs file or dir >... < hdfs dir >
5) 移动文件(mv)
hadoop fs -mv hdfs:/test.txt hdfs:/dir/test.txt
hadoop fs -mv /test.txt /dir/test.txt
源路径有多个时,目标路径必须为目录,且必须存在。
hadoop fs -mv < hdfs file or dir >... < hdfs dir >
注意:跨文件系统的移动(local到hdfs或者反过来)都是不允许的
6) 删除文件、目录(rm)
删除指定文件
hadoop fs -rm /a.txt
删除全部txt文件
hadoop fs -rm /*.txt
递归删除全部文件和目录
hadoop fs -rm -R /dir/
每次可以删除多个文件或目录
hadoop fs -rm < hdfs file > ...
hadoop fs -rm -r < hdfs dir>...
7) 读取文件(cat、tail)
hadoop fs -cat /test.txt #以字节码的形式读取
hadoop fs -tail /test.txt
8) 创建空文件(touchz)
hadoop fs - touchz /newfile.txt
9) 创建文件夹(mkdir)
hadoop fs -mkdir /newdir /newdir2 # 可以同时创建多个,只能一级一级的建目录,父目录不存在的话使用这个命令会报错
hadoop fs -mkdir -p /newpkg/newpkg2/newpkg3 # 同时创建父级目录,所创建的目录如果父目录不存在就创建该父目录
10) 获取逻辑空间文件、目录大小(du)
hadoop fs - du / #显示HDFS根目录中各文件和文件夹大小
hadoop fs -du -h / #以最大单位显示HDFS根目录中各文件和文件夹大小,文件的大小用方便阅读的形式表示,例如用64M代替67108864
hadoop fs -du -s / #仅显示HDFS根目录大小。即各文件和文件夹大小之和
11)合并文件(getmerge)
将hdfs指定目录下所有文件排序后合并到local指定的文件中,文件不存在时会自动创建,文件存在时会覆盖里面的内容
hadoop fs -getmerge < hdfs dir > < local file >
加上nl后,合并到local file中的hdfs文件之间会空出一行
hadoop fs -getmerge -nl < hdfs dir > < local file >
12)统计文件(count)
统计hdfs对应路径下的目录个数,文件个数,文件总计大小
显示为目录个数,文件个数,文件总计大小,输入路径
hadoop fs -count < hdfs path >
13)text
将文本文件或某些格式的非文本文件通过文本格式输出
hadoop fs -text < hdsf file>
14)setrep
改变一个文件在hdfs中的副本个数,上述命令中数字3为所设置的副本个数,-R选项可以对一个人目录下的所有目录+文件递归执行改变副本个数的操作
hadoop fs -setrep -R 3 < hdfs path >
13.stat
hadoop fs -stat [format] < hdfs path >
返回对应路径的状态信息
[format]可选参数有:%b(文件大小),%o(Block大小),%n(文件名),%r(副本个数),%y(最后一次修改日期和时间)
可以这样书写hadoop fs -stat %b%o%n < hdfs path >,不过不建议,这样每个字符输出的结果不是太容易分清楚
14)tail
在标准输出中显示文件末尾的1KB数据
hadoop fs -tail < hdfs file >
15)archive
hadoop archive -archiveName name.har -p < hdfs parent dir > < src >* < hdfs dst >
命令中参数name:压缩文件名,自己任意取;< hdfs parent dir > :压缩文件所在的父目录;< src >:要压缩的文件名;< hdfs dst >:压缩文件存放路径
*示例:hadoop archive -archiveName hadoop.har -p /user 1.txt 2.txt /des
示例中将hdfs中/user目录下的文件1.txt,2.txt压缩成一个名叫hadoop.har的文件存放在hdfs中/des目录下,如果1.txt,2.txt不写就是将/user目录下所有的目录和文件压缩成一个名叫hadoop.har的文件存放在hdfs中/des目录下
显示har的内容可以用如下命令:
hadoop fs -ls /des/hadoop.jar
显示har压缩的是那些文件可以用如下命令
hadoop fs -ls -R har:///des/hadoop.har
注意:har文件不能进行二次压缩。如果想给.har加文件,只能找到原来的文件,重新创建一个。har文件中原来文件的数据并没有变化,har文件真正的作用是减少NameNode和DataNode过多的空间浪费。
16)balancer
hdfs balancer
如果管理员发现某些DataNode保存数据过多,某些DataNode保存数据相对较少,可以使用上述命令手动启动内部的均衡过程
17)dfsadmin
hdfs dfsadmin -help
管理员可以通过dfsadmin管理HDFS,用法可以通过上述命令查看
hdfs dfsadmin -report
显示文件系统的基本数据
hdfs dfsadmin -safemode < enter | leave | get | wait >
enter:进入安全模式;leave:离开安全模式;get:获知是否开启安全模式;
wait:等待离开安全模式
18)distcp
用来在两个HDFS之间拷贝数据
参考:
3.Python操作HDFS的其他API
使用python操作hdfs本身并不难,只不过是把对应的shell 功能“翻译”成高级语言,网上大部分使用的是
pyhdfs:官方文档
hdfs:官方文档
选一种就可以。也可以两个都试一下。
首先要安装pip:
yum install python-pip
pip install --upgrade pip # 升级
然后安装pyhdfs/hdfs:
pip install pyhdfs/hdfs
以hdfs为例,尝试参考资料中的基本命令。
4.观察上传后的文件,上传大于128M的文件与小于128M的文件有何区别?
到浏览器里看会发现:
两个文件的Block Size都是128M。无论多大的文件在HDFS中都是以Block为单位存储的。大于128MB会被分为两个block存储,小于128MB就是1个block存储。
我们在HDFS中存储数据是以块(block)的形式存放在DataNode中的,块(block)的大小可以通过设置dfs.blocksize来实现;
在Hadoop2.x的版本中,文件块的默认大小是128M,老版本中默认是64M;
寻址时间:HDFS中找到目标文件块(block)所需要的时间。
原理:
文件块越大,寻址时间越短,但磁盘传输时间越长;
文件块越小,寻址时间越长,但磁盘传输时间越短。一、为什么HDFS中块(block)不能设置太大,也不能设置太小?
1. 如果块设置过大,
一方面,从磁盘传输数据的时间会明显大于寻址时间,导致程序在处理这块数据时,变得非常慢;
另一方面,mapreduce中的map任务通常一次只处理一个块中的数据,如果块过大运行速度也会很慢。
2. 如果块设置过小,
一方面存放大量小文件会占用NameNode中大量内存来存储元数据,而NameNode的内存是有限的,不可取;
另一方面文件块过小,寻址时间增大,导致程序一直在找block的开始位置。
因而,块适当设置大一些,减少寻址时间,那么传输一个由多个块组成的文件的时间主要取决于磁盘的传输速率。
二、 HDFS中块(block)的大小为什么设置为128M?
1. HDFS中平均寻址时间大概为10ms;
2. 经过前人的大量测试发现,寻址时间为传输时间的1%时,为最佳状态;
所以最佳传输时间为10ms/0.01=1000ms=1s
3. 目前磁盘的传输速率普遍为100MB/s;
计算出最佳block大小:100MB/s x 1s = 100MB
所以我们设定block大小为128MB。
ps:实际在工业生产中,磁盘传输速率为200MB/s时,一般设定block大小为256MB
磁盘传输速率为400MB/s时,一般设定block大小为512MB
5.启动HDFS后,会分别启动NameNode/DataNode/SecondaryNameNode,这些进程的的作用分别是什么?
NameNode主要是用来保存HDFS的元数据信息,比如命名空间信息,块信息等。当它运行的时候,这些信息是存在内存中的。但是这些信息也可以持久化到磁盘上。Namenode 管理着文件系统的Namespace。它维护着文件系统树(filesystem tree)以及文件树中所有的文件和文件夹的元数据(metadata)。
Datanode是文件系统的工作节点,他们根据客户端或者是namenode的调度存储和检索数据,并且定期向namenode发送他们所存储的块(block)的列表。
集群中的每个服务器都运行一个DataNode后台程序,这个后台程序负责把HDFS数据块读写到本地的文件系统。当需要通过客户端读/写某个 数据时,先由NameNode告诉客户端去哪个DataNode进行具体的读/写操作,然后,客户端直接与这个DataNode服务器上的后台程序进行通 信,并且对相关的数据块进行读/写操作。
Secondary NameNode是一个用来监控HDFS状态的辅助后台程序。就想NameNode一样,每个集群都有一个Secondary NameNode,并且部署在一个单独的服务器上。Secondary NameNode不同于NameNode,它不接受或者记录任何实时的数据变化,但是,它会与NameNode进行通信,以便定期地保存HDFS元数据的 快照。由于NameNode是单点的,通过Secondary NameNode的快照功能,可以将NameNode的宕机时间和数据损失降低到最小。同时,如果NameNode发生问题,Secondary NameNode可以及时地作为备用NameNode使用。
6.NameNode是如何组织文件中的元信息的,edits log与fsImage的区别?使用hdfs oiv命令观察HDFS上的文件的metadata
1)NameNode是如何组织文件中的元信息的:
2)fsimage - 它是在NameNode启动时对整个文件系统的快照
edit logs - 它是在NameNode启动后,对文件系统的改动序列
只有在NameNode重启时,edit logs才会合并到fsimage文件中,从而得到一个文件系统的最新快照。但是在产品集群中NameNode是很少重启的,这也意味着当NameNode运行了很长时间后,edit logs文件会变得很大。
参考:
3)命令hdfs oiv用于将fsimage,edits文件转换成其他格式的,如文本文件、XML文件。
该命令需要以下参数:
必须参数:
-i,–inputFile 输入FSImage文件.
-o,–outputFile 输出转换后的文件,如果存在,则会覆盖
可选参数:
-p,–processor 将FSImage文件转换成哪种格式: (Ls|XML|FileDistribution).默认为Ls.
-h,–help 显示帮助信息
例子1:
hdfs oiv -i /data1/hadoop/dfs/name/current/fsimage_0000000000019372521 -o /home/hadoop/fsimage.txt
执行后查看more /home/Hadoop/fsimage.txt
7.HDFS文件上传下载过程,源码阅读与整理。
参考: