二、大数据组件之HDFS

HDFS全称是Hadoop Distributed File System, 也就是Hadoop分布式文件系统,是一种在硬件上运行的分布式文件系统。它与现有的分布式文件系统有许多相似之处。
但是,与其他分布式文件系统的区别很明显。HDFS具有高度的容错能力,旨在部署在低成本硬件上。HDFS提供对应用程序数据的高吞吐量访问,并且适用于具有大数据集的应用程序。
HDFS是一种适合大文件存储的分布式文件系统,不适合小文件存储,也就是几KB和几M的那些文件。

一、HDFS语法

接下来我们通过实操来加深对HDFS的理解,针对HDFS,我们可以在命令行中进行操作,操作起来和Linux差不多,但还是有一丝不同,语法为

hdfs dfs -<命令> hdfs://://

如果你未配置HDFS到系统环境变量,那么应该进入到HDFS的bin目录中运行HDFS命令。其实右半部分hdfs://xxx这块就是我们在core-site.xml中配置的fs.defaultFS的值,如果系统配置了HADOOP_HOME那么是不需要在写了,因为会自动读取

二、HDFS的基本操作

如果没有安装大数据平台的话,建议先去看我的上一篇CDH6.2大数据平台安装部署手册。接下来我们就来介绍一下HDFS中常见的一些命令操作,HDFS的命令很多,但是很多都用的不多,这里就不全部介绍了,只介绍一些常用的命令,其他的你们就自己去看 HDFS的文档 哈,我们通过hdfs dfs就可以带出后面的所有命令

[root@hadoop1 conf]# hdfs dfs
Usage: hadoop fs [generic options]
    [-appendToFile  ... ]
    [-cat [-ignoreCrc]  ...]
    [-checksum  ...]
    [-chgrp [-R] GROUP PATH...]
    [-chmod [-R]  PATH...]
    [-chown [-R] [OWNER][:[GROUP]] PATH...]
    [-copyFromLocal [-f] [-p] [-l] [-d] [-t ]  ... ]
    [-copyToLocal [-f] [-p] [-ignoreCrc] [-crc]  ... ]
    [-count [-q] [-h] [-v] [-t []] [-u] [-x] [-e]  ...]
    [-cp [-f] [-p | -p[topax]] [-d]  ... ]
    [-createSnapshot  []]
    [-deleteSnapshot  ]
    [-df [-h] [ ...]]
    [-du [-s] [-h] [-v] [-x]  ...]
    [-expunge]
    [-find  ...  ...]
    [-get [-f] [-p] [-ignoreCrc] [-crc]  ... ]
    [-getfacl [-R] ]
    [-getfattr [-R] {-n name | -d} [-e en] ]
    [-getmerge [-nl] [-skip-empty-file]  ]
    [-help [cmd ...]]
    [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [ ...]]
    [-mkdir [-p]  ...]
    [-moveFromLocal  ... ]
    [-moveToLocal  ]
    [-mv  ... ]
    [-put [-f] [-p] [-l] [-d]  ... ]
    [-renameSnapshot   ]
    [-rm [-f] [-r|-R] [-skipTrash] [-safely]  ...]
    [-rmdir [--ignore-fail-on-non-empty]  ...]
    [-setfacl [-R] [{-b|-k} {-m|-x } ]|[--set  ]]
    [-setfattr {-n name [-v value] | -x name} ]
    [-setrep [-R] [-w]   ...]
    [-stat [format]  ...]
    [-tail [-f] ]
    [-test -[defsz] ]
    [-text [-ignoreCrc]  ...]
    [-touch [-a] [-m] [-t TIMESTAMP ] [-c]  ...]
    [-touchz  ...]
    [-truncate [-w]   ...]
    [-usage [cmd ...]]

Generic options supported are:
-conf         specify an application configuration file
-D                define a value for a given property
-fs  specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
-jt   specify a ResourceManager
-files                 specify a comma-separated list of files to be copied to the map reduce cluster
-libjars                specify a comma-separated list of jar files to be included in the classpath
-archives           specify a comma-separated list of archives to be unarchived on the compute machines

The general command line syntax is:
command [genericOptions] [commandOptions]
  • -ls命令
    这个命令和Linux系统中的ls一样,查看目录下的所有内容
[root@hadoop1 conf]# hdfs dfs -ls /
Found 3 items
drwxr-xr-x   - hdfs supergroup          0 2020-12-03 17:24 /test
drwxrwxrwt   - hdfs supergroup          0 2020-12-02 15:59 /tmp
drwxr-xr-x   - hdfs supergroup          0 2020-12-02 15:58 /user

可以看到列出了在根目录下的所有内容,因为上一篇安装大数据平台的时候有生成目录,所以这里有内容

  • -mkdir [-p]
    创建文件夹
# 创建个/test2文件夹
[root@hadoop1 conf]# hdfs dfs -mkdir /test2
# 查看是否存在我们刚刚创建的目录
[root@hadoop1 conf]# hdfs dfs -ls /
Found 4 items
drwxr-xr-x   - hdfs supergroup          0 2020-12-03 17:24 /test
drwxr-xr-x   - hdfs supergroup          0 2020-12-07 10:27 /test2
drwxrwxrwt   - hdfs supergroup          0 2020-12-02 15:59 /tmp
drwxr-xr-x   - hdfs supergroup          0 2020-12-02 15:58 /user

如果需要递归创建文件夹,就在命令后加上-p参数

[root@hadoop1 conf]# hdfs dfs -mkdir -p /test3/test
[root@hadoop1 conf]# hdfs dfs -ls /test3
Found 1 items
drwxr-xr-x   - hdfs supergroup          0 2020-12-07 10:31 /test3/test
  • -put
    向HDFS中上传一个文件,我们先事先创建一个文本文件,然后上传到HDFS的根目录
[root@hadoop1 /]# hdfs dfs -put hello.txt /
[root@hadoop1 /]# hdfs dfs -ls /
Found 6 items
-rw-r--r--   3 hdfs supergroup          6 2020-12-07 10:34 /hello.txt
drwxr-xr-x   - hdfs supergroup          0 2020-12-03 17:24 /test
drwxr-xr-x   - hdfs supergroup          0 2020-12-07 10:27 /test2
drwxr-xr-x   - hdfs supergroup          0 2020-12-07 10:31 /test3
drwxrwxrwt   - hdfs supergroup          0 2020-12-02 15:59 /tmp
drwxr-xr-x   - hdfs supergroup          0 2020-12-02 15:58 /user
  • -cat
    查看文件中的内容
# 查看刚刚上传的文本内容
[root@hadoop1 /]# hdfs dfs -cat /hello.txt
hello
  • -get
    下载HDFS中的文件到本地
[root@hadoop1 /]# hdfs dfs -get /test .
image.png
  • -rm
    删除目录和文件
    删除文件
[root@hadoop1 /]# hdfs dfs -rm /hello.txt
20/12/07 11:12:30 INFO fs.TrashPolicyDefault: Moved: 'hdfs://hadoop1:8020/hello.txt' to trash at: hdfs://hadoop1:8020/user/hdfs/.Trash/Current/hello.txt

删除目录

[root@hadoop1 /]# hdfs dfs -rm -r /test2
20/12/07 11:13:34 INFO fs.TrashPolicyDefault: Moved: 'hdfs://hadoop1:8020/test2' to trash at: hdfs://hadoop1:8020/user/hdfs/.Trash/Current/test2

如果开启了回收策略,那么如果你想彻底删除,需要在命令后加上-skipTrash,这样就彻底删除了

[root@hadoop1 /]# hdfs dfs -rm -r -skipTrash /test
Deleted /test

三、Java操作HDFS

事先我们创建好一个Maven项目,然后引入Hadoop的依赖


    org.apache.hadoop
    hadoop-client
    3.2.0

然后编写代码

package com.gjing.projects.bigdata.hdfs;

import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;

/**
 * Java操作HDFS, 这里只举例了部分操作例子,其他的自己可以一一实现下哈
 *
 * @author Gjing
 **/
public class HdfsDemo {
    public static void main(String[] args) throws IOException {
        // 创建一个配置
        Configuration configuration = new Configuration();
        // 设置HDFS的地址
        configuration.set("fs.defaultFS","hdfs://hadoop1:8020");
        // 此处副本数最好设置和集群中的hdfs-site.xml中一致,否则可能会出现副本块不足的警告
        configuration.set("dfs.replication","3");
        // 获取HDFS的操作对象
        FileSystem fileSystem = FileSystem.get(configuration);

        // 1、创建目录
        boolean mkdirs = fileSystem.mkdirs(new Path("/test"));
        System.out.println("创建目录: " + mkdirs);

        // 2、创建文件并写入内容
        FSDataOutputStream outputStream = fileSystem.create(new Path("/test/hello.txt"));
        outputStream.writeUTF("hello world");
        outputStream.flush();
        outputStream.close();

        // 3、查看写入的内容
        FSDataInputStream inputStream = fileSystem.open(new Path("/test/hello.txt"));
        IOUtils.copy(inputStream, System.out);

        // 4、删除目录 并递归删除其下面的文件和目录
        boolean delete = fileSystem.delete(new Path("/test"), true);
        System.out.println("\n删除文件: " + delete);
    }
}

这时候尝试启动下发现会报一个权限异常

image.png

回想一下我们在刚搭建完大数据平台的时候,通过服务器去操作HDFS的时候,也报了权限异常,后来在环境变量中设置了Hadoop的执行用户得以解决,这里也同理,在代码第一行加入System.setProperty("HADOOP_USER_NAME", "hdfs");

/**
 * Java操作HDFS, 这里只举例了部分操作例子,其他的自己可以一一实现下哈
 *
 * @author Gjing
 **/
public class HdfsDemo {
    public static void main(String[] args) throws IOException {
        // 加入这行代码,设置执行用户,解决权限不足问题
        System.setProperty("HADOOP_USER_NAME", "hdfs");
        // 创建一个配置
        Configuration configuration = new Configuration();
        // 设置HDFS的地址
        configuration.set("fs.defaultFS","hdfs://hadoop1:8020");
        // 此处副本数最好设置和集群中的hdfs-site.xml中一致,否则可能会出现副本块不足的警告
        configuration.set("dfs.replication","3");
        // 获取HDFS的操作对象
        FileSystem fileSystem = FileSystem.get(configuration);

        // 1、创建目录
        boolean mkdirs = fileSystem.mkdirs(new Path("/test"));
        System.out.println("创建目录: " + mkdirs);

        // 2、创建文件并写入内容
        FSDataOutputStream outputStream = fileSystem.create(new Path("/test/hello.txt"));
        outputStream.writeUTF("hello world");
        outputStream.flush();
        outputStream.close();

        // 3、查看写入的内容
        FSDataInputStream inputStream = fileSystem.open(new Path("/test/hello.txt"));
        IOUtils.copy(inputStream, System.out);

        // 4、删除目录 并递归删除其下面的文件和目录
        boolean delete = fileSystem.delete(new Path("/test"), true);
        System.out.println("\n删除文件: " + delete);
    }
}

接下来可以看到执行成功了,控制台也输出了

image.png

四、HDFS架构体系

HDFS具有主/从体系结构。主节点称为NameNode,因为其节点上运行了NameNode进程,NameNode支持多个,目前我们集群中就配置了一个,在文章的末尾我们会介绍如何通过CM来搭建多主多从的HDFS集群。
从节点称为DataNode,节点中有启动DataNode进程。DataNode支持多个,目前集群中配了两个。
还有一个进程SecondaryNameNode,字面意思为第二个NameNode,但是作用和NameNode有点不同哈,下面会为大家介绍。接下来看看下面的这张图,这是HDFS官网的体系图

image.png

1、NameNode

NameNode是整个文件系统的管理节点,它主要维护整个文件系统的目录树、文件、目录的信息和每个文件对应的数据块列表,并且还负责接收用户的请求:

  • 目录树:就是我们通过-ls命令查看的目录结构
  • 文件、目录信息:文件的基本信息,像什么用户组、文件大小、修改时间等等
  • 数据块列表:文件太大会被切割为多个块,存储到不同机器上面,所以会记录有多少块,每一块的存储位置
  • 接收用户的请求:在我们通过命令行或者代码的时候都是需要先和NameNode通信的,其次才会开始去操作

接下来我们看看NameNode到底包含哪些文件:

  • fsimage
  • edits
  • seed_txid
  • VERSION

这些文件存储位置是通过hdfs-site.xml配置文件指定的,由于我们是通过CM来安装的,所以配置文件位置在/etc/hadoop/conf目录,进入到这个目录然后打开这个配置文件,查询dfs.namenode.name.dir这个配置,值就是我们要找的存储位置了

image.png

接下来我们进入到这个目录/dfs/nn,这时候通过ls查看可以发现一个current目录和in_use.lock文件,in_use.lock文件相当于是一把锁,如果没有的话才可以启动NameNode成功,否则启动失败,停止的时候会把这个锁去掉。接下来我们进入到current目录,里面有我们前面讲到的那四个文件了

image.png

可以看到fsimage文件有两个文件名相同的,有一个后缀为md5,这其实是用来做MD5校验的,为了保证传输过程中不出问题,相同的文件内容MD5是一样的,接下来我们来看看fsimage文件,我们先随意找到一个文件,然后格式化成xml,否则无法观看

[root@hadoop1 current]# hdfs oiv -p XML -i fsimage_0000000000000051391 -o fsimage51391.xml

然后将生成的fsimage51391.xml文件拉取到我们电脑上去看,这样会看的比较直观,下面就是这个文件的内容了


-6417ce7dcdb76fd7f700cd7749bbc6390f76ff2abae
710664213100095090107375033351391


1RS-6-3-1024k1048576DISABLED
rs63



2RS-3-2-1024k1048576DISABLED
rs32



3RS-LEGACY-6-3-1024k1048576DISABLED
rs-legacy63



4XOR-2-1-1024k1048576DISABLED
xor21



5RS-10-4-1024k1048576DISABLED
rs104




249181816385DIRECTORY1607330993617hdfs:supergroup:07559223372036854775807-1
16386DIRECTORYtmp1606895984184hdfs:supergroup:1777-1-1
16387DIRECTORYuser1607310750934hdfs:supergroup:0755-1-1
16388DIRECTORYhistory1606895969221mapred:hadoop:0777-1-1
16389DIRECTORYlogs1606895909065mapred:hadoop:1777-1-1
16390DIRECTORYyarn1606895922067hdfs:supergroup:0755-1-1
16391DIRECTORYmapreduce1606895922067hdfs:supergroup:0755-1-1
16392DIRECTORYmr-framework1606895944188yarn:hadoop:0775-1-1
16393FILE3.0.0-cdh6.2.1-mr-framework.tar.gz216068959582791606895944188134217728yarn:hadoop:064410737418251001134217728
1073741826100298472263

0
16394DIRECTORYdone1606895969160mapred:hadoop:0771-1-1
16395DIRECTORYdone_intermediate1606895969221mapred:hadoop:1777-1-1
16396DIRECTORY.cloudera_health_monitoring_canary_files1607409437182hdfs:supergroup:0000-1-1
23264DIRECTORYhdfs1607310750935hdfs:supergroup:0700-1-1
23265DIRECTORY.Trash1607400000070hdfs:supergroup:0700-1-1
23611DIRECTORYtest1607332229117hdfs:supergroup:0755-1-1
23617DIRECTORY2012071700001607331241353hdfs:supergroup:0700-1-1
23618DIRECTORYtest1607331295270hdfs:supergroup:0700-1-1
23640FILEhello.txt316073358310561607332229117134217728hdfs:supergroup:06440

00
16385236111638616387
163861639616389
16387232641638816390
163881639416395
1639016391
1639116392
1639216393
2326423265
2326523617
2361123640
2361723618


0000100

最外层可以看到是fsimage标签,然后往下看,可以看到inode标签,每个inode表示的是hdfs中的一个目录或者文件,例如:

image.png

那么inode标签内的那些子标签是啥意思呢

标签 描述
id 唯一编号
type 文件类型
name 文件名称
replication 副本数量
mtime 修改时间
atime 访问时间
preferredBlockSize 推荐每一个数据块的大小
permission 权限信息
blocks 包含多少数据块
block 内部的id表示为块的id,genstamp是唯一编号,numBytes表示块的实际大小,storagePolicyId表示存储策略

从这个表格里我们可以看出,这个文件存储了hdfs里最核心的数据。
那么edits文件里面存储了哪些东西呢,其实,可以把它看成是一个事务文件,为啥捏?举个栗子,加入你要上传个几G的文件,那么hdfs会把他拆成好几个块,那么edits文件会记录每个块上传的状态,只有上传成功了edits文件才会记录这个文件上传成功了,这时候就能通过hdfs dfs -ls <目录>查看到这个文件了。

接下来我们来查看下edits文件的内容,和查看fsimage文件一样,先转成xml,在拉到本机查看

[root@hadoop1 current]# hdfs oev -i edits_0000000000000050674-0000000000000051035 -o edits.xml

这里我们就不展示所有内容了, 你们可以自行查看哈,我们通过查看文件可以看到里面有很多的record标签,每一个record都是代表不同的操作,例如OPP_ADD、OPP_DELETE等等,都能直观理解哈,这里就不讲解了,这里面的record都有一个事务idtxid,事务id是连续的,上传一个文件会生成很多record,这个我们都看不了。

通过介绍上面两个文件,我们发现两个文件不一致,那么是内部是如何将fsimage文件和edits文件保持一致的,其实是定期合并的哈,hdfs内部会对edits文件进行精简,至于如何精简的,有兴趣的同学就去自己看看框架源码了解其原理哈,这里就不多说了哈。

那么是什么进程在执行这个操作呢,是NameNode吗,显然不是,不然它还不得累死啊,又要接收用户请求又要处理合并。这时候就要祭出我们之前提到的第二个NameNode了,那就是SecondaryNamenode,他只做一件事,那就是合并edits文件到fsimage文件中,实际工作中部署时最好部署在单独的节点上。

current目录下还有一个seen_txid文件,这里面存的是hdfs format之后edits_*文件的尾数,
NameNode重启的时候会从头开始读edits_000000000000001到seen_txid的数字,如果根据对应的seen_txid找不到对应的文件,那么就会启动失败以保护数据一致性。

最后一个文件VERSION存的就是集群的版本信息了

2、SecondaryNameNode

该进程主要就是将edits文件合并到fsimage文件中,这个操作称为checkpoint,下面是整个checkpoint的流程图

image.png

3、DataNode

DataNode是提供具体文件存储的服务,也称为数据节点。对于DataNode有两个概念要了解,一个是block一个是replication。Hdfs会按照固定的大小和顺序对文件进行切割和编号,切割完后的每一块就是一个blockblock默认大小是128M,Block块是HDFS的读写数据的基本单位,无论什么数据,对于HDFS来说都是字节。

由于我们是CM来安装Hadoop集群的,我们可以直接在CM的管理界面点击HDFS组件进入管理界面

image.png

然后点击配置标签,在搜索框输入dfs.datanode.data.dir
image.png

可以看到数据存储目录在/data/dn目录,我们就随便选择一个数据节点登录进去看看,这里我们就登录hadoop2节点,然后进入到这个目录

image.png

我们现在hadoop1节点手动put一个文件到HDFS中,然后通过HDFS的web-ui,访问地址为:http://hadoop1:9870,查看下刚刚手动上传的文件存储信息

image.png

找到我们刚手动上传的文件,并点击,可以看到如下信息,这时候我们去数据节点上看看


image.png

我们一路往下进入,最终到达这个目录,BP这一段就是我们上图中红框圈出来的

image.png

这时候我们通过ll命令查看下目录下的目录,然后根据我们上传时间的找到对应的目录,并进入

image.png

然后可以看到里面有很多文件,这里面就有Block块了,这里.meta后缀的文件也是做校验用的,我们尝试打印出来看看

image.png

输出的就是我们这个block块中的内容了,这个block块中的内容可能只是文件中的一小部分,因为文件一旦超过了设置的block块大小就会切割成多个block块,如果没有默认的大,那么就只是一个block,在HDFS中,如果你的文件大小没有block默认大小大, 那么是不会占用整个block块的存储空间的。

block块的存储位置只有DataNode自己知道,在启动集群的时候,DataNode会扫描自己节点里面的所有block块信息,然后上传个NameNode节点,所以数据越多,启动越慢,还有个注意的地方,那就是NameNode启动时候会将所有文件的元信息加载到内存中,每个元数据信息都会占用150字节,所以这也是为啥不适合存储小文件,会造成内存满了,但是文件整体的大小很小。

最后,我们在/dfs/dn目录中也发现了一个VERSION文件,这个跟我们前面介绍的NameNode存储目录里的VERSION文件是有一些相似的地方的,我们分别打开DataNode和NameNode的VERSION文件

  • NameNode


    image.png
  • DataNode
    image.png

    可以看到两个clusterId是一样的,所以NameNode是不能随意格式化的,会造成两边对不上,所以,如果你们是通过hadoop官方方式安装的话,在不得不重新格式化的时候,一定要删除干净储存目录下的内容。

五、HDFS回收站

我们在上文有提到过如果在删除的时候,没有指定-skipTrash参数,那么是不会直接删除的,会移动到回收站,回收站里面有个日期,如果超过这个日期没有被恢复的话,就会被自动永远删除了,通过CM安装集群的话,是会默认开启的,时间为1分钟,我们可以手动去的调整,参数在core-site.xml文件中,当然你们也可以在CM平台上修改

  
    fs.trash.interval
    1
  

修改配置文件一定要同步到其他节点,然后在重新启动集群才会生效

六、安全模式

HDFS在每次启动的时候,都会去检查集群中文件信息是否完整,副本是否丢失等,所以这段时间内是不允许用户对HDFS集群进行操作的,这时候就需要我们耐心的等待一下啦!!我们可以在HDFS的web-ui查看当前状态

image.png

当然也可以通过命令行查看

[root@hadoop1 /]# hdfs dfsadmin -safemode get
Safe mode is OFF

如果你猴急了不想等了,你也可以强制退出,当然不建议你这么做

[root@hadoop1 /]# hdfs dfsadmin -safemode leave

七、HDFS升级高可用

HDFS高可用其实就是部署多个NameNode节点,这样就不会担心NameNode挂了导致整个集群瘫痪,接下来就给大家介绍如果通过CM来将之前安装的单节点HDFS升级为HA

1、安装Zookeeper

我们来到CM的首页,点击添加服务,并选择Zookeeper

image.png

找到Zookeeper并点击继续
image.png

来到了Zookeeper Server的角色分配,这里CM会根据服务器配置自动给你推荐机器,当然你也可以根据自己的计划选择机器,我们点击那个框框,然后自定义分配角色,这里我们就将集群中的三台机子都作为Zookeeper的节点
image.png

选择完毕后确定并继续下一步,这里来到了数据目录配置,这里我们就随便设置一个目录,如果是生产环境你们一定好好合理规划哦
image.png

点击继续,我们就开始安装啦,这里需要耐心的等待一下
image.png

好了,我们安装好了
image.png

接下来我们点击继续,这是个汇总页了,我们看完描述信息就点击完成
image.png

回到主页,我们就看到多出了一个zookeeper服务了
image.png

2、启用HA

点击主页的HDFS服务,进入到操作界面,然后选中启用HA

image.png

这里需要填写namespace名称,有默认的,也可以自己指定。这个namespace就是后面你们要是想通过代码或者命令连接hdfs的地址哦,hdfs:///[目录]。这里我们就使用默认的,然后下一步
image.png

这里是分配角色了,由于我们只有三个节点,因此就只能找个数据节点作为NameNode了,三台都选中为JournalNode,然后继续
image.png

这里也是填数据存储地址的,要根据生产环境合理考虑哦
image.png

点击继续后我们就来到了安装界面了,耐心等待启用成功
image.png

启动成功了,效果是这样的
image.png

然后我们点击继续并完成即可,这时候我们在进入到HDFS的操作界面,点击实例,就可以看到HA后的HDFS所有实例了
image.png


本手册到这就结束啦,篇幅过长,如果大家发现有啥问题可以在留言哦

你可能感兴趣的:(二、大数据组件之HDFS)