0. 教程地址
https://github.com/datawhalechina/juicy-bigdata/
1. 概述
1.1 分布式文件系统
1.1.1 块的对比
磁盘上每512字节为一个磁盘块,是由操作系统所决定的逻辑概念
-
普通文件系统
-
磁盘块是文件系统读写操作的最小单位
-
文件系统的块一般是磁盘块的整数倍
-
-
分布式文件系统
-
一般要比普通文件系统的文件块要大
-
例如老版本默认是64M,2.x以后是128M
-
1.1.2 块的大小
-
避免较小的块,设计较大的块可以:
-
最小化寻址开销(
HDFS
寻址开销包括:磁盘的寻道开销和数据块的定位开销) -
避免占用
NameNode
中大量内存来存储海量小文件的元数据
-
-
设计合适的块,避免更大的块可以:
-
避免传输时间过长:
从磁盘传输数据的时间会明显大于寻址时间,导致程序在处理这块数据时,变得非常慢
-
保证足够的并行速度:
MapReduce
中的Map
任务一次只处理一个块中的数据,如果块的容量比较大,那就意味着原始文件全部在一个块,而这一个块也只会被一个Map
去处理,这样也就只启动了一个任务。如果启动的任务太少,反而会影响并行的速度。
-
正常支持切分的数据:
而不持支切分的数据,就只有一个map
:
1.1.3 系统设计
1.1.3.1 整体设计
分布式文件系统一般采用C/S
模式,即:客户机/服务器(Client/Server)
服务器一方是计算机集群的节点,一般有两类节点
一个是“主节点”(Master Node),或者也被称为“名称节点"(NameNode)
另一类是“从节点"(Worker Node),或者也被称为“数据节点"(DataNode)
1.1.3.2 主节点、名称节点
-
负责文件和目录的创建、删除和重命名等
-
管理着数据节点和文件块的映射关系
-
客户端先从名称节点获取其所需文件的位置
-
然后再去相应的数据节点读取所需的文件
1.1.3.3 从节点、数据节点
-
负责数据的存储和读取。
-
存储文件时需要名称节点先分配存储位置,然后由客户端把数据直接写入相应数据节点
-
读取文件时需要名称节点先提供数据节点和文件块的映射关系,客户端再到相应位置访问
-
数据节点也要根据名称节点的命令创建、删除数据块和冗余复制,做好数据的维护工作
1.1.3.4 多副本设计
-
多副本存储可以避免计算机集群中节点故障的影响,保证数据的完整性
-
一个文件块的多个副本会存储在不同的节点上
-
而同一副本相应的节点会分布在不同的机器上
-
文件块的大小和副本个数通常可以由用户指定
-
过小的文件会严重影响到系统的扩展和性能
1.2 HDFS简介
1.2.1 优点
- 兼容廉价的硬件设备:
实现在硬件故障的情况下也能保障数据的完整性- 流数据读写:
不支持随机读写的操作- 大数据集:
数据量一般在GB、TB以上的级别- 简单的文件模型:
一次写入、多次读取- 强大的跨平台兼容性:
采用Java语言实现
1.2.1 缺点
- 不适合低延迟数据访问:
HDFS主要是面向大规模数据批量处理而设计的,采用流式数据读取,具有很高的数据吞吐率,但是,这也意味着较高的延迟,因此,HDFS不适合用在需要较低延迟(如数十毫秒)的应用场合。对于低延迟要求的应用程序而言,HBase是一个更好的选择;
- 无法高效存储大量小文件:
- 小文件是指文件大小小于一个块的文件,HDFS无法高效存储和处理大量的小文件,过多小文件会给系统扩展性和性能带来诸多问题:
- HDFS采用名称节点(NameNode)来管理文件系统的元数据,这些元数据被保存在内存中,使客户端可以快速获取文件实际存储位置。通常,每个文件、目录和块大约占150字节,如果有1000万个文件,每个文件对应一个块,那么,名称节点至少要消耗3GB的内存来保存这些元数据信息。很显然,这时元数据检索的效率就比较低了,需要花费较多的时间找到一个文件的实际存储位置。而且,如果继续扩展到数十亿个文件时,名称节点保存元数据所需要的内存空间就会大大增加,以现有的硬件水平,是无法在内存中保存如此大量的元数据;
- 用MapReduce处理大量小文件时,会产生过多的Map任务,线程管理开销会大大增加,因此处理大量小文件的速度远远低于处理同等大小的大文件的速度;
- 访问大量小文件的速度远远低于访问大文件的速度,因为访问大量小文件,需要不断从一个数据节点跳到另一个数据节点,严重影响性能。
- 不支持多用户写入及任意修改文件:HDFS只允许一个文件有一个写入者,不允许多个用户对同一个文件执行写操作,而且只允许对文件执行追加操作,不能执行随机写操作。
2. 体系结构
HDFS
是主从(Master/Slave)结构模型,一个集群内有一个名称节点(NameNode)和若干个数据节点(DataNode)
两者的设计基本与上文中分布式文件系统的设计保持一致,对数据的访问管理等操作也比较近似,其他的点有以下需要注意:
-
每个数据节点,也就是从节点,会周期性地向名称节点,也就是主节点,发送“心跳"信息,报告自己当前的状态。如果从节点没有按时发送心跳信息,那么主节点就会认为该数据节点出现故障,将不会再给他分配任何的I/O请求
-
当客户端需要操作文件时,一般都是和名称节点沟通文件的位置,然后访问对应的多个数据节点。因为一个文件可能包含多个数据块,而不同的块又是存储在不同的数据节点上,所以操作文件时可以并行地访问不同的数据节点来操作同一文件,这样能够有效地提高文件的处理速度。
3. 存储原理
3.1 冗余存储
参照上文分布式文件系统设计的描述,这里的冗余存储其实也就是多副本设计,即:一个数据块的多个副本会被分布到不同的数据节点上
这样的冗余存储设计有以下优点:
- 加快数据传输速度:
当多个客户端需要同时访问同一个文件时,可以让各个客户端分别从不同的数据块副本中读取数据,这就大大加快了数据传输速度,实现了并行操作。
- 容易检查数据错误:
HDFS的数据节点之间通过网络传输数据,采用多个副本可以很容易判断数据传输是否出错。
- 保证数据的可靠性:
即使某个数据节点出现故障失效,也不会造成数据丢失。
3.2 存取策略
3.2.1 数据存放
HDFS
采用了以机架(Rack
)为基础的数据存放策略
一个集群内包含多个机架,机架间的通信需要交换机或者路由器
机架内的通信则不需要,所以机架内的通信带宽更大
但是,HDFS
默认每个数据节点都在不同的机器上,这使得:
缺点:
- 写入数据的时候不能充分利用同一机架内部机器之间的带宽。
优点:
- 提高数据可靠性
即使一个机架发生故障,位于其他机架上的数据副本仍然可用。
- 提高了数据读取速度
在读数据的时候,可以在多个机架上并行读取数据
- 可以更容易实现系统内部负载均衡和错误纠正。
HDFS
的副本存放策略与上文的多副本设计类似:
即默认冗余复制因子为3
,每个文件有3
个副本
其中两份副本放在同一个机架的不同机器上面
而最后的第三个副本放在不同机架的机器上面
其具体的详细存放策略机制为:
-
对于第一个副本
-
如果是在集群内发起写操作请求,则把第1个副本放置在发起写操作请求的数据节点上,实现就近写入数据。
-
如果是来自集群外部的写操作,则从集群内部挑选一台磁盘空间较为充足、CPU不太忙的数据节点,作为第1个副本的存放地。
-
-
对于第二个副本
第2个副本会被放置在与第1个副本不同的机架的数据节点上。
-
对于第三个副本
第3个副本会被放置在与第1个副本相同的机架的其他节点上。
-
对于更多的副本
如果还有更多的副本,则继续从集群中随机选择数据节点进行存放。
3.2.2 数据读取
当客户端读取数据时:
-
从名称节点获取数据块不同副本的存放位置的数据节点列表
-
再调用API确定客户端和这些数据节点所属的机架ID。
-
当客户端发现某个数据块副本在同一机架,则优先选择该副本读取数据;
-
如果客户端没有发现同机架内的副本,则随机选择一个副本读取数据。
3.2.3 数据复制
当客户端要向HDFS中写入一个文件时:
这个文件会首先被写入本地,并根据设定值切分成若干个块
每个块都向名称节点发起写请求,名称节点会视使用情况,返回一个数据节点列表
然后客户端就把要写入的文件数据,以及给定的数据节点的列表,传给第1个数据节点
当第1个数据节点接收到数据的时候,将其写入本地,并且将数据和列表传给第2个数据节点
当第2个数据节点接收到数据的时候,将其写入本地,并且将数据和列表传给第3个数据节点
以此类推,列表中的多个数据节点形成一条数据复制的流水线。
最后,当文件写完的时候,数据复制也同时完成。
这个过程在下面的数据读写过程当中有更直观的图示
3.3 错误与恢复
3.3.1 主节点、名称节点出错
Hadoop
对主节点的保护如下:
-
名称节点上的元数据信息会被同步存储到其他文件系统中
-
运行维护一个第二名称节点,这里好像不是同步备份
根据教程所说,当第一名称节点挂掉的时候,如果直接根据第二名称恢复,仍然会丢失部分数据
看样子第二名称节点不是完整备份原节点的数据,所以一般的恢复方法是结合上述两种保护机制
先把同步备份到其他文件系统的原数据信息传到第二名称节点,再将其更新为第一名称节点
3.3.2 从节点、数据节点出错
数据节点一般是用心跳机制进行保护,如果主节点没有收到心跳,那就认为这个数据节点挂掉了
一方面,主节点不会再给其分配I/O,另一方面,如果这导致副本数量不足,主节点会生成新的副本
3.3.3 数据出错
数据出错一般是因为网络传输
和磁盘错误
这两种较为常见和主要的情况
为了防止出错,每个文件都在创建时生成了一个同一路径下隐藏的信息摘录文件
当客户端读取文件时,就会采用md5
和sha1
,并结合这个隐藏文件进行文件校验
如果校验出错,客户端就会查找自己接到的节点列表,去另外一个数据节点读取
同时会像向名称节点报告这里的错误,名称节点会定期检查并且重新复制这个块
4. 读写过程
这一部分可以结合对应的图示来理解:翻译经典 HDFS 原理讲解漫画
4.1 读数据
-
打开文件
客户端通过
FileSystem.open()
打开文件,对应在HDFS
的是DistributedFileSystem
客户端调用
open()
方法后,DistributedFileSystem
会创建输入流DFSInputStream
接下来的交互基本都是在
HDFS
内,所以具体发挥作用的就是DFSInputStream
-
获取数据块信息
客户端的
DFSInputStream
通过ClientProtocal.getBlockLocations()
远程调用名称节点名称节点返回保存该数据块的所有数据节点的地址,同时根据距离客户端的远近进行排序
然后
DFSInputStream
实例化FSDataInputStream
返回给客户端,同时返回数据节点列表 -
连接数据块
获得输入流
FSDataInputStream
后,客户端调用read()
函数读取数据。根据前面的排序结果,选择最近的数据节点建立连接并读取数据。
-
读取第一个数据块
客户端从该数据节点读取数据,读取完毕时由
FSDataInputStream
关闭连接如果客户端与数据节点通信时出现错误,那么客户端会尝试数据节点列表的下一个
-
查找下一个数据块
这一步在图中是
4.5
,需要跳回第二步查找下一个数据块的最佳节点位置如果客户端缓存中已经包含了该数据块的位置信息,就不需要调用该方法查找
-
读取完毕
当客户端读取完毕数据的时候,调用
FSDataInputStream
的close()
函数,关闭输入流。
4.2 写数据
-
客户端请求创建文件
客户端通过
FileSystem.create()
创建文件,对应在HDFS
的是DistributedFileSystem
客户端调用
create()
方法后,DistributedFileSystem
会创建输出流DFSOutputStream
-
名称节点进行检查
DFSOutputStream
通过RPC
远程调用名称节点,在文件系统的命名空间中创建新的文件名称节点会执行一些检查,比如文件是否已经存在,客户端是否有权限创建文件等
检查通过之后,名称节点会构造一个新文件,并添加文件信息,包括校验文件等
接着,
DFSOutputStream
会实例化FSDataOutputStream
返回给客户端,用于写入节点 -
客户端写入数据
客户端调用
FSDataOutputStream
的write()
方法向HDFS
中对应的文件写入数据。 -
HDFS
写入节点客户端向输出流
FSDataOutputStream
中写入的数据,会首先被分成一个个的分包这些分包被放入
DFSOutputStream
对象的内部队列,而不是FSDataOutputStream
FSDataOutputStream
会向名称节点申请保存文件和副本数据块的若干个数据节点这些数据节点形成一个数据流管道,并由第一个节点接收队列中的分包
第一个数据节点将数据包发送给第二个数据节点,第二个数据节点再给第三个
数据包会流经管道上的各个数据节点,即流水线复制策略
-
节点确认完成
因为各个数据节点位于不同机器上,而这意味着数据将通过网络发送,所以需要保证准确性
因此所有接收到数据的数据节点,都要向发送者发送“确认包”(
ACK Packet
)确认包沿着数据流管道逆流而上,从末端依次经过各个数据节点并最终发往客户端
当客户端收到应答时,它将对应的分包从内部队列移除,开始下一个,直到数据全部写完
-
客户端确认完成
客户端调用
close()
方法关闭输出流,这意味着客户端所需要写入的数据全部发送完毕接下来就等各个文件完成,也就是当
DFSOutputStream
对象内部队列中的分包都收到应答以后使用
ClientProtocol.complete()
方法通知名称节点关闭文件,完成一次正常的写文件过程
4.3 故障处理
这一部分可能和上面错误与恢复的内容略有重复
-
节点故障
这个问题,我们是通过心跳信号的机制来处理的,上面聊过
主节点
namenode
当中分别存有数据块和文件为索引的两张表其会维护这两个表,具体表现在维护文件有足够的副本数量
以及及时移除无效节点,来保持列表的数据节点有效
-
网络故障
据漫画中所说,每当发送一个数据,接收者都会返回一个应答信号
那么如果多次尝试后,都没有收到有效应答,那就会认为节点挂掉
-
数据损坏
这个问题上面也聊过,每个文件创建时都伴随一个摘要文件
我们利用
md5
和sha1
结合摘要文件来进行损坏的校验 -
读取故障
访问文件时,名称节点给的有该文件块的节点列表
所以如果当前的节点无效,访问列表的下一个节点就好
-
写入故障
写入文件时,如果节点写入成功,会返回
ack
信号,以此进行处理 -
副本策略
这个在上面也聊过,一个文件的默认副本数量是
3
如果写入者在集群内,那他就是第一副本的位置
如果不是的话,那就需要随机选择节点存第一副本
另外两个副本需要在与第一副本不同的同一个机架
至于如果可能有的更多的副本存放,需要注意:
首先是每个节点只能存放一个副本,不能更多
然后是每个机架最多有两个副本,也不能更多
5. 编程实战
先做一下准备工作吧,就是基于前面的实验环境
Ubuntu 20.04
,部署Java
,部署Hadoop 3.3.1
-
启动HDFS服务
教程上面写的是用
root
用户,有点神奇,我用专门建的hadoop
用户试试ubuntu@VM-0-12-ubuntu:~$ su master Password: master@VM-0-12-ubuntu:/home/ubuntu$ cd /opt/hadoop/sbin/ master@VM-0-12-ubuntu:/opt/hadoop/sbin$ ./start-dfs.sh Starting namenodes on [localhost] Starting datanodes Starting secondary namenodes [VM-0-12-ubuntu] master@VM-0-12-ubuntu:/opt/hadoop/sbin$
我感觉好像也没啥问题
-
查看HDFS进程
这里遇到一个神奇的问题,我之前装的好好的
java
不行了我上次还用过
jps
,这次java -version
都没有了,特别神奇然后我去看了文件和环境变量,一切正常,都没问题
然后我去
source /etc/profile
更新环境变量,可以了,不理解我觉得可能是因为关机的时候可能清掉了某些信息
所以会导致再次开机的时候需要重新操作
master@VM-0-12-ubuntu:/opt$ source /etc/profile master@VM-0-12-ubuntu:/opt$ jps 469651 NameNode 471120 Jps 469808 DataNode 470045 SecondaryNameNode master@VM-0-12-ubuntu:/opt$
-
验证HDFS运行状态
master@VM-0-12-ubuntu:/opt$ hadoop fs -ls / Found 4 items drwxr-xr-x - master supergroup 0 2022-03-15 23:38 /input drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out drwx------ - master supergroup 0 2022-03-15 23:39 /tmp drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user master@VM-0-12-ubuntu:/opt$ hadoop fs -mkdir /myhadoop1 master@VM-0-12-ubuntu:/opt$ hadoop fs -ls / Found 5 items drwxr-xr-x - master supergroup 0 2022-03-15 23:38 /input drwxr-xr-x - master supergroup 0 2022-03-17 19:21 /myhadoop1 drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out drwx------ - master supergroup 0 2022-03-15 23:39 /tmp drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user master@VM-0-12-ubuntu:/opt$
好了,接下来可以愉快地玩耍了
5.1 ls命令
列出hdfs文件系统根目录下的目录和文件,执行命令如下:
master@VM-0-12-ubuntu:/opt$ hadoop fs -ls /
Found 5 items
drwxr-xr-x - master supergroup 0 2022-03-15 23:38 /input
drwxr-xr-x - master supergroup 0 2022-03-17 19:21 /myhadoop1
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
列出hdfs文件系统所有的目录和文件,执行命令如下:
master@VM-0-12-ubuntu:/opt$ hadoop fs -ls -R /
drwxr-xr-x - master supergroup 0 2022-03-15 23:38 /input
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
drwxr-xr-x - master supergroup 0 2022-03-17 19:21 /myhadoop1
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
-rw-r--r-- 1 master supergroup 0 2022-03-15 23:39 /out/_SUCCESS
-rw-r--r-- 1 master supergroup 17 2022-03-15 23:39 /out/part-r-00000
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history
drwxrwxrwt - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history/done_intermediate
drwxrwx--- - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history/done_intermediate/master
-rwxrwx--- 1 master supergroup 22777 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history/done_intermediate/master/job_1647357988111_0001-1647358748535-master-word+count-1647358776955-1-1-SUCCEEDED-default-1647358761808.jhist
-rwxrwx--- 1 master supergroup 441 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history/done_intermediate/master/job_1647357988111_0001.summary
-rwxrwx--- 1 master supergroup 269494 2022-03-15 23:39 /tmp/hadoop-yarn/staging/history/done_intermediate/master/job_1647357988111_0001_conf.xml
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging/master
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp/hadoop-yarn/staging/master/.staging
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user/master
master@VM-0-12-ubuntu:/opt$
5.2 put命令
-
拷贝文件
也就是说将本地文件上传到HDFS,当然,我们需要保证HDFS的目录有效
hadoop fs -put <local file> <hdfs file>
例如我们在
Jbd2
当中执行word count
测试时候的命令master@VM-0-12-ubuntu:/$ hadoop fs -put /home/master/test /input
-
拷贝目录
hadoop fs -put <local dir> <hdfs dir>
与上一条命令没有什么区别,当然同样需要保证目录有效
-
查看结果
我们来看一看当初测试时候拷贝文件的结果
master@VM-0-12-ubuntu:/opt$ hadoop fs -ls /input Found 1 items -rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test master@VM-0-12-ubuntu:/opt$
5.3 moveFromLocal命令
我感觉就是属于剪贴命令,复制完毕后会删除本地文件,格式如下:
hadoop fs -moveFromLocal <local src> <hdfs dst>
实践如下:
master@VM-0-12-ubuntu:/opt$ hadoop fs -ls /input
Found 1 items
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ ls
cut.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -moveFromLocal /opt/master/cut.txt /input
master@VM-0-12-ubuntu:/opt/master$ ls
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 19:39 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$
5.4 get命令
这在命名上就是与put
相对应,所以就是从HDFS复制到本地:
hadoop fs -get < hdfs file or dir > < local file or dir>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ ls
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 19:39 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -get /input/cut.txt /opt/master
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 19:39 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ ls
cut.txt
master@VM-0-12-ubuntu:/opt/master$
注意:
拷贝多个文件或目录到本地时,本地要为文件夹路径
local file不能和hdfs file名字不能相同,否则会提示文件已存在。
如果用户不是root用户, local路径要使用该用户文件夹下的路径,否则会出现权限问题
我在上面的测试当中就遇到了问题,像新建一个测试文件,然后剪贴到HDFS
但是发现我是新建的Hadoop用户,所以说没有新建文件的权限,除非sudo
后来我在/opt
文件夹下新建了master
文件夹,并将所有者改为master
5.5 rm命令
这个可是写明了针对一个或者多个,而且也是对文件和目录都有效:
hadoop fs -rm <hdfs file> ...
hadoop fs -rm -r <hdfs dir> ...
实践如下,删一删我们之前新建的东西:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 19:39 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -rm /input/cut.txt
Deleted /input/cut.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 1 items
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /
Found 5 items
drwxr-xr-x - master supergroup 0 2022-03-17 19:49 /input
drwxr-xr-x - master supergroup 0 2022-03-17 19:21 /myhadoop1
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -rm -r /myhadoop1
Deleted /myhadoop1
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /
Found 4 items
drwxr-xr-x - master supergroup 0 2022-03-17 19:49 /input
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
master@VM-0-12-ubuntu:/opt/master$
5.6 mkdir命令
对于原始的命令,只能一级一级地新建目录,父目录不存在就会报错:
hadoop fs -mkdir <hdfs path>
但是如果加上了-p
参数,就可以同时新建不存在的父目录:
hadoop fs -mkdir -p <hdfs dir> ...
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /
Found 4 items
drwxr-xr-x - master supergroup 0 2022-03-17 19:49 /input
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -mkdir -p /master/data
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /
Found 5 items
drwxr-xr-x - master supergroup 0 2022-03-17 19:49 /input
drwxr-xr-x - master supergroup 0 2022-03-17 19:54 /master
drwxr-xr-x - master supergroup 0 2022-03-15 23:39 /out
drwx------ - master supergroup 0 2022-03-15 23:39 /tmp
drwxr-xr-x - master supergroup 0 2022-03-15 23:36 /user
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /master
Found 1 items
drwxr-xr-x - master supergroup 0 2022-03-17 19:54 /master/data
master@VM-0-12-ubuntu:/opt/master$
5.7 cp命令
这个就是在HDFS内部的操作了,复制命令啊,不知道可不可以多个,当然要保证路径有效:
hadoop fs -cp <hdfs file or dir>... <hdfs dir>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -cp /input/cut.txt /master/
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /master
Found 1 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:03 /master/cut.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$
5.8 mv命令
那对应的就是,剪贴命令,也可以重命名,总之路径要有效:
hadoop fs -mv <hdfs file or dir>... <hdfs dir>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -mv /input/test /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$
5.9 count命令
统计文件目录格式、文件个数、文件总计大小:
hadoop fs -count <hdfs path>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -count /input
1 2 14 /input
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -count /input/
1 2 14 /input
master@VM-0-12-ubuntu:/opt/master$
感觉比较神奇,/input
下面应该是只有两个文件,为什么统计出来还有一个目录,难道是包含自身?
5.10 du命令
原始命令是显示对应路径下每个文件夹和文件的大小:
hadoop fs -du <hdsf path>
加上-s
参数那就是显示路径下所有文件大小的总和
hadoop fs -du -s <hdsf path>
加上-h
参数,是在原始命令的基础上便于阅读
hadoop fs -du -h <hdsf path>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -du /input
0 0 /input/cut.txt
14 14 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -du -s /input
14 14 /input
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -du -h /input
0 0 /input/cut.txt
14 14 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -du -s -h /input
14 14 /input
master@VM-0-12-ubuntu:/opt/master$
执行结果说明:
- 第一列:
表示该目录下总文件大小
- 第二列:
表示该目录下所有文件在集群上的总存储大小,该大小和副本数相关
设置的默认副本数为3 ,所以第二列的是第一列的三倍
(第二列内容 = 文件大小 \times× 副本数)
- 第三列:
表示查询的目录
5.11 setrep命令
改变一个文件在HDFS中副本的个数,-R
意味着对一个目录下所有的目录和文件递归执行操作:
hadoop fs -setrep -R number <hdfs path>
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -setrep -R 1 /input
Replication 1 set: /input/cut.txt
Replication 1 set: /input/test.txt
master@VM-0-12-ubuntu:/opt/master$
挺神奇的,我这是单机版的伪分布式,只有一个节点,也成功了
5.12 stat命令
查看对应路径的状态信息:
hadoop fs -stat [format] < hdfs path >
可选的参数不少:
- %b:文件大小
- %o:Block大小
- %n:文件名
- %r:副本个数
- %y:最后一次修改日期和时间
实践如下:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat /input/test.txt
2022-03-15 15:38:43
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %b %o %n %r %y /input/test.txt
stat: `%o': No such file or directory
stat: `%n': No such file or directory
stat: `%r': No such file or directory
stat: `%y': No such file or directory
14
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %b /input/test.txt
14
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %o /input/test.txt
134217728
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %n /input/test.txt
test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %r /input/test.txt
1
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -stat %y /input/test.txt
2022-03-15 15:38:43
master@VM-0-12-ubuntu:/opt/master$
也挺神奇的,一次只能用一个参数,不带参数的话看的是最后修改时间
5.13 balancer命令
用于启动内部均衡过程,解决某些DataNode数据过多而同时另一些DataNode数据过少:
hadoop balancer
或
hdfs balancer
master@VM-0-12-ubuntu:/opt/master$ hadoop balancer
WARNING: Use of this script to execute balancer is deprecated.
WARNING: Attempting to execute replacement "hdfs balancer" instead.
2022-03-17 20:26:49,475 INFO balancer.Balancer: namenodes = [hdfs://localhost:9000]
2022-03-17 20:26:49,486 INFO balancer.Balancer: parameters = Balancer.BalancerParameters [BalancingPolicy.Node, threshold = 10.0, max idle iteration = 5, #excluded nodes = 0, #included nodes = 0, #source nodes = 0, #blockpools = 0, run during upgrade = false]
2022-03-17 20:26:49,486 INFO balancer.Balancer: included nodes = []
2022-03-17 20:26:49,486 INFO balancer.Balancer: excluded nodes = []
2022-03-17 20:26:49,486 INFO balancer.Balancer: source nodes = []
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved NameNode
2022-03-17 20:26:49,498 INFO balancer.NameNodeConnector: getBlocks calls for hdfs://localhost:9000 will be rate-limited to 20 per second
2022-03-17 20:26:51,304 INFO balancer.Balancer: dfs.namenode.get-blocks.max-qps = 20 (default=20)
2022-03-17 20:26:51,304 INFO balancer.Balancer: dfs.balancer.movedWinWidth = 5400000 (default=5400000)
2022-03-17 20:26:51,305 INFO balancer.Balancer: dfs.balancer.moverThreads = 1000 (default=1000)
2022-03-17 20:26:51,305 INFO balancer.Balancer: dfs.balancer.dispatcherThreads = 200 (default=200)
2022-03-17 20:26:51,305 INFO balancer.Balancer: dfs.balancer.getBlocks.size = 2147483648 (default=2147483648)
2022-03-17 20:26:51,305 INFO balancer.Balancer: dfs.balancer.getBlocks.min-block-size = 10485760 (default=10485760)
2022-03-17 20:26:51,305 INFO balancer.Balancer: dfs.datanode.balance.max.concurrent.moves = 100 (default=100)
2022-03-17 20:26:51,306 INFO balancer.Balancer: dfs.datanode.balance.bandwidthPerSec = 104857600 (default=104857600)
2022-03-17 20:26:51,316 INFO balancer.Balancer: dfs.balancer.max-size-to-move = 10737418240 (default=10737418240)
2022-03-17 20:26:51,317 INFO balancer.Balancer: dfs.blocksize = 134217728 (default=134217728)
2022-03-17 20:26:51,347 INFO net.NetworkTopology: Adding a new node: /default-rack/127.0.0.1:9866
2022-03-17 20:26:51,356 INFO balancer.Balancer: 0 over-utilized: []
2022-03-17 20:26:51,357 INFO balancer.Balancer: 0 underutilized: []
Mar 17, 2022 8:26:51 PM 0 0 B 0 B 0 B 0 hdfs://localhost:9000
The cluster is balanced. Exiting...
Mar 17, 2022 8:26:51 PM Balancing took 2.802 seconds
master@VM-0-12-ubuntu:/opt/master$ hdfs balancer
2022-03-17 20:27:03,194 INFO balancer.Balancer: namenodes = [hdfs://localhost:9000]
2022-03-17 20:27:03,206 INFO balancer.Balancer: parameters = Balancer.BalancerParameters [BalancingPolicy.Node, threshold = 10.0, max idle iteration = 5, #excluded nodes = 0, #included nodes = 0, #source nodes = 0, #blockpools = 0, run during upgrade = false]
2022-03-17 20:27:03,206 INFO balancer.Balancer: included nodes = []
2022-03-17 20:27:03,206 INFO balancer.Balancer: excluded nodes = []
2022-03-17 20:27:03,206 INFO balancer.Balancer: source nodes = []
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved NameNode
2022-03-17 20:27:03,210 INFO balancer.NameNodeConnector: getBlocks calls for hdfs://localhost:9000 will be rate-limited to 20 per second
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.namenode.get-blocks.max-qps = 20 (default=20)
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.balancer.movedWinWidth = 5400000 (default=5400000)
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.balancer.moverThreads = 1000 (default=1000)
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.balancer.dispatcherThreads = 200 (default=200)
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.balancer.getBlocks.size = 2147483648 (default=2147483648)
2022-03-17 20:27:04,990 INFO balancer.Balancer: dfs.balancer.getBlocks.min-block-size = 10485760 (default=10485760)
2022-03-17 20:27:04,991 INFO balancer.Balancer: dfs.datanode.balance.max.concurrent.moves = 100 (default=100)
2022-03-17 20:27:04,991 INFO balancer.Balancer: dfs.datanode.balance.bandwidthPerSec = 104857600 (default=104857600)
2022-03-17 20:27:04,998 INFO balancer.Balancer: dfs.balancer.max-size-to-move = 10737418240 (default=10737418240)
2022-03-17 20:27:04,998 INFO balancer.Balancer: dfs.blocksize = 134217728 (default=134217728)
2022-03-17 20:27:05,015 INFO net.NetworkTopology: Adding a new node: /default-rack/127.0.0.1:9866
2022-03-17 20:27:05,020 INFO balancer.Balancer: 0 over-utilized: []
2022-03-17 20:27:05,022 INFO balancer.Balancer: 0 underutilized: []
Mar 17, 2022 8:27:05 PM 0 0 B 0 B 0 B 0 hdfs://localhost:9000
The cluster is balanced. Exiting...
Mar 17, 2022 8:27:05 PM Balancing took 2.327 seconds
master@VM-0-12-ubuntu:/opt/master$
没想到单机版伪分布式也能运行成功,虽然确实没啥实际意义就是了
5.14 dfsadmin命令
属于是管理员的管理命令,需要追加参数
-help
参数可以查看相关帮助:
hdfs dfsadmin -help
-report
参数可以查看文件系统的基本数据:
hdfs dfsadmin -report
-safemode
参数可以操作安全模式,这个也有追加参数:
hdfs dfsadmin -safemode <enter | leave | get | wait>
其中:
- enter:进入安全模式
- leave:离开安全模式
- get:查看是否开启安全模式
- wait:等待离开安全模式
实践操作如下:
master@VM-0-12-ubuntu:/opt/master$ hdfs dfsadmin -help
hdfs dfsadmin performs DFS administrative commands.
Note: Administrative commands can only be run with superuser permission.
The full syntax is:
hdfs dfsadmin
[-report [-live] [-dead] [-decommissioning] [-enteringmaintenance] [-inmaintenance]]
[-safemode <enter | leave | get | wait | forceExit>]
[-saveNamespace [-beforeShutdown]]
[-rollEdits]
···
master@VM-0-12-ubuntu:/opt/master$ hdfs dfsadmin -report
Configured Capacity: 52781854720 (49.16 GB)
Present Capacity: 41042354176 (38.22 GB)
DFS Remaining: 41041985536 (38.22 GB)
DFS Used: 368640 (360 KB)
DFS Used%: 0.00%
Replicated Blocks:
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
Erasure Coded Block Groups:
Low redundancy block groups: 0
Block groups with corrupt internal blocks: 0
Missing block groups: 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
-------------------------------------------------
Live datanodes (1):
Name: 127.0.0.1:9866 (localhost)
Hostname: localhost.localdomain
Decommission Status : Normal
Configured Capacity: 52781854720 (49.16 GB)
DFS Used: 368640 (360 KB)
Non DFS Used: 9494781952 (8.84 GB)
DFS Remaining: 41041985536 (38.22 GB)
DFS Used%: 0.00%
DFS Remaining%: 77.76%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 0
Last contact: Thu Mar 17 20:32:09 CST 2022
Last Block Report: Thu Mar 17 19:13:58 CST 2022
Num of Blocks: 5
master@VM-0-12-ubuntu:/opt/master$ hdfs dfsadmin -safemode enter
Safe mode is ON
master@VM-0-12-ubuntu:/opt/master$ hdfs dfsadmin -safemode get
Safe mode is ON
master@VM-0-12-ubuntu:/opt/master$ hdfs dfsadmin -safemode leave
Safe mode is OFF
master@VM-0-12-ubuntu:/opt/master$
5.15 cat命令
用于查看HDFS当中文本文件的内容:
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -ls /input
Found 2 items
-rw-r--r-- 1 master supergroup 0 2022-03-17 20:01 /input/cut.txt
-rw-r--r-- 1 master supergroup 14 2022-03-15 23:38 /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -cat /input/test.txt
Hello world!
master@VM-0-12-ubuntu:/opt/master$
5.16 tail命令
应该是查看文件尾部的内容吧,跟Linux的命令差不多,-f
参数就是持续追踪,刷新文件
- 此时要想暂停刷新,使用Ctrl+S暂停终端,S表示sleep
- 若想要继续刷新终端,使用Ctrl+Q,Q表示quiet
- 若想退出tail命令,直接使用Ctrl+C,也可以使用Ctrl+Z Ctrl+C和Ctrl+Z都是中断命令,当他们的作用却不一样的:
- Ctrl+C比较暴力,就是发送Terminal到当前的程序,比如正在运行一个查找功能,文件正在查找中,使用Ctrl+C会强制结束当前这个进程
- Ctrl+Z则会将当前程序挂起,暂停执行这个程序,比如mysql终端下,需要跳出来执行其他的文件操作,又不想退出mysql终端(因为下次还需要输入用户名密码进入,很麻烦),于是可以使用Ctrl+Z将mysql挂起,然后进行其他操作,输入fg回车可以回到mysql终端,担任也可以挂起很多进程到后台,执行fg <编号>就能将挂起的进程返回到当前的终端。配合bg和fg命令能更方便的进行前后台切换
之前在打比赛的时候用过这个tail -f
,当时是配合另一个持续写入的命令,在记录的同时即时查看
5.17 appendToFile命令
将本地文件的内容追加到HDFS的文本文件,神奇:
hadoop fs -appendToFile <local file> <hdfs file>
实践操作如下:
master@VM-0-12-ubuntu:/opt/master$ cat /opt/master/cut.txt
new end
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -cat /input/test.txt
Hello world!
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -appendToFile /opt/master/cut.txt /input/test.txt
master@VM-0-12-ubuntu:/opt/master$ hadoop fs -cat /input/test.txt
Hello world!
new end
master@VM-0-12-ubuntu:/opt/master$
5.18 chown命令
该命令可以修改HDFS当中文件的读、写、执行权限:
hadoop fs -chown user:group /datawhale
hadoop fs -chmod 777 /datawhale
参数如下:
- chown:定义谁拥有文件
- chmod:定义可以对该文件做什么
最后,关闭环境!关闭环境!关闭环境!
实验完毕,当然要关闭实验环境啦,但是教程并没有做这一步…管杀不管埋啊
虽然好像即使不关闭也没啥大问题?不知道,万一下次再玩的时候出错了怎么办
master@VM-0-12-ubuntu:/opt/master$ cd /opt/hadoop/sbin/
master@VM-0-12-ubuntu:/opt/hadoop/sbin$ ls
distribute-exclude.sh kms.sh start-balancer.sh start-yarn.sh stop-dfs.sh yarn-daemon.sh
FederationStateStore mr-jobhistory-daemon.sh start-dfs.cmd stop-all.cmd stop-secure-dns.sh yarn-daemons.sh
hadoop-daemon.sh refresh-namenodes.sh start-dfs.sh stop-all.sh stop-yarn.cmd
hadoop-daemons.sh start-all.cmd start-secure-dns.sh stop-balancer.sh stop-yarn.sh
httpfs.sh start-all.sh start-yarn.cmd stop-dfs.cmd workers.sh
master@VM-0-12-ubuntu:/opt/hadoop/sbin$ ./stop-dfs.sh
Stopping namenodes on [localhost]
Stopping datanodes
Stopping secondary namenodes [VM-0-12-ubuntu]
master@VM-0-12-ubuntu:/opt/hadoop/sbin$