HDFS

HSFS

概念

HDFS(Hadoop DIstributed File System)为分布式文件管理系统中的一种,通过目录树来定位文件,由很多服务器联合起来实现期功能

适用场景:适合一次写入,多次读出,且不支持文件修改。适合用来做数据分析,不适合用来做网盘应用。

优缺点

  • 优点
    • 高容错性
      • 自动保存多个副本
      • 某一个副本丢失后可以自动恢复
    • 适合处理大数据
      • 数据规模:能够处理的数据规模达GB、TB甚至PB
      • 文件规模:能够处理百万规模以上的文件数量
    • 可以构建在廉价机器上,通过多副本机制提高可靠性
  • 缺点
    • 不适合低延时的数据访问
    • 无法高效地对大量小文件进行存储
      • 存储大量小文件会占用NameNode大量内存在存储文件目录和块信息
      • 小文件的寻址时间大于读取时间,违反了HDFS的设计目标
    • 不支持并发写入、文件随机修改
      • 一个文件不允许多线程同时写
      • 仅支持数据追加,不支持文件随机修改

组成架构

  • NameNode:集群文件的管理者
    • 管理HDFS的名称空间
    • 配置副本策略
    • 管理数据块映射信息
    • 处理客户端读写请求
  • DataNode:执行NameNode下达的指令
    • 存储实际的数据块
    • 执行数据块的读写操作
  • Client
    • 文件切分:文件上传HDFS的时候,Client将文件切成一个一个Block,然后进行上传
    • 与NameNode交互,获取文件位置信息
    • 与DataNode交互,读取或写入数据
    • Client提供一些命令来管理HDFS,比如NameNode格式化
    • Client通过一些命令来访问HDFS,比如对HDFS进行增删改查
  • Secondary NameNode:并非NameNode的热备,当NameNode挂掉的时候,并不能马上替换NameNode并提供服务
    • 辅助NameNode,分担工作量,比如定期合并Fsimage和Edits,并推送给NameNode
    • 在紧急情况下,可辅助恢复NameNode

文件快大小(面试重点)

  1. 默认block大小为128M或256M

  2. 为什么block不能太小也不能太大?

    (1)设置太小,会增加寻址时间

    (2)设置太大,传输数据的时间会明显大于寻址时间,导致在处理这块数据的时候会非常慢

  3. block大小主要取决于磁盘传输速度

Shell操作

基本语法

bin/hadoop fs 具体命令	或
bin/hdfs dfs 具体命令
#dfs是fs的实现类

开发重点

API操作

获取文件系统,并进行特殊配置
Configuration configuration = new Configuration();
configuration.set("dfs.replication", "2");//设置副本数
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "root");
文件上传
fs.copyFromLocalFile(new Path("e:/banzhang.txt"), new Path("/banzhang.txt"));
文件下载
fs.copyToLocalFile(false, new Path("/banzhang.txt"), new Path("e:/banhua.txt"), true);//第二个参数为是否递归
删除
fs.delete(new Path("/0508/"), true);
修改文件名
fs.rename(new Path("/banzhang.txt"), new Path("/banhua.txt"));
文件详情查看
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);//第二个参数为是否递归
while (listFiles.hasNext()) {
	LocatedFileStatus fileStatus = listFiles.next();

	//查看文件名称、权限、长度信息
	System.out.println(fileStatus.getPath().getName());//名称
	System.out.println(fileStatus.getPermission());//权限
	System.out.println(fileStatus.getLen());//长度
	
	//获取块信息
	BlockLocation[] blockLocations = fileStatus.getBlockLocations();
	for(BlockLocation blockLocation : blockLocations) {
		String[] hosts = blockLocation.getHosts();
		for (String host : hosts) {
			System.out.println(host);
		}
	}
}
判断是文件还是文件夹
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for (FileStatus fileStatus : listStatus) {
    if (fileStatus.isFile()) {
        //文件
        System.out.println("f:"+fileStatus.getPath().getName());
    }else {
        //文件夹
        System.out.println("d:"+fileStatus.getPath().getName());
    }
}

I/O流操作

文件上传
//创建输入流
FileInputStream fis = new FileInputStream(new File("d:/test2.txt"));
//获取输出流
FSDataOutputStream fos = fs.create(new Path("/测试2.txt"));
//流对拷
IOUtils.copyBytes(fis, fos, conf);
文件下载
//创建输入流
FSDataInputStream fis = fs.open(new Path("/测试2.txt"));
//获取输出流
FileOutputStream fos = new FileOutputStream(new File("d:/test4.txt"));
//流的对拷
IOUtils.copyBytes(fis, fos, configuration);
定位文件读取
public void readFileSeek1() throws IOException, InterruptedException, URISyntaxException{
    //获取文件系统
    Configuration configuration = new Configuration();
    FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "root");
    //获取输入流
    FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
    //创建输出流
    FileOutputStream fos = new FileOutputStream(new File("d:/hadoop-2.7.2.tar.gz.part1"));
    //流的拷贝(只拷贝128M)
    byte[] buf = new byte[1024];
    for(int i =0 ; i < 1024 * 128; i++){
        fis.read(buf);
        fos.write(buf);
    }
    // 5关闭资源
    IOUtils.closeStream(fis);
    IOUtils.closeStream(fos);
    fs.close();
}
//定位文件读取 下载第二块
@Test
public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException{
    //获取文件系统
    Configuration configuration = new Configuration();
    FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "root");
    //打开输入流
    FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
    //设置指定读取的起点
    fis.seek(1024*1024*128);
    //创建输出流
    FileOutputStream fos = new FileOutputStream(new File("d:/hadoop-2.7.2.tar.gz.part2"));
    //流的对拷
    IOUtils.copyBytes(fis, fos, configuration);
    //关闭资源
    IOUtils.closeStream(fis);
    IOUtils.closeStream(fos);
}

HDFS数据流

写数据流

在这里插入图片描述

1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。

2)NameNode返回是否可以上传。

3)客户端请求第一个 Block上传到哪几个DataNode服务器上。

4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。

5)客户端通过FSDataOutputStream模块请求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步)。

网络拓扑-节点距离计算

节点距离:两个节点到达最近的共同祖先的距离总和

在这里插入图片描述

副本节点选择

第一个节点:在Client所处的节点上,如果在集群外随机选择一个

第二个节点:与第一个副本位于相同机架,随机节点

第三个节点:不同机架,随机节点

读数据流程

在这里插入图片描述

1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。

2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。

3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。

4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值