分布式文件系统HDFS

分布式文件系统HDFS(按块存储,默认一个block块128M)
一、分布式文件系统HDFS
1、产生背景
传统的本地文件系统(单机式),在数据量过快、数据备份、数据安全性、操作使用便捷性上存在严重不足。

2、特点介绍
2.1 高容错和高可用性,硬件错误是常态而不是异常
HDFS设计为运行在普通硬件上,所以硬件故障是很正常的。HDFS提供文本存储副本策略,可以实现错误自检并快速自动回复。个别硬件的损坏不影响整体数据完整性和计算任务的正常执行。
机架:是一个局部的局域网。副本会使用到。会先在其他的机架保存一份,会在本机架保存一份。如果本机架丢失,会优先就近查找。
2.2流式数据访问
HDFS主要采用流式数据读取,做批量处理而不是用户交互处理,因此HDFS更关注数据访问的高吞吐量。(吞吐量是指对网络、设备、端口、虚电路或其他设施,单位时间内成功地传送数据的数量(以比特、字节、分组等测量)。)
2.3弹性存储,支持大规模数据集(存储小文件,inode(存放数据描述,文件与属性等,一般删除时会删除inode),block(存在真正的数据))
HDFS支持大文件存储,典型的文件在GB甚至TB级别,可以支持数以千万计的大规模数据集。根据业务的需要灵活的增加或者缩减存储节点。弹性存储的最大挑战是减少在修改存储节点时的数据震荡问题。
2.4简单一致性模型(有删除,创建,但是没有删除,HDFS只是用来存储)
HDFS文件实行一次性写、多次读的访问模式,设计为文件一经创建、写入和关闭后就不需要再更改了,这种设计和假定简化了数据一致性的问题,提高吞吐量成为了可能,但是现在可以通过设置一些参数进行追加。
2.5移动计算而非移动数据
由于HDFS支持大文件的存储,对于大文件来说,移动计算比移动数据的代价要低。这样可以减少网络的拥塞和提高系统的吞吐量。
2.6协议和接口多样性(Http协议、https协议、ftp协议、file://)
为上层应用提供了多种接口,HttpRestful接口、NFS接口、Ftp接口等等POSIX标准协议。
2.7多样的数据管理功能
对于数据压缩、数据加密、数据缓存和存储配置等提供了多样的管理功能。

3.应用场景
3.1各大应用商
3.2中大型互联网公司,如BAT,京东、乐视等。
3.3金融银行保险类公司
3.4各大云平台底层存储平台
3.5其他本地系统无法承载存储能力的应用

二、HDFS架构设计
jps是 https://blog.csdn.net/u013250071/article/details/80496623
是有关java的命令,集群中,是绿色安装,所以jps没有回显。
杀掉一个进程:kill -9 进程id
1、HDSF是什么
HDFS(Hadoop Distributed File System)是Hadoop分布式文件系统。
2、HDFS组件角色
2.1NameNode
2.1.1HDFS元数据管理者,管理NameNode(文件系统命名空间),记录文件是如何分割成数据块以及他们分别存储在集群在哪些数据节点上。
2.1.2NameSpace或其本身属性的任何更改都由NameNode记录,维护整个文件系统的文件与目录。
2.2DataNode
2.2.1DataNode是文件系统的工作节点,根据客户端或者NameNode发送的管理指令,负责HDFS的数据块的读写和检索操作。
2.2.2通过心跳机制定期向NameNode发送他们的存储块的列表。
2.3Client
2.3.1客户端Client代表用户与NameNode或者DataNode交互来访问整个文件系统的对象
2.3.2开发人员面向ClientAPI来编程实现,对NameNode、DataNode来说透明无感。

3、HDFS架构设计
3.1基本架构
分布式文件系统HDFS_第1张图片
HDFS是一个主从式(Master/Slave)的体系结构。HDFS集群中有一个NameNode和一些DataNodes,NameNode管理文件的元数据,DataNode存储实际的数据。从用户的角度看,就像操作传统的文件系统一样,可以通过目录路径对文件执行创建、读取、删除操作。客户端联系NameNode来获取元数据信息,而真正的文件I/O是直接和DataNode进行交互的。
3.2读文件流程(I/O流过程)
如果不满128M(block块的默认大小)则该使用多少空间就使用多少空间

分布式文件系统HDFS_第2张图片

详细步骤:
	第一步:Client向NameNode发送数据请求后,NameNode会寻找与之相对应的数据块的位置信息。
	第二步:NameNode返回文件对应的数据块元数据信息,如所属的机器,数据块的block_id、数据块的先后顺序等。
	第三步:由Client与DataNode直接通信,读取各个block数据块的信息。过程为并行读取,由客户端合并数据。

3.3写文件流程
分布式文件系统HDFS_第3张图片
详细步骤:
第一步:
Client向NameNode发送写数据请求后,寻找可以写入的数据块block信息的机器位置。
若文件过大,写入可能会分成很多block数据块,实质上是通过一个block一个block的申请。
若副本为3,则每次请求后返回一个block的对应的3个副本的block的存放位置
第二步:
Client获取到对应的block数据块所处的DataNode节点位置后,Client开始写操作。
Client先写入第一个DataNode,以数据包package的方式逐个发送和接收。如64k大小的package包大小来发送与接收。
存在多个副本时,package包的写入是依次进行的。写入到第一个DataNode后,第一个向第二个DataNode传输。第二个写完后,第二个向第三个DataNode传输package。以此类推。
写完一个block数据块后,如果还有则反复进行第一步和第二步。
第三步:ack:https://blog.csdn.net/wjtxt/article/details/6606022
待所有的数据块block均写完后,Client接收到全部写完的ack答复,告诉NameNode数据已写完,Client关闭socket流。(可能会进行机器间的通信,所以是socket连接)
DataNode也会向NameNode报告新增block数据块的信息。
写要不都成功,要不就失败。失败之后,会将已经写的副本删掉(中断情况)
三、HDFS高可靠性措施
3.1冗余备份
数据存储在这些HDFS中的节点上,为了防止因为某个节点宕机而导致数据丢失,HDFS对数据进行冗余备份,至于具体冗余多少个副本,在dfs.replication中配置。
3.2跨机架副本存放
仅仅对数据进行冗余备份还不够,假设所有的备份在一个节点上,那么该节点宕机后,数据一样会丢失,因此HDFS要有一个好的副本存放策略,该策略还在开发中,目前使用的是以dfs.replication=3为例,在同一机架的两个节点上个备份一个副本,然后在另一个机架的某个节点上再放一个副本,前者防止该机架的某个节点宕机,后者防止某个机架宕机。
3.3心跳检测
DataNode节点定时向NameNode节点发送心跳包,以确保DataNode没有宕机,如果宕机,会采取相应措施,比如数据副本的备份。
3.4数据完整性检测
NameNode在创建HDFS文件时,会计算每个数据的校验和并储存起来,当客户端从DataNode获取数据时,他会将获取的数据校验和与之前存储的校验和进行对比。
3.5安全模式
HDFS启动时,会进入安全模式,此模式不允许写操作。这时,NameNode会收到所有DataNode节点的数据块报告,在确认安全之后,系统自动退出安全模式。
3.6核心文件备份
HDFS核心文件是映像文件和事务日志,如果这些文件损坏,将会导致HDFS不可用,系统支持对这两个文件的备份,以确保NameNode宕机后的恢复。
3.7空间回收
从HDFS中删除的文件会首先被放入到/trash中,/trash文件夹中的内容是被删除文件最后的副本,该文件夹会被定时清空。该文件夹中不存在的文件就彻底不存在了。
分布式文件系统HDFS_第4张图片

四、HDFS Shell应用
4.1HDFS Sheel命令

分布式文件系统HDFS_第5张图片

4.2hdfs dfs常用命令
hdfs dfs 与 hadoop fs 对等,只是一个先后推荐使用的区别,目前推荐使用 hdfs dfs。 hdfs 提供了类似 shell 命令的方式,可以像操作本地系统文件一样来操作 hdfs 文件,常用的命 令如下:
4.2.1查看hdfs dfs下所有所有命令
hdfs dfs
4.2.2查看hdfs 根目录下文件列表
hdfs dfs -ls
4.2.3查看hdfs的某个文本文件的内容
hdfs dfs -cat/tmp/index.html
4.2.4在hdfs 中创建/tmp/jiqun目录
hdfs dfs -mkdir /tmp/jiqun
4.2.5删除/tmp/jiqun目录
hdfs dfs -rm -r /tmp/jiqun(-rmr也可以)
4.2.6从hdfs下载文件(将hdfs中的/tmp/index.html文件下载到本地文件的当前路径)
hdfs dfs -copyToLocal /tmp/jiqun
4.2.7从本地上传文件到hdfs(从本地当前目录,上传之前的index.html文件到hdfs的/tmp/jiqun目录中)
hdfs dfs -copyFromLocal index.html /tmp/jiqun
4.2.8查看压缩文件的格式(将文件压缩为gzip格式:gzip index.html)
hdfs dfs -text /tmp/jiqun/index.html.gz | more
4.2.9查看文件大小(Linux使用df-h)
查看磁盘使用情况hdfs dfs -df -h
查看hdf目录/tmp/jiqun中文件占用磁盘的大小
hdfs dfs -du -h /tmp/jiqun
4.2.10在/tmp/jiqun目录中创建空文件HelloWorld.txt
hdfs dfs -touchz /tmp/jiqun/HelloWorld.txt
4.2.11查看hdfs dfs 中某个命令的用法,例如cp
hdfs dfs -usage cp
4.3hdfs dfsadmin
hdfs dfsadmin 是集群管理员的常用命令,用来对于HDFS集群的整体运行进行管理和运维。常用的管理命令如下:
4.3.1查看可用的管理命令
hdfs dfsadmin -help
4.3.2报告文件系统的基本信息和统计信息
hdfs dfsadmin -report
4.3.3设置目录配额,目录配额是一个长整型数,限定指定目录下的名字个数
hdfs dfs -setQuota 10 /tmp/jiqun
4.3.4安全模式管理
当集群环境启动时,NameNode会进入一个安全模式,此时不会出现数据块的写操作。NameNode会收到各个DataNode拥有的数据块列表的数据块报告,由此NameNode获得所有的数据块的信息。数据块达到最小副本数时,该数据快就被认为是安全的。
hdfs dfsadmin -safemode get ##返回安全模式是否开启的信息,返回 Safe mode is OFF/OPEN
hdfs dfsadmin -safemode enter ##进入安全模式
hdfs dfsadmin -safemode leave ##强制 NameNode 退出安全模式
hdfs dfsadmin -safemode wait ##等待,一直到安全模式结束

五、HDFS Java API应用
HDFS 提供了两种访问接口,除了上面介绍的Hadoop Shell接口,还另外提供了Java API接口,对HDFS里面的文件进行操作,具体对Block放在哪台DataNode上面,对于开发者来说时透明的,可以像操作本地系统的文件一样,对HDFS进行文件的上传、创建、重命名、删除等操作。
下面以实际操作作为例子来解释API的具体应用:
5.1操作需求
从HDFS文件/tmp/jiqun/input.txt中读取其文本内容,并打印出来
5.2步骤分解
分布式文件系统HDFS_第6张图片

5.3操作实现
	5.3.1资源准备
		本地新建文件夹index.txt,写入“hello world”内容,上传至HDFS文件系统的/tmp/jiqun/input.txt文件中。
	5.3.2Maven环境搭建
		Maven开发环境搭建,用Eclipse IDE工具,创建一个新的Maven项目。
	5.3.3Pom配置依赖
	修改新建项目的pom.xml的配置文件,将Hadoop的依赖加入进去
		配置依赖jar包的坐标,即描述我是谁
		指定依赖的仓库
		具体需要哪些相关依赖
		配置打包依赖
	具体配置参考如下:	    


4.0.0

cn.tl
Hadoop-Core
0.0.1-SNAPSHOT
jar

Hadoop-Core
http://maven.apache.org


	UTF-8




	
		nexus-aliyun
		Nexus aliyun
		http://maven.aliyun.com/nexus/content/groups/public
	


	
	
		org.apache.hadoop
		hadoop-client
		2.7.4
		provided
	


	Hadoop-Core
	
		
			maven-compiler-plugin
			2.3.2
			
				1.7
				1.7
				UTF-8
			

		
		
			maven-assembly-plugin
			
				
					jar-with-dependencies
				
			
			
				
					make-assembly
					package
					
						assembly
					
				
			
		
	

          5.3.4编码实现
          实现步骤:
          	定义读取的HDFS文件路径
          	用HDFS Java API将文本文件转化为字符串形式“
          		先将HDFS文本文件以字节数组形式读取到内存中(因为网络运输使用字节更方便)
          		将字节数组转换成字符串
          	通过控制台将字符串打印出来

	涉及到的Hadoop中类的说明:
		Configuration 
		1)、负责 HDFS 系统的配置文件的加载或者更改配置文件的工具类,将配置文件件加载到 内存中。
		 2)、通过 new Configuration()初始化 Configuration 对象,即将 HDFS 的默认配置文件 加载到内存中,供别的对象使用。 
		  FileSystem
		   1)、对 HDFS 系统的引用,操作 HDFS 的根类。所有 HDFS 文件操作均以此类为源头发起。
		    2)、通过 new FileSystem(new Configuration())初始化针对某集群的 FileSystem 对象。 
		    Path 
		    1)、HDFS 文件的抽象,与 Java IO 流中的 File 对象对等。
		     2)、通过 new Path(hdfsFilePath)得到 Path 对象。 
		    FSDataInputStream 
		    1)、HDFS 系统的文件字节输入流,类比于 Java IO 中的 InputStream 类,实现对 HDFS 文件的读取。
		     2)、FileSystem.open(filePath)可以获取 HDFS 的输入流。
		     FSDataOutputStream 
		     1)、HDFS 系统的文件字节输出流,类比于 Java IO 中的 OutputStream 类,实现对 HDFS 文件的写入。
		      2)、FileSystem.create(filePath)可以获取 HDFS 的输出流。 
		      具体代码:`package cn.tl;

import java.io.ByteArrayOutputStream;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.log4j.Logger;

/**

  • Hdfs 文件操作工具类

*/
public class HdfsFileOperationUtil {
// 添加日志输出
Logger logger = Logger.getLogger(HdfsFileOperationUtil.class);

//加载配置文件到内存对象
static Configuration conf = new Configuration();

//读取hdfs文件 -> 字节数组
public static byte[] readFromFileToByteArray(String src) throws Exception{
	//文件路径判断
	if(src == null || src.trim().length() == 0){
		throw new Exception("读取的源文件"+src+"不能为空!");
	}
	
	//获取hadoop conf对应的hdfs集群对象引用
	FileSystem fs = FileSystem.get(conf);
	//将给定src构建成一个hdfs路径对象path
	Path path = new Path(src);
	FSDataInputStream fsInStream = fs.open(path);
	
	//初始化字节数组
	byte[] arr = new byte[65536];
	//初始化字节输出流
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	
	//实际长度
	int len = -1;
	//读取过程
	while((len = fsInStream.read(arr)) != -1){
		baos.write(arr);
		arr = new byte[65536];
	}
	//关闭流
	fsInStream.close();
	return baos.toByteArray();
} 

//从hdfs读取文件
public static String readFromFile(String src) throws Exception{
	//文件路径判断
	if(src == null || src.trim().length() == 0){
		throw new Exception("读取的源文件"+src+"不能为空!");
	}
	byte[] arr = readFromFileToByteArray(src);
	if(arr == null || arr.length == 0){
		return null;
	}
	return new String(arr,"utf-8");
}

public static void main(String[] args) throws Exception {
	// 定义要读的hdfs的文件路径
	String hdfsPath = "/hupu.txt";
	//将文件从hdfs读取下来,转化成字符串
	String result = readFromFile(hdfsPath);
	//命令行输出
	System.out.println("--- --- Start --- ---");
	System.out.println(result);
	System.out.println("--- --- End --- ---");

}

}
`
Maven打包:右击项目,run as -> maven install 进行打包及上传至本地仓库中,生成 target 目录下的 TlHadoopCore-jar-with-dependencies.jar 文件
将运行包发布上传至Hadoop环境:通过 rz 命令,将生成的 TlHadoopCore-jar-with-dependencies.jar 上传到 hdfs 环境中。
线上测试运行:yarn jar TlHadoopCore-jar-with-dependencies.jar com.tianliangedu.utils.HdfsFileOperatorUtil
查看验证效果:在回显位置会出现文本文件的内容

六、经典问题
6.1HDFS 为何要讲文件分成 block 块存储?
减少底层操作系统的 IO 读取时的寻址时间
方便更高效的流式读取,提高吞吐量
6.2HDFS block 块的默认大小时多少?
dfs.blocksize 为 Hadoop 定义 block 块大小的设置参数,在 hdfs-site.xml 中
版本不一样,默认值不同。Hadoop2.2.x 及以后版本均为 128M
6.3 HDFS block 块的大小是否可以更改?
可以修改
参数修改对以前的文件不起作用,对以后的文件起作用
也可针对上传文件临时修改,指定-D dfs.blocksize 即可
6.4一个 block 块文件是否可以存储多个文件数据?
一个 block 块文件不会跨文件存储
一个 block 块文件最多只会存储一个文件对应的数据
6.5如果一个文件的大小,小于一个 blocksize,那么它实际占用多大空间?
实际文件多大则占多大空间,但是占了一个 block 块的元数据空间大小
小文件越多,Hadoop NameNode 的压力越大。故 Hadoop 的优势在于处理大文件数据,GB、 TB 甚至 PB 等。
6.6HDFS block 越大越好?还是越小越好?
越大则分块越少,则 NameNode 压力将减小,但并行的 IO 和处理能力降低
越小则分块越多,则 NameNode 处理压力越大,但因为寻址时间太久,不利于提高吞吐量
适中即可,一般采用官方的 128M 即可

你可能感兴趣的:(大数据基础,分布式文件系统)