Hadoop之HDFS
Posted 寒风孤月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hadoop之HDFS相关的知识,希望对你有一定的参考价值。
一.HDFS概述
1.1HDFS产生的背景定义
1)背景:随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的 操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种。
2)定义:HDFS(Hadoop Distributed File System),它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。
1.2 HDFS优缺点
1)优点:
1、可构建在廉价机器上
通过多个副本来提高可靠性,文件切分多个块进行存储
2、高容错性
数据自动保存多个副本,副本丢失后,可以自动恢复
3、适合批处理
移动计算比移动数据方便
4、适合大数据处理
10k+节点规模
5、流式文件访问
一次写入,多次读取,可以保证数据的一致性
2)缺点:
不适于以下操作
1、要求高的数据访问
比如毫秒级
2、小文件存取
寻道时间超过读取时间
3、并发写入、文件随机修改
一个文件只能有一个写
仅仅支持追加
4、不适合存储小文件
存储一个1亿个小文件,大小仅仅1t,但是消耗掉20g左右的内存
1.3HDFS组成架构
**1.3.1架构介绍**
HDFS是一个主从(Master/Slaves)架构
由一个NameNode和一些DataNode组成
面向文件包含:文件数据(data)和文件元数据(metadata)
NameNode负责存储和管理文件元数据,并维护了一个层次型的文件目录树
DataNode负责存储文件数据(block块),并提供block的读写
DataNode与NameNode维持心跳,并汇报自己持有的block信息
Client和NameNode交互文件元数据和DataNode交互文件block数据
1.3.2角色功能
1) NameNode
完全基于内存存储文件元数据、目录结构、文件block的映射
需要持久化方案保证数据可靠性
提供副本放置策略
2)DataNode
基于本地磁盘存储block(文件的形式)
并保存block的校验和数据保证block的可靠性
与NameNode保持心跳,汇报block列表状态
3) Client:就是客户端。
文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;(2)与NameNode交互,获取文件的位置信息;
与DataNode交互,读取或者写入数据;
Client提供一些命令来管理IDFS,比INameNode格式化;
Client可以通过一些命令来访问HIDFS,比对HHDFSt增删查改操作;
4) Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
在非Ha模式下,SNN一般是独立的节点,周期完成对NN的EditLog向FsImage合并,减少EditLog大小,减少NN启动时间
根据配置文件设置的时间间隔fs.checkpoint.period 默认3600秒
根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB
1.3.3 HDFS文件块大小
举个例子:
100g的数据,集群有100个节点,按照1g的大小进行存储,每个节点要存储1g的数据量
100g的数据,集群有90个节点,按照1g的大小进行存储,其中有10台要存储2g的数据,其他的80台要存储1g的数据
假设1g的数据需要1秒钟的运算时间,那么整个任务需要2秒钟的运算时间。
100g的数据,集群有90个节点,按照512m的大小进行切分存储,有20个节点存储1.5g的数据,有70个节点存储1g的数据
假设1g的数据需要1秒钟的运算时间,那么整个任务需要1.5秒钟的运算时间。
从上面的这个例子结果来看,我们切分是不是越小越好?
但是有个问题:小文件很多,就会有问题!
举个例子:
access.log 100g
block0 50g
block1 50g
access.log 100g
block0 20g
block1 20g
block2 20g
block3 20g
block4 20g
从上面的这个例子结果来看:因为下载的时候需要将文件还原,需要合并块,从这看,是不是切分的越大越好?
不大不小:
HDFS在设计的时候考虑了不同的应用场景,每个不同的场景中,有可能需要的切分的块的大小不一样,可以配置。
HDFS集群块大小可以配置
但是有默认的大小:
Hadoop2.x版本以前,默认块大小:64M
Hadoop2.x版本及以后,默认块大小:128M
二.HDFS的Shell操作
2.1 基本语法
hadoop fs 具体命令 OR hdfs dfs 具体命令,两个是完全相同的。
2.2 命令大全
[wangzhao@hadoop102 ~]$ hadoop fs
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] [-d] [-t <thread count>] <localsrc> ... <dst>]
[-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] <path> ...]
[-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] [-v] [-x] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] -n name | -d [-e en] <path>]
[-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
[-head <file>]
[-help [cmd ...]]
[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [-b|-k -m|-x <acl_spec> <path>]|[--set <acl_spec> <path>]]
[-setfattr -n name [-v value] | -x name <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] [-s <sleep interval>] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touch [-a] [-m] [-t TIMESTAMP ] [-c] <path> ...]
[-touchz <path> ...]
[-truncate [-w] <length> <path> ...]
[-usage [cmd ...]]
Generic options supported are:
-conf <configuration file> specify an application configuration file
-D <property=value> define a value for a given property
-fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
-jt <local|resourcemanager:port> specify a ResourceManager
-files <file1,...> specify a comma-separated list of files to be copied to the map reduce cluster
-libjars <jar1,...> specify a comma-separated list of jar files to be included in the classpath
-archives <archive1,...> specify a comma-separated list of archives to be unarchived on the compute machines
The general command line syntax is:
command [genericOptions] [commandOptions]
2.3常用命令操作
1)-help:输出这个命令参数
[wangzhao@hadoop102 ~]$ hadoop fs -help rm
-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ... :
Delete all files that match the specified file pattern. Equivalent to the Unix
command "rm <src>"
-f If the file does not exist, do not display a diagnostic message or
modify the exit status to reflect an error.
-[rR] Recursively deletes directories.
-skipTrash option bypasses trash, if enabled, and immediately deletes <src>.
-safely option requires safety confirmation, if enabled, requires
confirmation before deleting large directory with more than
<hadoop.shell.delete.limit.num.files> files. Delay is expected when
walking over large directory recursively to count the number of
files to be deleted before the confirmation.
2)创建/wz文件夹`
[wangzhao@hadoop102 ~]$ hadoop fs -mkdir /wz
3)上传
- -moveFromLocal:从本地剪切粘贴到HDFS
hadoop fs -moveFromLocal ./wz.txt /wz
- -copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去
hadoop fs -copyFromLocal wz.txt /wz
3)-put:等同于copyFromLocal,生产环境更习惯用put
hadoop fs -put ./wz.txt /wz
- -appendToFile:追加一个文件到已经存在的文件末尾
hadoop fs -appendToFile wz.txt /wz/wz.txt
4)下载
1)-copyToLocal:从HDFS拷贝到本地
hadoop fs -copyToLocal /wz/wz.txt ./
- -get:等同于copyToLocal,生产环境更习惯用get
hadoop fs -get /wz/wz.txt ./wz.txt
5)操作
1)-ls: 显示目录信息
hadoop fs -ls /wz
2)-cat:显示文件内容
hadoop fs -cat /wz/wz.txt
3)-chgrp、-chmod、-chown:Linux文件系统中的用法一样,修改文件所属权限
hadoop fs -chmod 777 /wz/wz.txt
hadoop fs -chown wangzhao:wangzhao /wz/wz.txt
4)-rm:删除文件或文件夹
hadoop fs -rm /wz/wz.txt
5)-rm -r:递归删除目录及目录里面内容
hadoop fs -rm -r /wz
6)-mkdir:创建路径
hadoop fs -mkdir /wxh
7)从HDFS的一个路径拷贝到HDFS的另一个路径
hadoop fs -cp /wz/wz.txt /jinguo
8)-mv:在HDFS目录中移动文件
hadoop fs -mv /wz/wy.txt /jinguo
三. HDFS的API操作
package com.wangzhao.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
/*
客户端代码常用套路
1.获取客户端对象
2.执行相关的操作
3.关闭资源
HDFS Zookeeper
*/
public class HdfsClient
private FileSystem fs;
@Before
public void init() throws URISyntaxException, IOException, InterruptedException
//链接集群nn的地址
URI uri = new URI("hdfs://hadoop102:8020");
//创建一个配置文件
Configuration conf = new Configuration();
//用户
String user ="wangzhao";
//1.获取客户端对象
fs = FileSystem.get(uri, conf,user);
@After
public void close() throws IOException
//3.关闭资源
fs.close();
//创建目录
@Test
public void testmkdir() throws IOException
fs.mkdirs(new Path("/xiyou/huaguoshan1"));
//上传
/*
参数优先级 hdfs-default.xml=>hdfs-site.xml=>在项目资源目录文件下的配置文件=》代码里面的配置
*/
@Test
public void testPut() throws IOException
//参数一表示删除原数据 参数二 是否允许被覆盖 参数三 原数据路径 参数四目的地路径
fs.copyFromLocalFile(true,false,new Path("D:\\\\sunwukong.txt"),new Path("/xiyou/huaguoshan"));
//文件下载
@Test
public void testGet() throws IOException
// 参数一:原文件是否删除 参数二:原文件路径(HDFS) 参数三:目标地址路径(Win) 参数四:校验文件
fs.copyToLocalFile(true,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("D:\\\\sunwukong.txt"),true);
//删除
@Test
public void testRm() throws IOException
//参数一:要删除的路径 参数二:是否要递归删除
//fs.delete(new Path("/xiyou/huaguoshan1/sunwukong.txt"),false);
//删除空目录
fs.delete(new Path("/xiyou/huaguoshan1"),false);
//文件的更名和移动
@Test
public void testMv() throws IOException
//参数一原文件路径 参数二 目标文件的路径
//对文件名称的修改
//fs.rename(new Path("/xiyou/huaguoshan"),new Path("/xiyou/shuilian"));
//文件的移动和更名
fs.rename(new Path("/xiyou/shuilian"),new Path("/cls"));
//获取文件详情
@Test
public void fileDetail() throws IOException
//获取所有文件信息
RemoteIterator<LocatedFileStatus> list_f = fs.listFiles(new Path("/"), true);
while (list_f.hasNext())
LocatedFileStatus fileStatus = list_f.next();
System.out.println("----------"+fileStatus.getPath()+"---------------");
System.out.println(fileStatus.getPermission());
System.out.println(fileStatus.getOwner());
System.out.println(fileStatus.getLen());
System.out.println(fileStatus.getModificationTime());
System.out.println(fileStatus.getReplication());
System.out.println(fileStatus.getBlockSize());
System.out.println(fileStatus.getPath().getName());
//获取块信息
System.out.println("获取块信息");
BlockLocation[] locations = fileStatus.getBlockLocations();
System.out.println(Arrays.toString(locations));
//判断是文件还是文件夹
@Test
public void testFile() throws IOException
FileStatus[] list = fs.listStatus(new Path("/"));
for (FileStatus status : list)
if (status.isFile())
System.out.println(" 文件 : "+status.getPath().getName());
else
System.out.println("目录:"+status.getPath().getName());
四.HDFS读写流程(重点)
1)Block的副本放置策略
第一个副本:放置在上传文件的DN;如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点。
第二个副本:放置在于第一个副本不同的 机架的节点上。
第三个副本:与第二个副本相同机架的节点。
更多副本:随机节点。
2)写流程
Client和NN连接创建文件元数据
NN判定元数据是否有效
NN处发副本放置策略,返回一个有序的DN列表
Client和DN建立Pipeline连接
Client将块切分成packet(64KB),并使用chunk(512B)+chucksum(4B)填充
Client将packet放入发送队列dataqueue中,并向第一个DN发送
第一个DN收到packet后本地保存并发送给第二个DN
第二个DN收到packet后本地保存并发送给第三个DN
这一个过程中,上游节点同时发送下一个packet
生活中类比工厂的流水线
Hdfs使用这种传输方式,副本数对于client是透明的
当block传输完成,DN们各自向NN汇报,同时client继续传输下一个block
所以,client的传输和block的汇报也是并行的
3)读流程
为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本。
如果在读取程序的同一个机架上有一个副本,那么就读取该副本。
如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本。
语义:下载一个文件:
Client和NN交互文件元数据获取fileBlockLocation
NN会按距离策略排序返回
Client
以上是关于Hadoop之HDFS的主要内容,如果未能解决你的问题,请参考以下文章
Hadoop HDFS编程 API入门系列之从本地上传文件到HDFS
Hadoop HDFS编程 API入门系列之路径过滤上传多个文件到HDFS