版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前言
上一篇文章介绍了HDFS组成、读写原理还有一些其他的,这次准备来上手操作下。
HDFS的Shell命令行使用
Shell命令行客户端
HDFS是存取数据的分布式文件系统,那么对HDFS的操作,就是文件系统的基本操作,比如文件的创建、修改、删除、修改权限等,文件夹的创建、删除、重命名等。对HDFS的操作命令类似于Linux的shell对文件的操作,如ls、mkdir、rm等。
Hadoop提供了文件系统的shell命令行客户端,使用方法如下:
hadoop fs <args>
文件系统shell包括与Hadoop分布式文件系统(HDFS)以及Hadoop支持的其他文件系统(如本地FS,HFTP FS,S3 FS等)直接交互的各种类似shell的命令。
所有FS shell命令都将路径URI作为参数。URI格式为scheme://authority/path。对于HDFS,该scheme是hdfs,对于本地FS,该scheme是file。scheme和authority是可选的。如果未指定,则使用配置中指定的默认方案。
对于HDFS,命令示例如下:
hadoop fs -ls hdfs://namenode:port/parent/child
hadoop fs -ls /parent/child
对于本地文件系统,命令示例如下:
hadoop fs -ls file:///root/
如果使用的文件系统是HDFS,则也可使用hdfs dfs 命令。
Shell命令选项
选项名称 | 使用格式 | 含义 |
---|
-ls | -ls <路径> | 查看指定路径的当前目录结构 | -lsr | -lsr <路径> | 递归查看指定路径的目录结构 | -du | -du <路径> | 统计目录下个文件大小 | -dus | -dus <路径> | 汇总统计目录下文件(夹)大小 | -count | -count [-q] <路径> | 统计文件(夹)数量 | -mv | -mv <源路径> <目的路径> | 移动 | -cp | -cp <源路径> <目的路径> | 复制 | -rm | -rm [-skipTrash] <路径> | 删除文件/空白文件夹 | -rmr | -rmr [-skipTrash] <路径> | 递归删除 | -put | -put <多个linux上的文件> <hdfs路径> | 上传文件 | -copyFromLocal | -copyFromLocal <多个linux上的文件> <hdfs路径> | 从本地复制 | -moveFromLocal | -moveFromLocal -moveFromLocal <多个linux上的文件> <hdfs路径> | 从本地移动 | -getmerge | -getmerge <源路径> <linux路径> | 合并到本地 | -cat | -cat <hdfs路径> | 查看文件内容 | -text | -text <hdfs路径> | 查看文件内容 | -copyToLocal | -copyToLocal [-ignoreCrc] [-crc] [hdfs源路径] [linux目的路径] | 从本地复制 | -moveToLocal | -moveToLocal [-crc] <hdfs源路径> <linux目的路径> | 从本地移动 | -mkdir | -mkdir <hdfs路径> | 创建空白文件夹 | -touchz | -touchz <文件路径> | 创建空白文件 | -stat | -stat [format] <路径> | 显示文件统计信息 | -tail | -tail [-f] <文件> | 查看文件尾部信息 | -chmod | -chmod [-R] <权限模式> [路径] | 修改权限 | -chown | -chown [-R] [属主][:[属组]] 路径 | 修改属主 | -chgrp | -chgrp [-R] 属组名称 路径 | 修改属组 | -help | -help [命令选项] | 帮助 |
常用的Shell命令
-ls
格式: hadoop fs -ls URI
作用:类似于Linux的ls命令,显示文件列表
hadoop fs -ls /
-lsr
格式 : hdfs dfs -lsr URI
作用 : 在整个目录下递归执行ls, 与UNIX中的ls-R类似
hadoop fs -lsr /
ls
格式 : hdfs dfs [-p] -mkdir <paths>
作用 : 以<paths>中的URI作为参数,创建目录。使用-p参数可以递归创建目录
hadoop fs -mkdir /dir1
hadoop fs -mkdir /dir2
hadoop fs -p -mkdir /aaa/bbb/ccc
-put
格式 : hadoop fs -put <localsrc > ... <dst>
作用 : 将单个的源文件src或者多个源文件srcs从本地文件系统拷贝到目标文件系统中(<dst>对应的路径)。也可以从标准输入中读取输入,写入目标文件系统中
echo “Hello HDFS” >> /root/1.txt
hadoop fs -put /root/1.txt /dir1
-moveFromLocal
格式: hdfs dfs -moveFromLocal <localsrc> <dst>
作用: 和put命令类似,但是源文件localsrc拷贝之后自身被删除
echo “Hello HDFS” >> /root/2.txt
hdfs dfs -moveFromLocal /root/2.txt /
-moveToLocal
未实现
-get
格式 hadoop fs -get [-ignorecrc ] [-crc] <src> <localdst>
作用:将文件拷贝到本地文件系统。 CRC 校验失败的文件通过-ignorecrc选项拷贝。 文件和CRC校验和可以通过-CRC选项拷贝
hadoop fs -get /2.txt /export/data
-getmerge
格式: hadoop fs -getmerge -nl < hdfs dir > < local file >
功能:合并下载多个文件
参数: 加上nl后,合并到local file中的hdfs文件之间会空出一行
示例:比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,...
hadoop fs -getmerge /aaa/log.* ./log.sum
-mv
格式 : hadoop fs -mv URI <dest>
作用: 将hdfs上的文件从原路径移动到目标路径(移动之后文件删除),该命令不能夸文件系统
hadoop fs -mv /dir1/a.txt /dir2
-rm
格式: hadoop fs -rm [-r] 【-skipTrash】 URI 【URI 。。。】
作用: 删除参数指定的文件和目录,参数可以有多个,删除目录需要加-r参数
如果指定-skipTrash选项,那么在回收站可用的情况下,该选项将跳过回收站而直接删除文件;
否则,在回收站可用时,在HDFS Shell 中执行此命令,会将文件暂时放到回收站中。
hadoop fs -rm /2.txt
hadoop fs -rm -r /dir1
-cp
格式: hdfs dfs -cp URI [URI ...] <dest>
作用: 将文件拷贝到目标路径中。如果<dest> 为目录的话,可以将多个文件拷贝到该目录下。
-f 选项将覆盖目标,如果它已经存在。
-p 选项将保留文件属性(时间戳、所有权、许可、ACL、XAttr)。
hadoop fs -cp /dir1/1.txt /dir2/2.txt
-cat
hadoop fs -cat URI [uri ...]
作用:将参数所指示的文件内容输出到控制台
hadoop fs -cat /dir2/2.txt
-du
hadoop fs -cat URI
功能:显示目录中所有文件大小,当只指定一个文件时,显示此文件的大小。
hadoop fs -du /
-chmod
格式: hadoop fs -chmod [-R] URI[URI ...]
作用: 改变文件权限。如果使用 -R 选项,则对整个目录有效递归执行。使用这一命令的用户必须是文件的所属用户,或者超级用户。
例如:可以创建一个用户hadoop,将/a.txt的所属用户和所属用户组修改为hadoop
hadoop fs -chmod -R 777 /dir1
-chown
格式: hadoop fs -chmod [-R] URI[URI ...]
作用: 改变文件的所属用户和用户组。如果使用 -R 选项,则对整个目录有效递归执行。使用这一命令的用户必须是文件的所属用户,或者超级用户。
hadoop fs -chown -R hadoop:hadoop /a.txt
-appendToFile
格式: hadoop fs -appendToFile <localsrc> ... <dst>
作用: 追加一个或者多个文件到hdfs指定文件中.也可以从命令行读取输入.
cd /export/server/hadoop2.7.5/etc/hadoop/
hadoop fs -appendToFile *.xml /big.xml
HDFS的JAVA API操作
HDFS在生产应用中主要是客户端的开发,其核心步骤是从HDFS提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件。
配置Windows下Hadoop环境
在windows上做HDFS客户端应用开发,需要设置Hadoop环境,而且要求是windows平台编译的Hadoop,不然会报以下的错误: 缺少winutils.exe Could not locate executable null \bin\winutils.exe in the hadoop binaries 缺少hadoop.dll Unable to load native-hadoop library for your platform… using builtin-Java classes where applicable 搭建步骤: 第一步 :将已经编译好的Windows版本Hadoop解压到到一个没有中文没有空格的路径下面 第二步 :在windows上面配置hadoop的环境变量: HADOOP_HOME,并将%HADOOP_HOME%\bin添加到path中 第三步 :把hadoop2.7.5文件夹中bin目录下的hadoop.dll文件放到系统盘: C:\Windows\System32 目录 第四步 :关闭windows重启
导入Maven依赖
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
使用文件系统方式访问数据
涉及的主要类
在java中操作HDFS,主要涉及以下Class: Configuration :该类的对象封转了客户端或者服务器的配置; FileSystem :该类的对象是一个文件系统对象,可以用该对象的一些方法来对文件进行操作,通过FileSystem的静态方法get获得该对象。
FileSystem fs = FileSystem.get(conf);
get方法从conf中的一个参数 fs.defaultFS的配置值判断具体是什么类型的文件系统。如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为: file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象。
获取FileSystem方式
第一种方式
@Test
public void getFileSystem1() throws IOException {
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", "hdfs://node1:8020/");
FileSystem fileSystem = FileSystem.get(configuration);
System.out.println(fileSystem.toString());
}
第二种方式
@Test
public void getFileSystem2() throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"), new Configuration());
System.out.println("fileSystem:"+fileSystem);
}
遍历HDFS中所有文件
@Test
public void listMyFiles()throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"), new Configuration());
RemoteIterator<LocatedFileStatus> locatedFileStatusRemoteIterator = fileSystem.listFiles(new Path("/"), true);
while (locatedFileStatusRemoteIterator.hasNext()){
LocatedFileStatus next = locatedFileStatusRemoteIterator.next();
System.out.println(next.getPath().toString());
}
fileSystem.close();
}
HDFS上创建文件夹
@Test
public void mkdirs() throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
boolean mkdirs = fileSystem.mkdirs(new Path("/hello/mydir/test"));
fileSystem.close();
}
下载文件-方式1
@Test
public void getFileToLocal()throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
FSDataInputStream inputStream = fileSystem.open(new Path("/timer.txt"));
FileOutputStream outputStream = new FileOutputStream(new File("e:\\timer.txt"));
IOUtils.copy(inputStream,outputStream );
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
fileSystem.close();
}
下载文件-方式2
@Test
public void downLoadFile() throws URISyntaxException, IOException, InterruptedException {
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"), new Configuration());
fileSystem.copyToLocalFile(new Path("/anaconda-ks.cfg"), new Path("E:\\test"));
fileSystem.close();
}
上传文件
@Test
public void putData() throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"), new Configuration());
fileSystem.copyFromLocalFile(new Path("file:///c:\\install.log"),new Path("/hello/mydir/test"));
fileSystem.close();
}
小文件合并
由于 Hadoop 擅长存储大文件,因为大文件的元数据信息比较少,如果 Hadoop 集群当中有大量的小文件,那么每个小文件都需要维护一份元数据信息,会大大的增加集群管理元数据的内存压力,所以在实际工作当中,如果有必要一定要将小文件合并成大文件进行一起处理,可以在上传的时候将小文件合并到一个大文件里面去
@Test
public void mergeFile() throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"), new Configuration(),"root");
FSDataOutputStream outputStream = fileSystem.create(new Path("/bigfile.txt"));
LocalFileSystem local = FileSystem.getLocal(new Configuration());
FileStatus[] fileStatuses = local.listStatus(new Path("file:///E:\\input"));
for (FileStatus fileStatus : fileStatuses) {
FSDataInputStream inputStream = local.open(fileStatus.getPath());
IOUtils.copy(inputStream,outputStream);
IOUtils.closeQuietly(inputStream);
}
IOUtils.closeQuietly(outputStream);
local.close();
fileSystem.close();
}
hdfs访问权限控制
HDFS权限模型和Linux系统类似。每个文件和目录有一个所有者(owner)和一个组(group)。文件或目录对其所有者、同组的其他用户以及所有其他用户(other)分别有着不同的权限。对文件而言,当读取这个文件时需要有r权限,当写入或者追加到文件时需要有w权限。对目录而言,当列出目录内容时需要具有r权限,当新建或删除子文件或子目录时需要有w权限,当访问目录的子节点时需要有x权限。但hdfs的文件权限需要开启之后才生效,否则在HDFS中设置权限将不具有任何意义! HDFS的权限设置是通过hdfs-site.xml文件来设置,在搭建Hadoop集群时,将HDFS的权限关闭了,所以对HDFS的任何操作都不会受到影响的。 接下来我们将HDFS的权限开启,测试下HDFS的权限控制。
1、 停止hdfs集群,在node1机器上执行以下命令
stop-dfs.sh
2、修改node1机器上的hdfs-site.xml当中的配置文件
vim hdfs-site.xml
<property>
<name>dfs.permissions.enabled</name>
<value>true</value>
</property>
3、修改完成之后配置文件发送到其他机器上面去
scp hdfs-site.xml node2:$PWD
scp hdfs-site.xml node3:$PWD
4、 重启hdfs集群
start-dfs.sh
5、随意上传一些文件到我们hadoop集群当中准备测试使用
cd /export/server/hadoop-2.7.5/etc/hadoop
hadoop fs -mkdir /config
hadoop fs -put *.xml /config
hadoop fs -chmod 600 /config/core-site.xml
经过以上操作之后,core-site.xml文件的权限如下: 这个权限是当前所属用户root具有对core-site.xml文件的可读,可写权限。
6、 使用代码准备下载文件
@Test
public void getConfig()throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root");
fileSystem.copyToLocalFile(new Path("/config/core-site.xml"),new Path("file:///c:/core-site.xml"));
fileSystem.close();
}
当HDFS的权限开启之后,运行以上代码发现权限拒绝,不允许访问。 这是因为我们在Windows下运行HDFS的客户端,用户名一般不是root,是其他用户,所以对core-site.xml文件没有任何操作权限。
解决方法: 方式1-修改core-site.xml的文件权限
hadoop fs -chmod 777/config/core-site.xml
方式2-伪造用户 在这里,我们可以以root用户的身份去访问文件
@Test
public void getConfig()throws Exception{
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root");
fileSystem.copyToLocalFile(new Path("/config/core-site.xml"),new Path("file:///c:/core-site.xml"));
fileSystem.close();
}
执行结果如下 执行成功
HDFS的高级使用命令
HDFS的安全模式
安全模式是hadoop的一种保护机制 ,用于保证集群中的数据块的安全性。当集群启动的时候,会首先进入安全模式。当系统处于安全模式时会检查数据块的完整性。
假设我们设置的副本数(即参数dfs.replication)是3,那么在datanode上就应该有3个副本存在,假设只存在2个副本,那么比例就是2/3=0.666。hdfs默认的副本率0.999。我们的副本率0.666明 显小于0.999,因此系统会自动的复制副本到其他dataNode,使得副本率不小于0.999。如果系统中有5个副本,超过我们设定的3个副本,那么系统也会删除多于的2个副本。
在安全模式状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在当整个系统达到安全标准时,HDFS自动离开安全模式。 安全模式操作命令
hdfs dfsadmin -safemode get
hdfs dfsadmin -safemode enter
hdfs dfsadmin -safemode leave
HDFS基准测试
实际生产环境当中,hadoop的环境搭建完成之后,第一件事情就是进行压力测试,测试我们的集群的读取和写入速度,测试我们的网络带宽是否足够等一些基准测试
测试写入速度
向HDFS文件系统中写入数据,10个文件,每个文件10MB,文件存放到/benchmarks/TestDFSIO中
hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -write -nrFiles 10 -fileSize 10MB
完成之后查看写入速度结果
hadoop fs -text /benchmarks/TestDFSIO/io_write/part-00000
测试读取速度
测试hdfs的读取文件性能 在HDFS文件系统中读入10个文件,每个文件10M
hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -read -nrFiles 10 -fileSize 10MB
查看读取结果
hadoop fs -text /benchmarks/TestDFSIO/io_read/part-00000
清除测试数据
hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -clean
HDFS其他功能
不同集群之间的数据复制
在我们实际工作当中,极有可能会遇到将测试集群的数据拷贝到生产环境集群,或者将生产环境集群的数据拷贝到测试集群,那么就需要我们在多个集群之间进行数据的远程拷贝,hadoop自带也有命令可以帮我们实现这个功能。
集群内部文件拷贝scp
本地复制到远程
方式1:指定用户名,命令执行后需要再输入密码; scp -r local_folder remote_username@remote_ip:remote_folder
方式2:没有指定用户名,命令执行后需要输入用户名和密码; scp -r local_folder remote_ip:remote_folder 注意,如果实现了ssh免密登录之后,则不需要输入密码即可拷贝。 实例:
scp /root/test.txt root@192.168.88.161:/root/
scp /root/test.txt root@192.168.88.161:/root/test1.txt
scp -r /root/test/ root@192.168.88.161:/root/
远程复制到本地
远程复制到本地 与 从本地复制到远程命令类似,不同的是 远程文件作为源文件在前,本地文件作为目标文件在后。
scp root@192.168.88.162:/root/test.txt /root/test.txt
跨集群之间的数据拷贝distcp
DistCp(distributed copy)是一款被用于大型集群间/集群内的复制工具,该命令的内部原理是MapReduce。
cd /export/servers/hadoop-2.7.5/
bin/hadoop distcp hdfs://node1:8020/jdk-8u241-linux-x64.tar.gz hdfs://cluster2:8020/
Archive档案的使用
HDFS并不擅长存储小文件,因为每个文件最少一个block,每个block的元数据都会在NameNode占用内存,如果存在大量的小文件,它们会吃掉NameNode节点的大量内存。 Hadoop Archives可以有效的处理以上问题,它 可以把多个文件归档成为一个文件,归档成一个文件后还可以透明的访问每一个文件。
如何创建Archive
Usage: hadoop archive -archiveName name -p * 其中-archiveName是指要创建的存档的名称。比如test.har,archive的名字的扩展名应该是*.har。 -p参数指定文件存档文件(src)的相对路径。 例如:如果你只想存档一个目录/config下的所有文件:
hadoop archive -archiveName test.har -p /config /outputdir
这样就会在/outputdir目录下创建一个名为test.har的存档文件。
如何查看Archive
首先我们来看下创建好的har文件。使用如下的命令:
hadoop fs -ls /outputdir/test.har
这里可以看到har文件包括:两个索引文件,多个part文件(本例只有一个)以及一个标识成功与否的文件。 part文件是多个原文件的集合,根据index文件去找到原文件。 例如上述的/input目录下有很多小的xml文件。进行archive操作之后,这些小文件就归档到test.har里的part-0一个文件里。
hadoop fs -cat /outputdir/test.har/part-0
archive作为文件系统层暴露给外界。所以所有的fs shell命令都能在archive上运行,但是要使用不同的URI。Hadoop Archives的URI 是: har://scheme-hostname:port/archivepath/fileinarchive scheme-hostname格式为 hdfs-域名:端口,如果没有提供scheme-hostname,它会使用默认的文件系统。这种情况下URI是这种形式: har:///archivepath/fileinarchive 如果用har uri去访问的话,索引、标识等文件就会隐藏起来,只显示创建档案之前的原文件: 查看归档文件中的小文件,使用har uri
hadoop fs -ls har://hdfs-node1:8020/outputdir/test.har
查看归档文件中的小文件,不使用har uri
hadoop fs -ls har:///outputdir/test.har
查看har归档文件中小文件的内容
hadoop fs -cat har:///outputdir/test.har/core-site.xml
如何解压Archive
hadoop fs -mkdir /config2
hadoop fs -cp har:///outputdir/test.har/* /config2
查看HDFS页面,发现/config2目录中已经有解压后的小文件了
Archive注意事项
1、 Hadoop archives是特殊的档案格式。一个Hadoop archive对应一个文件系统目录。Hadoop archive的扩展名是*.har; 2、 创建archives本质是运行一个Map/Reduce任务,所以应该在Hadoop集群上运行创建档案的命令,要提前启动Yarn集群; 3、 创建archive文件要消耗和原文件一样多的硬盘空间; 4、 archive文件不支持压缩,尽管archive文件看起来像已经被压缩过; 5、 archive文件一旦创建就无法改变,要修改的话,需要创建新的archive文件。事实上,一般不会再对存档后的文件进行修改,因为它们是定期存档的,比如每周或每日; 6、 当创建archive时,源文件不会被更改或删除;
Snapshot快照的使用
快照顾名思义,就是相当于 对hdfs文件系统做一个备份,可以通过快照对指定的文件夹设置备份,但是添加快照之后,并不会立即复制所有文件,而是指向同一个文件。当写入发生时,才会产生新文件。 HDFS 快照(HDFS Snapshots)是文件系统在某个时间点的只读副本。可以在文件系统的子树或整个文件系统上创建快照。快照的常见用途主要包括数据备份,防止用户误操作和容灾恢复。
快照使用基本语法
1、开启指定目录的快照功能
hdfs dfsadmin -allowSnapshot 路径
2、禁用指定目录的快照功能(默认就是禁用状态)
hdfs dfsadmin -disallowSnapshot 路径
3、给某个路径创建快照snapshot
hdfs dfs -createSnapshot 路径
4、指定快照名称进行创建快照snapshot
hdfs dfs -createSanpshot 路径 名称
5、给快照重新命名
hdfs dfs -renameSnapshot 路径 旧名称 新名称
6、列出当前用户所有可快照目录
hdfs lsSnapshottableDir
7、恢复快照
hdfs dfs -cp -ptopax 快照路径 恢复路径
8、删除快照snapshot
hdfs dfs -deleteSnapshot <path> <snapshotName>
快照操作实际案例
1、开启指定目录的快照
hdfs dfsadmin -allowSnapshot /config
2、对指定目录创建快照 注意:创建快照之前,先要允许该目录创建快照
hdfs dfs -createSnapshot /config
通过web浏览器访问快照 http://node1:50070/explorer.html#/config/.snapshot/
3、指定名称创建快照
hdfs dfs -createSnapshot /config mysnap1
4、重命名快照
hdfs dfs -renameSnapshot /config mysnap1 mysnap2
5、列出当前用户所有可以快照的目录
hdfs lsSnapshottableDir
6、恢复快照
hdfs dfs -cp -ptopax /config/.snapshot/mysnap1 /config3
7、删除快照
hdfs dfs -deleteSnapshot /config mysnap1
HDFS的Trash回收站功能
和Linux系统的回收站设计一样,HDFS会为 每一个用户 创建一个回收站目录: /user/用户名/.Trash/current ,每一个被用户通过Shell删除的文件/目录,在系统回收站中都一个周期,也就是当系统回收站中的文件/目录在一段时间之后没有被用户恢复的话,HDFS就会自动的把这个文件/目录彻底删除,之后,用户就永远也找不回这个文件/目录了。 如果检查点已经启用,会定期使用时间戳重命名Current目录。.Trash中的文件在用户可配置的时间延迟后被永久删除。回收站中的文件和目录可以简单地通过将它们移动到.Trash目录之外的位置来恢复。
配置
HDFS的回收站就像Windows操作系统中的回收站一样。它的目的是防止你无意中删除某些东西。你可以通过设置如下属性来启用此功能(默认是不开启的):
<property>
<name>fs.trash.interval</name>
<value>10080</value>
<description>Number of minutes after which the checkpoint gets deleted. If zero, the trash feature is disabled.</description>
</property>
属性 | 说明 |
---|
fs.trash.interval | 分钟数,回收站文件的存活时间, 当超过这个分钟数后文件会被删除。如果为零,回收站功能将被禁用。 |
恢复回收站数据
hadoop fs -mv /user/root/.Trash/current/hadoop-env.sh /config
注意点
回收站功能默认是禁用的。对于生产环境,建议启用回收站功能以避免意外的删除操作。启用回收站提供了从用户操作删除或用户意外删除中恢复数据的机会。但是为fs.trash.interval设置合适的值也是非常重要的,以使垃圾回收以你期望的方式运作。例如,如果你需要经常从HDFS上传和删除文件,则可能需要将fs.trash.interval设置为较小的值。
当启用垃圾回收并删除一些文件时,HDFS容量不会增加,因为文件并未真正删除。 回收站功能默认只适用于使用Hadoop shell删除的文件和目录。使用其他接口(例如WebHDFS或Java API)以编程的方式删除的文件或目录不会移动到回收站,即使已启用回收站,除非程序已经实现了对回收站功能的调用。
有时你可能想要在删除文件时临时禁用回收站,也就是删除的文件或目录不用放在回收站而直接删除,在这种情况下,可以使用-skipTrash选项运行rm命令。例如:
hadoop fs -rm -skipTrash /dir1/a.txt
HDFS的高可用机制
HDFS高可用介绍
在Hadoop 中,NameNode 所处的位置是非常重要的,整个HDFS文件系统的元数据信息都由NameNode 来管理,NameNode的可用性直接决定了Hadoop 的可用性,一旦NameNode进程不能工作了,就会影响整个集群的正常使用。
在典型的HA集群中,两台独立的机器被配置为NameNode。在工作集群中,NameNode机器中的一个处于Active状态,另一个处于Standby状态。Active NameNode负责群集中的所有客户端操作,而Standby充当从服务器。Standby机器保持足够的状态以提供快速故障切换(如果需要)。
组件介绍
Active NameNode 和 Standby NameNode :两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
主备切换控制器ZKFC( ZKFailoverController):ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换。
Zookeeper 集群 :为主备切换控制器提供主备选举支持。
元数据信息共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。主 NameNode 和备用NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。 原信息共享存储系统主要用于保存 EditLog,并不保存 FSImage 文件。FSImage 文件还是在 NameNode 的本地磁盘上。共享存储采用多个称为 JournalNode 的节点组成的 JournalNode 集群来存储 EditLog。每个 JournalNode 保存同样的 EditLog 副本。每次 NameNode 写 EditLog 的时候,除了向本地磁盘写入 EditLog 之外,也会并行地向 JournalNode 集群之中的每一个 JournalNode 发送写请求,只要大多数 的 JournalNode 节点返回成功就认为向 JournalNode 集群写入 EditLog 成功。如果有 2N+1 台 JournalNode,那么根据大多数的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。
DataNode 节点 :除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。
NameNode 的主备切换实现
NameNode 主备切换主要由 ZKFailoverController 、 HealthMonitor和 ActiveStandbyElector 这 3 个组件来协同实现:
ZKFailoverController 作为 NameNode 机器上一个独立的进程启动 (在 hdfs 启动脚本之中的进程名为 zkfc),启动的时候会创建 HealthMonitor 和 ActiveStandbyElector 这两个主要的内部组件,ZKFailoverController 在创建 HealthMonitor 和 ActiveStandbyElector 的同时,也会向 HealthMonitor 和 ActiveStandbyElector 注册相应的回调方法。
HealthMonitor 主要负责检测 NameNode 的健康状态,如果检测到 NameNode 的状态发生变化,会回调 ZKFailoverController 的相应方法进行自动的主备选举。
ActiveStandbyElector 主要负责完成自动的主备选举,内部封装了 Zookeeper 的处理逻辑,一旦 Zookeeper 主备选举完成,会回调 ZKFailoverController 的相应方法来进行 NameNode 的主备状态切换。
NameNode 实现主备切换的流程如图 2 所示,有以下几步:
1、 HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。 2、 HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。 3、 如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。 4、 ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。 5、 ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。 6、 ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。
Hadoop的联邦机制(Federation)
背景概述
单NameNode的架构使得HDFS在集群扩展性和性能上都有潜在的问题,当集群大到一定程度后,NameNode进程使用的内存可能会达到上百G,NameNode成为了性能的瓶颈。因而提出了namenode水平扩展方案-- Federation。 Federation中文意思为联邦,联盟,是NameNode的Federation,也就是会有多个NameNode。多个NameNode的情况意味着有多个namespace(命名空间),区别于HA模式下的多NameNode,它们是拥有着同一个namespace。现有的HDFS数据管理架构,如下图所示: 从上图中,我们可以很明显地看出现有的HDFS数据管理,数据存储2层分层的结构.也就是说,所有关于存储数据的信息和管理是放在NameNode这边,而真实数据的存储则是在各个DataNode下.而这些隶属于同一个NameNode所管理的数据都是在同一个命名空间下的。
一个namespace对应一个block pool。Block Pool是同一个namespace下的block的集合.当然这是我们最常见的单个namespace的情况,也就是一个NameNode管理集群中所有元数据信息的时候.如果我们遇到了之前提到的NameNode内存使用过高的问题,这时候怎么办?元数据空间依然还是在不断增大,一味调高NameNode的jvm大小绝对不是一个持久的办法.这时候就诞生了HDFS Federation的机制。
Federation架构设计
HDFS Federation是解决namenode内存瓶颈问题的水平横向扩展方案。
Federation意味着在集群中将会有多个namenode和namespace。这些namenode之间是联合的,也就是说,他们之间相互独立且不需要互相协调,各自分工,管理自己的区域。分布式的datanode被用作通用的数据块存储存储设备。每个datanode要向集群中所有的namenode注册,且周期性地向所有namenode发送心跳和块报告,并执行来自所有namenode的命令。 Federation一个典型的例子就是上面提到的NameNode内存过高问题,我们完全可以将上面部分大的文件目录移到另外一个NameNode上做管理.更重要的一点在于,这些NameNode是共享集群中所有的DataNode的,它们还是在同一个集群内的。 这时候在DataNode上就不仅仅存储一个Block Pool下的数据了,而是多个 。
概括起来: 多个NN共用一个集群里的存储资源,每个NN都可以单独对外提供服务。 每个NN都会定义一个存储池(block pool),有单独的id,每个DN都为所有存储池提供存储。 DN会按照存储池id向其对应的NN汇报块信息,同时,DN会向所有NN汇报本地存储可用资源情况。
HDFS Federation加高可用
HDFS Federation并没有完全解决单点故障问题。虽然namenode/namespace存在多个,但是从单个namenode/namespace看,仍然存在单点故障:如果某个namenode挂掉了,其管理的相应的文件便不可以访问。Federation中每个namenode仍然像之前HDFS上实现一样,配有一个secondary namenode,以便主namenode挂掉一下,用于还原元数据信息。
所以一般集群规模真的很大的时候,会采用HA+Federation的部署方案。也就是每个联合的namenodes都是ha的。
结束
HDFS的文章一共为2篇,2篇基本涵盖了HDFS的全部内容,HDFS的内容到这里就结束了。
|