HDFS前言
设计的的思想:主要的是分而治之,将大的文件分割称为一个个小的文件,存储在各个机器上。
在大数据中的应用:为大数据框架提供储存数据的服务
重点概念:文件分块、副本存放、元数据。
HDFS的概念和特性
首先,它是一个文件系统,用于存储文件,通过统一的命名空间——目录树来定位文件。
其次,它是分布式的,很多服务器联合实现功能。
HDFS组成结构图
HDFS 写文件的基本流程
先来了解几个概念
block
文件上传前需要分块,这个块就是block,一般为128MB,当然你可以去改(改成多少跟磁盘性能有关)。block太小的话,会导致block的数量多,寻址block的时间就会增加。block太大的话,会导致Map任务数太少,作业执行速度变慢。它是最大的一个单位。
packet
packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。
chunk
chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128 : 1。(即64*1024 / 512)
例如,在client端向DataNode传数据的时候,HDFSOutputStream会有一个chunk buff,写满一个chunk后,会计算校验和并写入当前的chunk。之后再把带有校验和的chunk写入packet,当一个packet写满后,packet会进入dataQueue队列,其他的DataNode就是从这个dataQueue获取client端上传的数据并存储的。同时一个DataNode成功存储一个packet后之后会返回一个ack packet,放入ack Queue中。
详细步骤
- client请求NameNode上传文件,NameNode查询对应权限,目录存不存在等 返回是否可以上传。
- client对文件进行block切片,并请求NameNode第一个 Block 上传到哪几个 DataNode 服务器上。
- NameNode 根据副本数等信息返回可用的DataNode节点,例如上面的 dn1,dn2,dn3。
- client 请求3台节点中的一台服务器dn1,进行传送数据(本质上是一个RPC调用,建立管道Pipeline),dn1收到请求会继续调用服务器dn2,然后服务器dn3调用服务器dn3。将这个通信管道建立完成。
- client 开始往 dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以 Packet为单位,dn1收到一个 Packet就会传给 dn2,dn2传给 dn3;dn1每传一个 packet会放入一个应答队列等待应答。
- 数据被分割成一个个Packet数据包在Pipeline上依次传输,而在Pipeline反方向上,将逐个发送Ack(命令正确应答),最终由Pipeline中第一个DataNode节点dn1将Pipeline的 Ack信息发送给客户端。
- 当一个 Block传输完成之后,客户端再次请求 NameNode上传第二个 Block的服务器。
HDFS 读文件的基本流程
- client 通过 Distributed FileSystem向 NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址进行返回。
- 挑选一台 DataNode(就近原则,然后随机)服务器,请求读取数据。当第一次读取完成之后,才进行第二次块的读取。
- DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以 Packet为单位来做校验)。
- 客户端以 Packet为单位接收,先在本地缓存,然后写入目标文件。
NameNode+SecondaryNameNode工作原理
- 集群启动,会加载edits日志和fsimage文件到内存得到元数据。
- client发起元数据的修改操作时,NameNode先将操作顺序追加到edits_inprogress001文件(效率极高),然后更新到内存(保证元数据最新)。
- SecondaryNameNode会定期(一小时)或者 edits日志满了(比如到达了100w条),会请求NameNode进行CheckPoint。
- NameNode会生成一个新的edits_inprogress002 用于存储新的请求。然后将原来的edits_inprogress001 修改成edits_001。
- SecondaryNameNode 会将NameNode的edits_001 和 fsimage拉取过来,进行计算(执行edits里面的操作)合并成新的镜像文件(fsimage.chkpoint),然后发送给NameNode。
- NameNode将fsimage.chkpoint改名覆盖原来的fsimage 。这样fsimage 就保持了当前SecondaryNameNode计算合并的最新(加上edits_inprogress002 才是最新的元数据)。
为什么要有fsimage?
为了服务器断电后恢复元数据。fsimage就是元数据的磁盘镜像。
为什么要有edits日志?
没有这个日志,当我们修改元数据,就只能修改fsimage文件,修改磁盘文件是效率极低的。edits日志只能顺序追加,记录的是元数据的操作(类似redis的AOF),这个效率是极高的。后面通过 SecondaryNameNode 的定期合并 生成新的fsimage,这样保证了元数据高效备份到磁盘。
DataNode 工作原理
DataNode用于存储文件的表现形式block,还存储了block的长度,校验和,以及时间戳。
DataNode启动后向NameNode注册 当前可用的block信息,以后每隔(N小时)向NameNode上报所有的block信息 。
DataNode同时每隔3秒向NameNode发送心跳,如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用。
HDFS Shell基本命令
1.查看有哪些命令
[root@hadoop1 ~]# hadoop fs
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] [-d] [-t <thread count>] <localsrc> ... <dst>]
[-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] <path> ...]
[-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] [-v] [-x] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
[-head <file>]
[-help [cmd ...]]
[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] [-s <sleep interval>] <file>]
2.创建文件夹
# 创建文件夹
[root@hadoop1 ~]# hadoop fs -mkdir /hadluo
# 列出文件
[root@hadoop1 ~]# hadoop fs -ls /hadluo
#查看文件
[root@hadoop1 ~]# hadoop fs -cat /hadluo/b.txt
# 跟linux一样 ,还有 rm -r,tail ,cp,mv,du
3.上传
#从本地剪切上传到hdfs
[root@hadoop1 local]# hadoop fs -moveFromLocal /usr/local/b.txt /hadluo
#从本地复制上传到hdfs
[root@hadoop1 local]# hadoop fs -put /usr/local/b.txt /hadluo
#追加一个文件到已经存在的文件末尾
[root@hadoop1 local]# hadoop fs -appendToFile /usr/local/a.txt /hadluo/b.txt
4.下载
# 拷贝到本地
[root@hadoop1 local]# hadoop fs -get /hadluo/b.txt ./
HDFS Java Api
引入 maven:
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
java代码:
public class HDFS {
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
Configuration configuration = new Configuration();
// 设置副本数
configuration.set("dfs.replication", "2");
// 创建客户端
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:8020"), configuration, "root");
// 创建文件夹
fs.mkdirs(new Path("/abc"));
// 上传
fs.copyFromLocalFile(new Path("C:\\Users\\youh\\Desktop\\斗店爬虫v0.0.1\\geckodriver.exe"), new Path("/abc"));
// 下载
fs.copyToLocalFile(new Path("/abc/geckodriver.exe"), new Path("C:\\Users\\youh\\Desktop\\斗店爬虫v0.0.1"));
// 删除 参数2:是否递归删除
fs.delete(new Path("/abc"), false);
// 文件移动 并且 改名
fs.rename(new Path("/abc/geckodriver.exe"), new Path("/klk/geckodriver22.exe"));
// 递归遍历文件夹
RemoteIterator<LocatedFileStatus> it = fs.listFiles(new Path("/abc"), false);
while (it.hasNext()) {
LocatedFileStatus file = it.next();
System.out.println("文件名:" + file.getPath().getName());
System.out.println("块存储信息:" + file.getBlockLocations());
System.out.println("副本数:" + file.getReplication());
}
// 判断是否是文件
for (FileStatus status : fs.listStatus(new Path("/abc"))) {
System.out.println("是否是文件: " + status.isFile());
}
// 关闭客户端
fs.close();
}
}
总结
HDFS是存储基石 , MapReduce负责计算(后面会介绍), 今天我们详细讲解了hdfs的存储系统, 就是一个核心思想: 分而治之。