HDFS基本操作命令和读写原理
- 一、基本操作命令
- 1、创建目录 mkdir
- 2、查看文件,ls 没有cd命令, 需要指绝对路径
- 3、上传文件 put
- 4、下载文件 get
- 5、复制 cp
- 6、查看文件内容 cat , 如果数据量比较大,不能使用
- 7、移动 mv, 物理层面文件没有移动,只是改变了元数据(目录结构)
- 8、删除文件或者目录 rmr
- 8.1回收站自动清理
- 8.2手动删除回收站
- 8.3强制删除,-skipTrash 当需要删除的文件比较大的时候
- 9、查看文件末尾 tail -f ; 一直等待查看
- 10、查看文件的大小
- 二、读写原理
- 1.读数据
- 2.写数据
- 三、优缺点
- 1.优点:
- 2.缺点:
一、基本操作命令
1、创建目录 mkdir
mkdir : 创建目录
/data ; 路径 , 需要从 "/" 开始
hadoop dfs -mkdir /data
-p : 递归创建多级目录
hadoop dfs -mkdir -p /a/b/c2、查看文件,ls 没有cd命令, 需要指绝对路径
hadoop dfs -ls /data
权限(rwx(当前用户的权限) ,r-x (当前用户组的权限) ,r-x 其他用户的权限))
drwxr-xr-x - root supergroup 0 2021-01-05 00:11 /a
drwxr-xr-x - root supergroup 0 2021-01-05 00:09 /data3、上传文件 put
创建路径
hadoop dfs -mkdir /data/student
上传学生表的数据到hdfs, students.txt: linux本地的一个文件,/data/student: hdfs 目录
hadoop dfs -put students.txt /data/student
hadoop dfs -mkdir /data/score
hadoop dfs -put score.txt /data/score
hadoop dfs -mkdir /data/cource
hadoop dfs -put cource.txt /data/cource4、下载文件 get
将hdfs文件下载到linux本地
hadoop dfs -get /data/student/students.txt5、复制 cp
/data/a.txt :源文件或者目录
/ : 目标目录
hadoop dfs -cp /data/a.txt /6、查看文件内容 cat , 如果数据量比较大,不能使用
hadoop dfs -cat /data/student/students.txt7、移动 mv, 物理层面文件没有移动,只是改变了元数据(目录结构)
hadoop dfs -mv /a.txt /a8、删除文件或者目录 rmr
hadoop dfs -rmr /a/a.txt
并没有真正删除文件,只是将文件放到了回收站中,
/user/root/.Trash/Current ; 每一个用户都有一个回收站文件永久删除:
8.1回收站自动清理
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>8.2手动删除回收站
Hadoop dfs -rmr /user/root/.Trash/Current8.3强制删除,-skipTrash 当需要删除的文件比较大的时候
hadoop dfs -rmr -skipTrash /a9、查看文件末尾 tail -f ; 一直等待查看
hadoop dfs -tail /data/student/students.txt10、查看文件的大小
hadoop dfs -du -h /data二、读写原理
首先了解下面三个东西
1.block:
前面也提到过block块,它是数据存储的最大单位,在进行文件上传前client会对文件进行分块,分得的块就是block,默认128M,这是在综合考虑寻址时间和传输效率的的情况下得出的最佳大小。
2.packet:
packet是client向DataNode传输数据时候的基本单位,默认64KB。
3.chunk:
chunk是进行数据校验的基本单位,默认512Byte,加上4Byte的校验位,实际上chunk写入packet的大小为516Byte,常见于client向DataNode进行的数据校验。
1.读数据


粗略流程:
1.客户端向namenode 请求下载文件,namenode 通过查询元数据,找到文件块所在的datanode地址。
2.挑选一台datanode(就近原则,然后随机)服务器,请求读取数据。
3.datanode 开始传输数据给客户端(从磁盘里面读取数据放入流,以packet 为单位来做校验)。
4.客户端以packet 为单位接收,先在本地缓存,然后写入目标文件。详细流程:
1.首先调用FileSystem的open方法获取一个DistributedFileSystem实例;
2.然后DistributedFileSystem实例通过RPC在NameNode里获得文件的第一批block的locations(可能
是需要读取文件的全部,也可能是一部分),同一个block会按照在DataNode的重复数返回多个locations;
3.返回的多个locations会按照Hadoop拓扑结构排序,按照就近原则来排序;
4.前面三步结束后会返回一个FSDataInputStream对象,通过调用read方法时,该对象会找出离客户端最近
的DataNode并与之建立连接;
5.数据通过io流从DataNode源源不断地流向客户端;
6.如果第一个block块数据读取完成,就会关闭指向第一个block块的DataNode连接,接着读取下一个block
块,直到把这一批的block块数据读取完成;
7.每读取完一个block块都会进行checksum验证(校验每个块的信息通过偏移量和预写值对比,写的时候是校
验packet的信息),如果读取 DataNode 时出现错误,客户端会 通知 NameNode,然后再从下一个拥有
block 拷贝的 DataNode 继续读;
8.如果第一批blocks读取完成,且文件读取还没有结束,也就是文件还没读完。FSDataInputStream就会
向NameNode获取下一批blocks的locations,然后重复上面的步骤,直到所有blocks读取完成,这时就会
关闭所有的流。2.写数据


粗略流程:
1.客户端向namenode 请求上传文件,namenode 检查目标文件是否已存在,父目录是否存在。
2.namenode 返回是否可以上传。
3.客户端请求第一个block 上传到哪几个datanode 服务器上。
4.namenode 返回3 个datanode 节点,分别为dn1、dn2、dn3。
5.客户端请求dn1 上传数据,dn1 收到请求会继续调用dn2,然后dn2 调用dn3,将这个通信管道建立完成
6.dn1、dn2、dn3 逐级应答客户端
7.客户端开始往dn1 上传第一个block(先从磁盘读取数据放到一个本地内存缓存),packet 为单位,dn1 收到一个packet 就会传给dn2,dn2 传给dn3;dn1 每传一个packet 会放入一个应答队列等待应答
8.当一个block 传输完成之后,客户端再次请求namenode 上传第二个block 的服务器。(重复执行3-7 步)细致流程:
1.客户端使用Configuration类加载配置文件信息,然后调用FileSystem的get()方法,获取一个分布式文
件系统对象DistributedFileSystem。然后通过调用这个对象的create方法,向NameNode发送写文件请求;
2.客户端通过RPC与NameNode进行通信,NameNode需要经过各种不同的检查,比如命名空间里该路径文件是
否存在,客户端是否有相应权限。如果没有通过,返回IOException,反之如果检查通过,NameNode就会在
命名空间下新建该文件(此时新文件大小为0字节),并记录元数据,返回一个FSDataOutputStream输出流对象;
3.FSDataOutputStream封装了一个DFSOutputStream对象,由该对象负责处理datanode和namenode之间
的通信。(DistributedFileSystem.create()会DFSClient.create()方法创建DFSOutputStream输出
流并构造一个HdfsDataOutputStream来包装DFSOutputStream);
4.客户端把数据按照block块进行切分;
5.然后调用DFSOutputStream的create方法,开始执行写入操作(FSDataOutputStream封装了一个DFSOutputStream对象,由该对象负责处理datanode和namenode之间的通信),DFSOutputStream会把
数据切成一个个小packet,然后排成队列 dataQueue;
6.DataStreamer(DFSOutputStream的内部线程类)会去处理dataQueue,它先问询 NameNode 这个新的
block 最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们
排成一个 pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 的内存中,然后
第一个 DataNode又把 packet 输出到第二个 DataNode 中,以此类推;
7.在DataStreamer将packet写入pipeline时,同时也会将该packet存储到另外一个由ResponseProcessor
线程管理的缓存队列ackqueue确认队列中。ResponseProcessor线程会等待DataNode的确认响应。当收到所
有的DataNode的确认信息后,该线程再将ackqueue里的packet删除;
8.如果写入期间发生故障,会首先关闭pipeline,把ackqueue的所有packet都放回dataqueue的最前端,以
确保故障节点后的节点不会漏掉任一packet。同时,会标识正常的DataNode,方便在故障节点恢复后,删除错
误的部分数据块。然后从管线中删除故障节点,基于新的DataNode构建一个新的管线;
9.在一个block块大小的n个packet数据包写完后,客户端会调用FSDataOutputStream的close方法关闭写入
流,当然在调用close之前,DataNode会将内存中的数据写入本地磁盘;
10.最后DataStreamer会继续向NameNode请求下一个块的DataNode列表,开始下一个块的写入。直到写完整个
文件的最后一个块数据,然后客户端通知 NameNode 把文件标示为已完成,到这里整个写入过程就结束了。三、优缺点
数据的读写是HDFS的核心和考察重点,下面在结合着总结一下优缺点:
1.优点:
简单一致性模型:一次写入,多次读取,但要注意不能修改,只能追加;
高容错,低成本:可以搭建在廉价的机器上,并且数据以多副本保存在不同的服务器上,某个副本丢失,也能通过别的副本进行恢复;
流式数据访问:不是随机读写;
适合大规模数据集:能够进行批处理,支持横向扩展,支持PB级数据和10k节点规模。
2.缺点:
延迟高:不支持低延迟数据访问,做不到毫秒级存储数据,但是适合高吞吐率(某一时间内写入大量的数据)的场景;
不适合小文件:每条元数据占用空间是一定的,因此大量小文件会占用NameNode大量的内存来存储文件、目录和块信息;
不支持并发写入:一个文件只允许一个线程进行写操作,不适合并发写入;
不能修改和随机读写:文件不允许修改,只支持追加,同时也不是随机读写。
















