目录
1.2.1 常用命令 hdfs dfs -help/-ls/-put/-get/-cat/-rm/-cp/-mkdir/-touchz/-appendToFile
一. HDFS概述
-
HDFS是Hadoop中的一个存储子模块
-
HDFS (全称Hadoop Distributed File System),即hadoop的分布式文件系统
-
File System文件系统:操作系统中负责管理和存储文件信息的软件;具体地说,它负责为用户创建文件,存入、读出、修改、转储、删除文件等
-
比如windows下的文件系统
-
当数据集大小超出一台计算机的存储能力时,就有必要将它拆分成若干部分,然后分散到不同的计算机中存储。管理网络中跨多台计算机存储的文件系统称之为分布式文件系统(distributed filesystem)
-
1.1 HDFS特点
-
HDFS是Hadoop中的分布式文件系统
-
HDFS高容错、可扩展
-
HDFS适合存储大文件,不适合存储小文件
-
不适合处理低延时的数据方问
1.1.1 优点:
-
1、适合存储大文件,能用来存储管理PB级的数据;不适合存储小文件
-
2、存储非结构化数据 (https://blog.csdn.net/haishu_zheng/article/details/81844178)
-
3、流式的访问数据,一次写入、多次读写
-
4、运行于廉价的商用机器集群上,成本低
-
5、高容错:故障时能继续运行且不让用户察觉到明显的中断
-
6、容量可扩展
-
可扩展
1.2.2 局限性
-
1、不适合处理低延迟数据访问
-
DFS是为了处理大型数据集分析任务的,主要是为达到高的数据吞吐量而设计的
-
对于低延时的访问需求,HBase是更好的选择
-
-
2、无法高效存储大量的小文件
-
小文件会给Hadoop的扩展性和性能带来严重问题(How?)
-
利用SequenceFile、MapFile等方式归档小文件(How?)
-
-
3、不支持多用户写入及任意修改文件
-
文件有一个写入者,只能执行追加操作
-
不支持多个用户对同一文件的写操作,以及在文件任意位置进行修改,但支持追加
-
1.2、HDFS命令
HDFS命令与linux 命令的很相似性,前面多了 hadoop fs
HDFS命令有两种风格:hadoop fs开头的 hdfs dfs开头的,两种命令均可使用,效果相同
输入hadoop fs 或hdfs dfs,回车,查看所有的HDFS命令
许多命令与linux命令有很大的相似性,学会举一反三
有用的help,如查看ls命令的使用说明:hadoop fs -help ls
1.2.1 常用命令 hdfs dfs -help/-ls/-put/-get/-cat/-rm/-cp/-mkdir/-touchz/-appendToFile
-
查看hdfs或hadoop子命令的帮助信息,如ls子命令
hdfs dfs -help ls hadoop fs -help ls #两个命令等价
-
查看hdfs文件系统中已经存在的文件。对比linux命令ls
hdfs dfs -ls / hadoop fs -ls /
-
在hdfs文件系统中创建文件
hdfs dfs -touchz /edits.txt
-
向HDFS文件中追加内容
hadoop fs -appendToFile edit1.xml /edits.txt #将本地磁盘当前目录的edit1.xml内容追加到HDFS根目录 的edits.txt文件
-
查看HDFS文件内容
hdfs dfs -cat /edits.txt
-
从本地路径上传文件至HDFS
#用法:hdfs dfs -put /本地路径 /hdfs路径 hdfs dfs -put hadoop-2.7.3.tar.gz / hdfs dfs -copyFromLocal hadoop-2.7.3.tar.gz / #根put作用一样 hdfs dfs -moveFromLocal hadoop-2.7.3.tar.gz / #根put作用一样,只不过,源文件被拷贝成功后,会被删除
-
在hdfs文件系统中下载文件
hdfs dfs -get /hdfs路径 /本地路径 hdfs dfs -copyToLocal /hdfs路径 /本地路径 #根get作用一样
-
在hdfs文件系统中创建目录
hdfs dfs -mkdir /shell
-
在hdfs文件系统中删除文件
hdfs dfs -rm /edits.txt hdfs dfs -rm -r /shell
-
在hdfs文件系统中修改文件名称(也可以用来移动文件到目录)
hdfs dfs -mv /xcall.sh /call.sh hdfs dfs -mv /call.sh /shell
-
在hdfs中拷贝文件到目录
hdfs dfs -cp /xrsync.sh /shell
-
递归删除目录
hdfs dfs -rmr /shell
-
列出本地文件的内容(默认是hdfs文件系统)
hdfs dfs -ls file:///home/bruce/
-
查找文件
# linux find命令 find . -name 'edit*' # HDFS find命令 hadoop fs -find / -name part-r-00000 # 在HDFS根目录中,查找part-r-00000文件
1.2.2.、hdfs与getconf结合使用
-
获取NameNode的节点名称(可能有多个)
hdfs getconf -namenodes
-
获取hdfs最小块信息
hdfs getconf -confKey dfs.namenode.fs-limits.min-block-size
-
查找hdfs的NameNode的RPC地址
hdfs getconf -nnRpcAddresses
1.2.3、 hdfs与dfsadmin结合使用
-
借助帮助信息
hdfs dfsadmin -help safemode
-
查看hdfs dfsadmin的帮助信息
hdfs dfsadmin
-
查看当前的模式
hdfs dfsadmin -safemode get
-
进入安全模式
hdfs dfsadmin -safemode enter
1.2.4、hdfs与fsck结合使用
-
fsck指令显示HDFS块信息
hdfs fsck /02-041-0029.mp4 -files -blocks -locations # 查看文件02-041-0029.mp4的块信息
1.2.5、 其他命令
-
检查压缩库本地安装情况
hadoop checknative
-
格式化名称节点(慎用,一般只在初次搭建集群,使用一次;格式化成功后,不要再使用)
hadoop namenode -format
-
执行自定义jar包
hadoop jar YinzhengjieMapReduce-1.0-SNAPSHOT.jar com.kaikeba.hadoop.WordCount /world.txt /out
1.3、WEB UI界面
注意:
若在windows下,能够访问node01:50070,需要配置C:\Windows\System32\drivers\etc\hosts文件,末尾添加如下三行内容
192.168.52.100 node01
192.168.52.110 node02
192.168.52.120 node03
-
访问HDFS的web界面,浏览器访问 node01:50070
二、block(核心概念)
2.1、数据块block
-
向HDFS上传文件,是按照128M为单位,切分成一个个block,分散的存储在集群的不同数据节点datanode上
-
问:1、HDFS中一个44M大小的block块会不会占据128M的空间?
-
不会,小于128M大小的块不会占据128M空间,此例占据44M
-
-
问:2、这样存储有没有问题?
-
hadoop集群搭建在廉价的商用服务器上,所以服务器有出问题的几率
-
-
2.2、block副本
-
因为HDFS是用普通的商用服务器搭建起来的;所以有节点出问题的可能性;
-
那么如果每个block只有一份的话,当block所在的节点宕机后,此block将无法访问,进而导致文件无法完整读取
-
为保正数据的可用及容错,HDFS设计成每个block共有三份,即三个副本
-
如何设置副本数?
-
hdfs-site.xml文件中 设置replication = 3
-
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
2.3 机架存储策略
-
实际机房中,会有机架,每个机架上若干服务器
每个block有三个副本;以block1为例
-
第一副本:在本机器(rack1机架中的datanode1)的HDFS目录下存储block1的第一个副本。
-
第二副本:在不同Rack(如rack2)的某个DataNode(datanode4)上存储block1的第二个副本。
-
第三副本:在datanode4所在机架rack2下,找一台其它的datanode节点(如datanode5),存储block1的第三个副本。
-
能有多副本:随机节点
了解下服务器参数:https://item.jd.com/4564487.html
机架:https://item.jd.com/16829137698.html
2.4 block的一些操作
-
1、设置文件副本数的作用:
-
数据分块存储和副本的存放,是保证可靠性和高性能的关键
-
-
2、设置文件副本数的方法:
-
方式一:使用命令设置文件副本数;动态生效,不需要重启hadoop集群
-
hadoop fs -setrep -R 4 /pathHDFS提供了fsck命令,用于检查HDFS上文件和目录的健康状态、获取文件的block信息和位置信息
-
-
方式二:修改配置文件hdfs-site.xml,需要重启hadoop集群才能生效
-
<property> <name>dfs.replication</name> <value>4</value> </property>
-
-
-
3、检查HDFS上文件和目录的健康状态、获取文件的block信息和位置信息
-
[hadoop@node01 ~]$ hdfs fsck
-
(1)查看文件中损坏的块
[hadoop@node01 ~]$ hdfs fsck /tmall-201412-1w.csv -list-corruptfileblocks
(2)删除损坏的文件
hdfs fsck /02-041-0029.mp4 -files -blocks -locations
三、HDFS架构(重点 )
-
大多数分布式大数据框架都是主从架构
-
HDFS也是主从架构 Master|Slave,或称为管理节点|工作节点
-
主叫NameNode,中文称“名称节点”
-
从叫DataNode,中文称“数据节点
-
-
NameNode负责存储HDFS集群的元数据,存在内存中
-
DataNode负责存储block块及块的元数据
-
SecondaryNameNode主要负责对HDFS元数据做checkpoint操作
-
集群的心跳机制,让集群中各节点形成一个整体;主节点知道从节点的死活
-
节点的上下线,导致存储的不均衡,可以手动触发负载均衡
3.1、概念
-
1、文件系统
-
file system文件系统:操作系统中负责管理文件、存储文件信息的软件
-
具体地说,它负责为用户创建文件,存入、读取、修改、转储、删除文件等
-
读文件 =>>找到文件 =>> 在哪 + 叫啥?
-
-
-
2、元数据
-
-
关于文件或目录的描述信息,如文件所在路径、文件名称、文件类型等等,这些信息称为文件的元数据metadata
-
注意:元数据的概念在其他的大数据框架中也屡有提及
-
-
3、命名空间
-
文件系统中,为了便于管理存储介质上的内容,给每个目录、目录中的文件、子目录都起了名字,这样形成的层级结构,称之为命名空间
-
同一个目录中,不能有同名的文件或目录
-
用处:这样通过目录+文件名称的方式能够唯一的定位一个文件
-
3.2、NameNode
-
1、HDFS本质上也是文件系统filesystem,所以它也有元数据metadata;
-
HDFS元数据metadata保存在NameNode内存中
-
-
2、NameNode作用:
-
HDFS的主节点
-
负责管理文件系统的命名空间,将HDFS的元数据存储在NameNode节点的内存中
-
负责响应客户端对文件的读写请求
-
-
3、HDFS元数据
-
文件目录树、所有的文件(目录)名称、文件属性(生成时间、副本、权限)、每个文件的块列表、每个block块所在的datanode列表
-
每个文件、目录、block占用大概150Byte字节的元数据;所以HDFS适合存储大文件,不适合存储小文件
-
-
4、HDFS元数据信息以两种形式保存:①编辑日志 edits log ②命名空间镜像文件 fsimage
-
① edits log:(HDFS编辑日志文件)
-
保存客户端对HDFS的所有更改记录,如增、删、重命名文件(目录),这些操作会修改HDFS目录树;
-
NameNode会在编辑日志edit日志中记录下来;
-
edits log为hdfs-site.xml中属性dfs.namenode.edits.dir的值决定;用于namenode保存edits.log文件
-
-
② fsimage:(HDFS元数据镜像文件 )
-
将namenode内存中的元数据落入磁盘生成的文件;
-
保存了文件系统目录树信息以及文件、块、datanode的映射关系,如下图
-
fsimage为hdfs-site.xml中属性dfs.namenode.name.dir的值决定;用于namenode保存fsimage文件
-
-
3.3、DataNode
-
1、DataNode数据节点的作用
-
存储block以及block元数据到datanode本地磁盘;
-
此处的元数据包括数据块的长度、块数据的校验和、时间戳
-
3.4、 SecondaryNameNode
-
1、为什么元数据存储在NameNode在内存中?
-
HDFS编辑日志文件 editlog:在NameNode节点中的编辑日志editlog中,记录下来客户端对HDFS的所有更改的记录,如增、删、重命名文件(目录);每次更改对应一个事务,每个事务有一个事务编号;事务编号递增
-
作用:一旦系统出故障,可以根据editlog恢复元数据;
-
-
2、这样做有什么问题?如何解决?
-
editlog日志大小会随着时间变的越来越大,导致系统重启后,根据日志恢复元数据的时间会越来越长。
-
为了避免这种情况,引入检查点机制checkpoint,命名空间镜像fsimage就是HDFS元数据的持久性检查点,即将内存中的元数据落磁盘生成的文件;
-
此时,namenode如果重启,可以将磁盘中的fsimage文件读入内容,将元数据恢复到某一个检查点,然后再执行检查点之后记录的编辑日志editlog,最后完全恢复元数据。
-
-
3、为什么引入SecondaryNameNode:
-
随着时间的推移,editlog记录的日志会变多;那么当namenode重启,恢复元数据过程中,会花越来越长的时间执行editlog中的每一个日志;而在namenode元数据恢复期间,HDFS不可用。
-
为了解决此问题,引入secondarynamenode辅助namenode,用来合并fsimage及editlog,定期做checkpoint检查点操作。
-
创建检查点checkpoint的两大条件:
-
另外,SecondaryNameNode每1分钟检查一次,从上一检查点开始,edits日志文件中是否已包括100万个事务,如果是,也会创建检查点
-
SecondaryNameNode每隔1小时创建一个检查点
-
-
-
-
4、合并流程
-
(1) SNN首先请求原NN进行edits的滚动,这样新的编辑操作就能够进入新的文件中
-
(2) SNN通过HTTP GET方式读取原NN中的fsimage及edits
-
(3) SNN读取fsimage到内存中,然后执行edits中的每个操作,并创建一个新的统一的fsimage文件,有ckpt后缀
-
(4) SNN通过HTTP PUT方式将新的fsimage发送到原NN
-
(5) 原NN用新的fsimage替换旧的fsimage,同时系统会更新fsimage文件到记录检查点的时间。
-
(6) 这个过程结束后,NN就有了最新的fsimage文件和更小的edits文件
-
5、SecondaryNameNode一般部署在另外一台节点上
-
因为它需要占用大量的CPU时间
-
并需要与namenode一样多的内存,来执行合并操作
6、如何查看edits日志文件
hdfs oev -i edits_0000000000000000256-0000000000000000363 -o /home/hadoop/edit1.xml
7、如何查看fsimage文件
hdfs oiv -p XML -i fsimage_0000000000000092691 -o fsimage.xml
3.5、心跳机制
1、工作原理:
-
NameNode启动的时候,会开一个ipc server在那里
-
DataNode启动后向NameNode注册,每隔3秒钟向NameNode发送一个“心跳heartbeat”
-
心跳返回结果带有NameNode给该DataNode的命令,如复制块数据到另一DataNode,或删除某个数据块
-
如果超过10分钟NameNode没有收到某个DataNode 的心跳,则认为该DataNode节点不可用
-
DataNode周期性(6小时)的向NameNode上报当前DataNode上的块状态报告BlockReport;块状态报告包含了一个该 Datanode上所有数据块的列表
2、心跳的作用:
-
通过周期心跳,NameNode可以向DataNode返回指令
-
可以判断DataNode是否在线
-
通过BlockReport,NameNode能够知道各DataNode的存储情况,如磁盘利用率、块列表;跟负载均衡有关
-
hadoop集群刚开始启动时,99.9%的block没有达到最小副本数(dfs.namenode.replication.min默认值为1),集群处于安全模式,涉及BlockReport;
3、相关配置项
3.6、 负载均衡
-
1、什么原因会有可能造成不均衡?
-
机器与机器之间磁盘利用率不平衡是HDFS集群非常容易出现的情况
-
尤其是在DataNode节点出现故障或在现有的集群上增添新的DataNode的时候
-
-
2、为什么需要均衡?
-
防止热点出现,提升集群存储资源利用率
-
从存储与计算两方面提高集群性能
-
-
3、如何手动负载均衡?下边命令无需重启hadoop
$HADOOP_HOME/sbin/start-balancer.sh -t 5% # 磁盘利用率最高的节点若比最少的节点,大于5%,触发均衡
-
停止负载均衡
$HADOOP_HOME/sbin/stop-balancer.sh
四、HDFS java API编程
4.1、建立MAVEN工程
①pom.xml文件;②建包、建类;
-
pom文件
<properties>
<cdh.version>2.6.0-cdh5.14.2</cdh.version>
</properties>
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-mr1-cdh5.14.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${cdh.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${cdh.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>${cdh.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
<scope>compile</scope>
</dependency>
</dependencies>
4.2、编写HDFS读写代码
1、本地文件上传到HDFS
package com.kaikeba.hadoop.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import java.io.*;
import java.net.URI;
/**
* 将本地文件系统的文件通过java-API写入到HDFS文件
*/
public class CopyFileFromLocal {
/**
* @param args
* args0 windows本地磁盘文件C:/test.txt 或虚拟机本地磁盘文件/kkb/install/hadoop-2.6.0-cdh5.14.2/README.txt
* args1 hdfs上文件hdfs://node01:8020/test.txt
*/
public static void main(String[] args){
// 0、本地磁盘路径
String source = args[0];
// 0、先确保/data目录存在
String destination = args[1];//HDFS的路徑
InputStream in = null;
try {
// 1、创建带缓冲的输入流in
in = new BufferedInputStream(new FileInputStream(source));
// 2、创建HDFS读写的配置文件对象
Configuration conf = new Configuration();
// 3、创建FileSystem对象
FileSystem fs = FileSystem.get(URI.create(destination),conf);
// 4、生成输出流out,根据FileSystem对象
//调用Filesystem的create方法返回的是FSDataOutputStream对象
//该对象不允许在文件中定位,因为HDFS只允许一个已打开的文件顺序写入或追加
OutputStream out = fs.create(new Path(destination));
// 5、将输入流的数据,拷贝到输出流,
IOUtils.copyBytes(in, out, 4096, true);
} catch (FileNotFoundException e) {
System.out.println("exception");
e.printStackTrace();
} catch (IOException e) {
System.out.println("exception1");
e.printStackTrace();
}
}
}
2、从HDFS上拷贝数据到本地
package com.kaikeba.hadoop.hdfs;
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.hadoop.io.IOUtils;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
/**
* 从HDFS读取文件
* 打包运行jar包 [bruce@node01 Desktop]$ hadoop jar com.kaikeba.hadoop-1.0-SNAPSHOT.jar com.kaikeba.hadoop.hdfs.ReadFileFromHDFS
*/
public class ReadFileFromHDFS {
/**
* @param args
* args0 hdfs上文件hdfs://node01:8020/test.txt
* args1 windows本地磁盘文件C:/01 HK/高级03班/test01.txt或虚拟机本地磁盘文件
*/
public static void main(String[] args) {
try {
// 0、源文件
String srcFile = args[0];//HDFS的路径
// 0、本地文件路径
String destination = args[1];
// 1、创建配置文件对象
Configuration conf = new Configuration();
// 2、创建文件系统
FileSystem fs = FileSystem.get(URI.create(srcFile),conf);
FSDataInputStream hdfsInStream = fs.open(new Path(srcFile));//输入流
// 3、创建带缓冲的输出流,
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destination));
// 4、将输出流的数据,拷贝到输入流,
IOUtils.copyBytes(hdfsInStream, outputStream, 4096, true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.3、运行代码
1、本地运行
(代码右键->run)
2、打包运行
(1)打包,两种方式;
方式一(得独立安装maven):
mvn clean package -DskipTests # 在工程目录下执行
方式二:利用IDEA图形化界面
(2) 运行jar包
[hadoop@node01 ~]$ hadoop jar com.kaikeba.hadoop-1.0-SNAPSHOT.jar com.kaikeba.hadoop.hdfs.CopyFileFromLocal /kkb/install/hadoop-2.6.0-cdh5.14.2 /README.txt /README.txt