Hadoop(2)初识HDFS

15 篇文章 0 订阅


HDFS(Hadoop Distributed File System)是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上。它所具有的高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特征为海量数据提供了不怕故障的存储,为超大数据集(Large Data Set)的应用处理带来了很多便利。

设计思想

分而治之(安全性):将大文件、大批量文件,分布式的存放在大量服务器上

存储方式

存放数据的单位是块。 2.0以后,块的默认大小:128M

主从架构

1.client 客户端
文件切分,文件上传HDFS的时候,client将文件切分成一个一个的block
与NameNode交互,获取文件的位置信息
与DataNode交互,读取或写入数据
Client提供一些命令来管理HDFS,比如启动或关闭HDFS
Client可以通过一些命令来访问HDFS

2.NameNode
就是master,是一个主管、管理者。管理HDFS的名称空间。主节点仅存放元数据信息(文件大小、位置、块索引)。配置副本策略,处理客户端读写请求,分配client去访问哪个从节点

3.DataNode
就是slave,从节点存放真实文件(实际文件)即实际的数据块,执行数据块的读写操作。
namenode下达命令,datanode执行实际的操作。
client客户端发起读取数据的请求,namenode接到请求后会通过元数据信息得到数据位置,最后由datanode将数据最后输出给client客户端

架构内容

1.数据块:默认128M,datanode通过数据块存储。存放在hadoopdata目录下
2.心跳机制:主从节点间通过心跳机制确定互相之间的关系每3秒发送一次
3.元数据管理
4.负载均衡:存储数据时,由namenode进行分配存在位置
5.副本存放策略:每个块都有两个副本
6.机架感知:datanode机架感知互相联系

优点

1.高容错性:
数据自动保存多个副本(默认有三个)
当某一个副本丢失后,它可以自动恢复,这是HDFS的内部机制

2.适合处理超大文件
可以批处理,是通过移动计算而不是移动数据
处理数据GB、TB、甚至PB级数据百万规模以上的文件数量

3.流式文件访问
一次性写入,像流水一样,一点点流出来的多次读取,保证数据一致性
能保留历史文件,不能任意修改hdfs文件,但是可以追加

4.可创建在廉价机器上
通过多副本提高可靠性,提供了容错和恢复机制

缺点

1.低延迟数据访问
适合低延迟与高吞吐率,就是在某一时间写入大量的数据,但是在低延时的情况下是不行的,比如毫秒级以内读取数据,是很难做到的

2.小文件存取
占用namenode大量内存:存储大量小文件(这里的小文件是指小于HDFS系统的Block大小的文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是有限的

3.并发写入、文件随机修改
一个文件只能有一个写,不允许多个线程同时写
仅支持append(追加),不支持文件的随即修改

相关特性

高容错、可扩展性及可配置性强
跨平台
Shell命令接口
机架感知功能
负载均衡
web界面

设计目标

1.可以检测和快速恢复硬件故障,故障的检测和快速自动恢复是HDFS的一个核心目标

2.流式数据访问
设计成适合进行批量处理,重视数据吞吐量,而不是数据访问的反应速度

3.大规模数据集:支持大文件的存储

4.移动计算代价比移动数据代价低
一个应用请求的计算,离他操作的数据越近就越高效,这在数据达到海量级别的时候更是如此

5.可移植性
HDFS在设计时就考虑到平台的可移植性,这种特性方便了HDFS作为大规模数据应用平台的推广


核心设计

1.心跳机制
2.安全模式
3.副本存放策略
4.负载均衡

心跳机制

1.master中有NameNode和ResourceManager,slave中有DataNode和NodeManager
Master 启动的时候会启动一个 IPC(Inter-Process Comunication,进程间通信) Server 服务,等待 Slave 的链接;
Slave 启动时,会主动链接 Master 的 IPC Server 服务,并且每隔 3 秒链接一次 Master,这个间隔时间是可以调整的,参数为 dfs.heartbeat.interval,这个每隔一段时间去链接一次的机制,我们形象地称为心跳。 Slave 通过心跳汇报自己的信息给 Master, Master 也通过心跳给 Slave 下达命令

2.NameNode 通过心跳得知 DataNode 的状态,ResourceManager 通过心跳得知NodeManager 的状态;
如果 Master 长时间都没有收到 Slave 的心跳,就认为该 Slave 挂掉了

3.死亡时间计算:
NameNode 感知到DataNode掉线死亡的时长计算:
HDFS 默认的超时时间为 10 分钟+30 秒,这里暂且定义超时时间为 timeout。
计算公式为:

timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval

默认的 heartbeat.recheck.interval 大小为 5 分钟,dfs.heartbeat.interval 默认的大小为 3 秒。
需 要 注 意 的 是 hdfs-site.xml 配 置 文 件 中 的 heartbeat.recheck.interval 的 单位 为 毫 秒,dfs.heartbeat.interval 的单位为秒。

  • 如果 heartbeat.recheck.interval 设置为 5000(毫秒), dfs.heartbeat.interval设置为 3(秒,默认),则总的超时时间为 40 秒。
<property>       
    <name>heartbeat.recheck.interval</name>       
    <value>5000</value>
</property>
<property>       
    <name>dfs.heartbeat.interval</name>       
    <value>3</value>
</property>
安全模式

1.safemode 是 NameNode 的一种状态(active/standby/safemode 安全模式)
2.NameNode 进入安全模式的原理:
NameNode 发现集群中的 block 丢失率达到一定比例时(0.1%), NameNode 就会进入安全模式,在安全模式下,不允许客户端进行任何修改文件的操作,包括上传文件、删除文件、重命名等操作,只能查看元数据信息(比如 ls)。这个丢失率是可以手动配置的,默认是在配置文件hdfs-default.xml 中定义了最小的副本率为dfs.safemode.threshold.pct=0.999f 。

在 HDFS 集群正常冷启动时, NameNode 也会在 safemode 状态下维持相当长的一段时间,此时你不需要去理会,等待它自动退出安全模式即可 。
在刚运行命令start-dfs.sh时,50070页面显示的信息:
在这里插入图片描述
3.安全模式常用操作命令:

hdfs dfsadmin -safemode leave    //强制 NameNode 退出安全模式
hdfs dfsadmin -safemode enter     //进入安全模式
hdfs dfsadmin -safemode get         //查看安全模式状态
hdfs dfsadmin -safemode wait         //等待,一直到安全模式结束
副本存放策略

1.副本的作用
数据分块存储和副本的存放,是保证可靠性和高性能的关键 。

2.副本存储方法
将每个文件的数据进行分块存储, 每一个数据块又保存有多个副本, 这些数据块副本分布在不同的机器节点上

3.副本存放策略
1)第一个 block 副本存放在 client 所在的 node 中(如果 client 不在集群范围内,则第一个 node是随机选取的,系统会尝试不选择那些太满或者太忙的 node);
2)第二个副本放置在与第一个 node相同的机架的不同 node 中(近乎随机选择,系统会尝试不选择那些太满或者太忙的 node);
3)第三个副本和放在与第二个不同的机架上,随机放在不同的 node 中。
4)其他副本随即存放

4.修改副本数(将副本数修改为1)
第一种方式
修改集群文件 hdfs-site.xml

<property>           //修改项开始       
<name>dfs.replication</name>        
<value>1</value>
</property>          //修改项结束

第二种方式
命令设置

hadoop fs  -setrep  -R  1  /
负载均衡

1.数据不平衡原因
机器与机器之间磁盘利用率不平衡是 HDFS 集群非常容易出现的情况
情况一:在 DataNode 节点出现故障
情况二:在现有的集群上增添新的 DataNode 的时候

2.HDFS数据自动平衡方法
影响Balancer的几个参数:

  • threshold
    默认设置:10,参数取值范围:0-100
    参数含义:判断集群是否平衡的阈值。理论上,该参数设置的越小,整个集群就越平衡。

  • dfs.balance.bandwidthPerSec
    默认设置:1048576(1M/S)
    参数含义:Balancer运行时允许占用的带宽

3.HDFS数据自动平衡方法
命令:
启动数据均衡,默认阈值为 10%

sbin/start-balancer.sh

启动数据均衡,阈值 5%

sbin/start-balancer.sh –threshold 5         

停止数据均衡

sbin/stop-balancer.sh                    

自动进行均衡非常慢, 一天能移动的数据量在 10G-10T 的级别,很难满足超大集群的需求。
原因: HDFS 集群默认不允许 balance 操作占用很大的网络带宽,这个带宽是可以调整的。

4.HDFS数据自动平衡方法
调整带宽:
(1)命令

hdfs dfsadmin -setBalanacerBandwidth 10485760

该数值的单位是字节,上面的配置是 10M/s,默认是 1M/s
(2) 在hdfs-site.xml 中设置:

<property>       
<name>dfs.balance.bandwidthPerSec</name>
<value>10485760</value>
</property>

HDFS READ

1.客户端向NN发出请求,与NN发生交互
调用FileSystem对象的open方法,其实获取的是一个DistributedFileSystem的实例

2.NN把文件的列表信息发送给client,列表信息即文件的位置索引
DistributedFileSystem通过RPC(远程过程调用)获得文件的第一批block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面

3.client根据列表信息去DN上读取block块信息(客户端会找离它比较近的去读,就近原则)
前两步会返回一个FSDataInputStream对象,该对象会被封装成 DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream就会找出离客户端最近的datanode并连接datanode
数据从datanode源源不断的流向客户端

4.一直读,直到所有块读完
如果第一个block块的数据读完了,就会关闭指向第一个block块的datanode连接,接着读取下一个block块
如果只有第一行有信息,也会把整个块读完

5.关闭读操作
如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的block块都读完,这时就会关闭掉所有的流

比如要读一个文件a.txt,300M,那么它会占用3个块,默认保存3个副本,所以存在三个DN上
在这里插入图片描述


HDFS WRITE

1.客户端根据文件的大小,为它分配需要的block数,然后向NN发出写的请求,看看文件是否存在,如果不存在就创建
-客户端通过调用 DistributedFileSystem 的create方法,创建一个新的文件。
-DistributedFileSystem 通过 RPC(远程过程调用)调用 NameNode,去创建一个没有blocks关联的新文件。创建前,NameNode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,NameNode 就会记录下新文件,否则就会抛出IO异常

2.NN为文件分配每个块写的位置,然后向client返回文件list,即元数据信息给client
-第一步结束后会返回 FSDataOutputStream 的对象,和读文件的时候相似,FSDataOutputStream 被封装成 DFSOutputStream,DFSOutputStream 可以协调 NameNode和 DataNode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列 data queue。

3.client根据文件list在相应的DN上写,每写完一个DN都向client返回一个ack信息。
DFSOutputStream 还有一个队列叫 ack queue,也是由 packet 组成,等待DataNode的收到响应,当pipeline中的所有DataNode都表示已经收到的时候,这时akc queue才会把对应的packet包移除掉。
-如果有DN坏了,NN会重新分配,client再重新写

4.客户端写完最后一块后,client关闭数据流
-客户端完成写数据后,调用close方法关闭写入流。
-DataStreamer 把剩余的包都刷到 pipeline 里,然后等待 ack 信息,收到最后一个 ack 后,通知 DataNode 把文件标示为已完成。

5.当第一块block完成时,它所在的那个节点的后台会启动一个进程进行复制,分别把副本写到其它DN上(管道复制)
-DataStreamer 会去处理接受 data queue,它先问询 NameNode 这个新的 block 最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个 pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 中,第一个 DataNode又把 packet 输出到第二个 DataNode 中,以此类推。

比如要写一个文件a.txt,300M,那么它会占用3个块,默认保存3个副本
在这里插入图片描述


HDFS操作

1.HDFS的Shell操作
2.通过JAVA API操作

1 常用命令

hdfs的ftp的上传目录

[yao@master ~]$ hadoop fs -ls hdfs://master:9000/
  • 查看
hadoop fs -ls /
hadoop fs -lsr /		//把每一层的目录都显示出来

[yao@master hadoop-2.7.7]$ hadoop fs -ls -R /tmp

在这里插入图片描述

  • 上传:
[yao@master ~]$ hadoop fs -copyFromLocal hadoop-2.7.7.tar.gz /0315

在这里插入图片描述

[yao@master hadoop-2.7.7]$ hadoop fs -put README.txt /0315

在这里插入图片描述

  • 下载:
hadoop fs -get

[yao@master hadoop-2.7.7]$ hadoop fs -copyToLocal /0315/README.txt /home/yao/

在这里插入图片描述

  • 查看文件:
[yao@master ~]$ hadoop fs -cat /0315/README.txt
  • 创建/删除目录:
hadoop fs -rm(r)
hadoop fs -mkdir /test

在这里插入图片描述

2 HDFS的Java API操作

hdfs 在生产应用中主要是客户端的开发,其核心步骤是从hdfs提供的api中构造一个HDFS的访问客户端对象,然后通过客户端对象操作(增加删除修改)HDFS上传的

  • 利用eclipse查看hdfs集群的文件信息
    下载一个eclipse开发工具
    解压eclipse

  • 获取hdfs的配置信息

Configuration conf=new Configuration();
  • 获取客户端实例
    从HDFS提供的API中创建一个HDFS的对象,通过这个对象来操作文件系统
FileSystem fs=FileSystem.get(conf);

在这里插入图片描述
注意,都要选org.apache.hadoop.fs相关
在这里插入图片描述

  • 检测,打印出访问的uri地址
System.out.println(fSystem.getUri());
  • 通过配置来获取fs对象
conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");

如果我们没有给conf设置文件系统,那么FileSystem默认获取的是本地文件系统的一个实例
若是我们设置了“fs.defaultFS”参数,这表示获取的是该URI的文件系统的实例,就是我们需要的HDFS集群的一个fs对象
如果在win配置了master,这里可以直接写成:

FileSystem fs=FileSystem.get(new URI("hdfs://master:9000"),conf,"yao");
  • 直接获取FileSystem对象
System.setProperty("HADOOP_USER_NAME", "yao");

这里不需要配置“fs.defaultFS”参数,直接传入URI和用户身份,最后一个参数是安装hadoop集群的用户,这里的是“yao”

  • 创建实例对象
FileSystem fs=FileSystem.get(conf);
  • java代码
package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class HdfsDemo {

	public static void main(String[] args) throws IOException {
		//创建配置信息,conf不给任何参数的时候,默认的时本地的文件系统
		//通过给两个参数,name为fs.defaultFS,现在访问的就是hdfs文件系统
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		//用yao用户访问hdfs文件系统
		System.setProperty("HADOOP_USER_NAME", "yao");
		//创建一个hdfs的客户端实例对象,需要把集群配置作为这个对象的参数
		FileSystem fs=FileSystem.get(conf);
		//检测
		System.out.println(fSystem.getUri());
  • 增删改查
    1.创建目录
    在这里插入图片描述
    在这里插入图片描述
package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;


public class Mkdir {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "yao");
		FileSystem fs=FileSystem.get(conf);
		
		fs.mkdirs(new Path("/0318"));
		fs.close();
	}

}

2.上传文件
在这里插入图片描述
在这里插入图片描述

package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class Put {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "yao");
		FileSystem fs=FileSystem.get(conf);
		
		Path src=new Path("E:/study2019/software/a.txt");
		Path dst=new Path("/0317");
		fs.copyFromLocalFile(src, dst);
		
		fs.close();
	}

}

//默认不删除本地源文件,不覆盖HDFS同名文件

3.下载文件
在这里插入图片描述

package org.yao.hdfs;

import java.io.IOException;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class Get {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "hdfs://192.168.16.199:9000");
		FileSystem fs=FileSystem.get(conf);
		
		Path src=new Path("/0317/README.txt");
		Path dst=new Path("E:/study2019/software");
		fs.copyToLocalFile(false, src, dst, true);
		
		fs.close();
	}

}

4.重命名文件或者文件夹
在这里插入图片描述
在这里插入图片描述

package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class Rename {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "yao");
		FileSystem fs=FileSystem.get(conf);
		
		fs.rename(new Path("/0317/a.txt"), new Path("/0317/s.txt"));
		fs.rename(new Path("/0318"), new Path("/0317_2"));
		
		fs.close();
	}

}

5.删除文件或者文件夹
在这里插入图片描述
*说明这是一个过时的命令,但是也可以执行
在这里插入图片描述
在这里插入图片描述

package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class Delete {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "yao");
		FileSystem fs=FileSystem.get(conf);
		
		fs.delete(new Path("/0317_2"), false);
		fs.delete(new Path("/0317/README.txt"), true);
		
		fs.close();
	}

}

6.查看
1)查看/目录下的目录
在这里插入图片描述
2)查看/test目录下的目录和文件
在这里插入图片描述
在这里插入图片描述

package org.yao.hdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class List {
	public static void main(String[] args) throws IOException {
		Configuration conf=new Configuration();
		conf.set("fs.defaultFS", "hdfs://192.168.16.199:9000");
		System.setProperty("HADOOP_USER_NAME", "yao");
		FileSystem fs=FileSystem.get(conf);
		
		FileStatus[] listStatus = fs.listStatus(new Path("/test"));
        String flag="";
        for(FileStatus status:listStatus){
            if(status.isDirectory()){
                flag="Directory";
            }else {
                flag="File";
            }
            System.out.println(flag+":"+status.getPath().getName());
        }
        fs.close();
	}

}

7.关闭

fs.close();

fs相当于一个资源,如果不关闭,它就一直在运行,是浪费资源

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值