分布式文件系统HDFS
一、分布式文件系统HDFS
1、产生背景
传统的本地文件系统(单机式),在数据量增长过快、数据备份、数据安全性、操作使用便捷性上存在严重不足。
2、特点介绍
高容错和高可用性,硬件错误是常态而不是异常
HDFS设计为运行在普通硬件上,所以硬件故障是很正常的。HDFS提供文件存储副本策略,可以实现错误自检并快速自动恢复。个别硬件的损坏不影响整体数据完整性和计算任务的正常执行。
流式数据访问
HDFS主要采用流式数据读取,做批量处理而不是用户交互处理,因此HDFS更关注数据访问的高吞吐量。
弹性存储,支持大规模数据集
HDFS支持大文件存储,典型的文件在GB甚至TB级别,可以支持数以千万计的大规模数据集。根据业务需要灵活的增加或者缩减存储节点。弹性存储的最大挑战是减小在修改存储节点时的数据震荡问题。
简单一致性模型
HDFS文件实行一次性写、多次读的访问模式。设计为文件一经创建、写入和关闭之后就不需要再更改了,这种设计和假定简化了数据一致性问题,使高吞吐量成为可能。
移动计算而非移动数据
由于HDFS支持大文件存储,对于大文件来说,移动计算比移动数据的代价要低。这样也可以减少网络的拥塞和提高系统的吞吐量。
协议和接口多样性
为上层应用提供了多种接口,Http RestFul接口、NFS接口、Ftp接口等等POSIX标准协议,另外通常会有自己的专用接口。
多样的数据管理功能
对于数据压缩、数据加密、数据缓存和存储配额等提供了多样的管理功能。
3、应用场景
各大电信运营商
中大型互联网公司,如BAT、京东、乐视、美团等
金融银行保险类公司
各大云平台底层存储平台
其他本地系统无法承载存储能力的应用
二、HDFS架构设计
1、HDFS是什么
HDFS(Hadoop Distributed File System )Hadoop分布式文件系统。
由论文为GFS(Google File System)Google 文件系统启发,是Google GFS的开源Java实现。
2、HDFS组件角色
2.1 NameNode(简称NN)
HDFS元数据管理者,管理NameSpace(文件系统命名空间),记录文件是如何分割成数据块以及他们分别存储在集群中的哪些数据节点上。
NameSpace或其本身属性的任何更改都由NameNode记录,维护整个文件系统的文件和目录。
2.2 DataNode(简称DN)
DataNode是文件系统的工作节点。根据客户端或者NameNode发送的管理指令,负责HDFS的数据块的读写和检索操作。
通过心跳机制定期向NameNode发送他们的存储块的列表。
2.3 Client
客户端Client代表用户与NameNode或者DataNode交互来访问整个文件系统的对象。
开发人员面向Client API来编程实现,对NameNode、DataNode来说透明无感。
3、HDFS架构设计
3.1基本架构
HDFS是一个主从式(Master/Slave)的体系结构。HDFS集群中有一个NameNode和一些DataNodes,
NameNode管理文件的元数据,DataNode存储实际的数据。从用户的角度看,就像操作传统的文件系统一样,可以通过目录路径对文件执行创建、读取、删除操作。客户端联系NameNode来获取元数据信息,而真正的文件I/O是直接和DataNode进行交互的。
3.2读文件流程
22
详细步骤:
第一步:Client向NameNode发送数据请求后,寻找数据对应的数据块的位置信息。
第二步:NameNode返回文件对应的数据块元数据信息,如所属机器、数据块的block_id、数据块的先后顺序等。
第三步:由Client与DataNode直接通信,读取各个block数据块的信息。过程为并行读取,由客户端合并数据。
3.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数据块后,如果还有则反复进行第一步和第二步。
第三步:
待所有的数据块block均写完后,Client接收到全部写完的ack答复,告诉NameNode数据已写完,Client关闭socket流。
DataNode也会向NameNode报告新增block数据块的信息。
三、HDFS高可用性措施
1、冗余备份
数据存储在这些HDFS中的节点上,为了防止因为某个节点宕机而导致数据丢失,HDFS对数据进行冗余备份,至于具体冗余多少个副本,在dfs.replication中配置。
2、跨机架副本存放
仅仅对数据进行冗余备份还不够,假设所有的备份都在一个节点上,那么该节点宕机后,数据一样会丢失,因此HDFS要有一个好的副本存放策略,该策略还在开发中。目前使用的是,以dfs.replication=3为例,在同一机架的两个节点上各备份一个副本,然后在另一个机架的某个节点上再放一个副本。前者防止该机架的某个节点宕机,后者防止某个机架宕机。
3、心跳检测
DataNode节点定时向NameNode节点发送心跳包,以确保DataNode没有宕机。如果宕机,会采取相应措施,比如数据副本的备份。
4、数据完整性检测
NameNode在创建HDFS文件时,会计算每个数据的校验和并储存起来。当客户端从DataNode获取数据时,他会将获取的数据的校验和与之前储存的校验和进行对比。
5、安全模式
HDFS启动时,会进入安全模式,此时不允许写操作。这时,NameNode会收到所有DataNode节点的数据块报告,在确认安全之后,系统自动退出安全模式。
6、核心文件备份
HDFS的核心文件是映像文件和事务日志,如果这些文件损坏,将会导致HDFS不可用。系统支持对这两个文件的备份,以确保NameNode宕机后的恢复。
7、空间回收
从HDFS中删除的文件会首先被放入到/trash中,/trash文件夹中的内容是被删除文件最后的副本,该文件夹会被定时清空。该文件夹中不存在的文件就彻底不存在了。
四、HDFS shell应用
1、HDFS Shell命令分类
2、hdfs dfs常用命令
hdfs dfs与hadoop fs对等,只是一个先后推荐使用的区别,目前推荐使用hdfs dfs。
hdfs提供了类似shell命令的方式,可以像操作本地系统文件一样来操作hdfs文件,常用的命令如下:
2.1查看所有命令
查看hdfs dfs下的所有可用命令:
2.2查看某目录下文件列表
查看hdfs根目录下的文件列表:
hdfs dfs -ls /
2.3查看某文本文件的内容
查看hdfs的某个文本文件:
hdfs dfs -cat /tmp/index.html
2.4创建目录
在hdfs中创建/tmp/tianliangedu目录:
hdfs dfs –mkdir /tmp/tianliangedu
2.5删除目录
删除/tmp/tianliangedu目录:
hdfs dfs –rm -r /tmp/tianliangedu
2.6从hdfs下载文件
将hdfs中的/tmp/index.html文件下载到本地文件的当前路径下:
hdfs dfs -copyToLocal /tmp/index.html .
2.7从本地上传文件到hdfs
从本地当前目录下,上传之前的index.html文件到hdfs的/tmp/tianliangedu目录中:
hdfs dfs -copyFromLocal index.html /tmp/tianliangedu
2.8查看压缩的文件内容
查看压缩文本文件的格式:
hdfs dfs -text /tmp/tianliangedu/index.html.gz | more
2.9查看文件大小
查看hdfs中目录/tmp/tianliangedu中文件占用磁盘大小:
hdfs dfs -du -h /tmp/tianliangedu
2.10创建文件
在/tmp/tianliangedu目录中创建空文件HelloWorld.txt:
hdfs dfs -touchz /tmp/tianliangedu/HelloWorld.txt
2.11查看命令帮助信息
查看hdfs dfs中某个命令的用法,比如:cp:
hdfs dfs -usage cp
3、hdfs dfsadmin
hdfs dfsadmin是集群管理员的常用命令,用来对HDFS集群的整体运行进行管理和运维。常用的管理命令如下:
3.1查看可用的管理命令
查看管理命令的帮助信息:
hdfs dfsadmin -help
3.2报告文件系统信息
报告文件系统的基本信息和统计信息
hdfs dfsadmin -report
3.3设置目录配额
设置目录配额,目录配额是一个长整型数,限定指定目录下的名字个数:
hdfs dfsadmin -setQuota ……
比如:hdfs dfsadmin -setQuota 10 /tmp/tianliangedu
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的具体使用。
1、操作需求
// hdfs dfs -cat /tmp/tianliangedu/input.txt
从hdfs文件/tmp/tianliangedu/input.txt中读取其文本内容,并打印出来。
2、步骤分解
3、操作实现
3.1资源准备
本地新建文件index.txt,写入“HelloWorld Hadoop”内容,上传至HDFS文件系统的/tmp/tianliangedu/input.txt文件中。
3.2 Maven环境搭建
Maven开发环境搭建,用Eclipse IDE工具,创建一个新的Maven项目。
3.3 Pom配置依赖
修改新建项目的pom.xml的配置文件,将Hadoop的依赖加入进去:
配置依赖jar包的坐标,即描述我是谁。
指定依赖的仓库
具体需要哪些相关依赖
配置打包插件
具体配置参考如下:
4.0.0
com.tianliangedu.course
TlHadoopCore
0.0.1-SNAPSHOT
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 文件操作工具类,从任意的hdfs filepath中读取文本内容
*/
public class HdfsFileOperatorUtil {
//添加日志输出能力
Logger logger = Logger.getLogger(HdfsFileOperatorUtil.class);
// 加载配置文件到内存对象
static Configuration hadoopConf = new Configuration();
/** 从HDFS上读取文件 /
public static String readFromFile(String srcFile) throws Exception {
//文件路径的空判断
if (srcFile == null || srcFile.trim().length() == 0) {
throw new Exception(“所要读取的源文件” + srcFile + “,不存在,请检查!”);
}
//将文件内容转换成字节数组
byte[] byteArray = readFromFileToByteArray(srcFile);
if (byteArray == null || byteArray.length == 0) {
return null;
}
//将utf-8编码的字节数组通过utf-8再进行解码
return new String(byteArray, “utf-8”);
}
/*
将指定的文件路径从hdfs读取并转换为byte array.
@param srcFile
@return
*/
public static byte[] readFromFileToByteArray(String srcFile)
throws Exception {
if (srcFile == null || srcFile.trim().length() == 0) {
throw new Exception(“所要读取的源文件” + srcFile + “,不存在,请检查!”);
}
//获取hadoopConf对应的hdfs集群的对象引用
FileSystem fs = FileSystem.get(hadoopConf);
//将给定的srcFile构建成一个hdfs的路径对象Path
Path hdfsPath=new Path(srcFile);
FSDataInputStream hdfsInStream = fs.open(hdfsPath);
//初始化一块字节数组缓冲区,大小为65536。缓存每次从流中读取出来的字节数组
byte[] byteArray = new byte[65536];
//初始化字节数输出流, 存放最后的所有字节数组
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 实际读过来多少
int readLen = 0;
//只要还有流数据能读出来,就一直读下去
while ((readLen = hdfsInStream.read(byteArray)) > 0) {
bos.write(byteArray);
byteArray = new byte[65536];
}
//读取完成,将hdfs输入流关闭
hdfsInStream.close();
//将之前写到字节输出流中的字节,转换成一个整体的字节数组
byte[] resultByteArray=bos.toByteArray();
bos.close();
return resultByteArray;
}
public static void main(String[] args) throws Exception {
//定义要读入的hdfs的文件路径
String hdfsFilePath = “/tmp/tianliangedu/input.txt”;
//将文件从hdfs读取下来,转化成字符串
String result = readFromFile(hdfsFilePath);
//根据题意,将字符串通过命令行输出
System.out.println(result);
}
}
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
查看验证效果