一、HDFS体系组成概述

这是一个分布式文件系统,适用于于一次写入多次读取的场景。包含以下角色:

NameNode(nn):
存储文件的元数据,如文件名、文件目录结构,文件属性等,以及每个文件的块列表和块所在的DataNode等。以及响应客户端对hdfs的读写操作,如创建目录、上传文件等。还有保存读写日志。

DataNode(dn):
在本地文件系统中存储文件块数据,以及块数据的校验和

SecondaryNameNode(snn):
用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照,相当于对NameNode进行备份。

二、HDFS-NameNode

主要职责是管理hdfs的所有节点。 1、响应客户端对hdfs的请求,如增删改查。 2、管理和维护hdfs 的元数据信息以及日志(非log日志)

NameNode会在 core-site.xml中指定的hadoop.tmp.dir 的目录中 创建目录:dfs/name/ 。下面我们看看这个目录的结构。

[root@bigdata121 tmp]# tree dfs/name
dfs/name
├── current
│   ├── edits_0000000000000000001-0000000000000000002
│   ├── edits_0000000000000000003-0000000000000000004
│   ├── edits_0000000000000000005-0000000000000000006
│   ├── edits_0000000000000000007-0000000000000000008
│   ├── edits_0000000000000000009-0000000000000000009
│   ├── edits_0000000000000000010-0000000000000000011
│   ├── edits_0000000000000000012-0000000000000000013
│   ├── edits_0000000000000000014-0000000000000000015
│   ├── edits_0000000000000000016-0000000000000000017
│   ├── edits_0000000000000000018-0000000000000000019
│   ├── edits_0000000000000000020-0000000000000000021
│   ├── edits_0000000000000000022-0000000000000000024
│   ├── edits_0000000000000000025-0000000000000000026
│   ├── edits_inprogress_0000000000000000027
│   ├── fsimage_0000000000000000024
│   ├── fsimage_0000000000000000024.md5
│   ├── fsimage_0000000000000000026
│   ├── fsimage_0000000000000000026.md5
│   ├── seen_txid
│   └── VERSION
└── in_use.lock

各个文件目录的作用如下:

1、current

主要存放hdfs的存储的数据的元信息和日志。

(1)edits文件

是一个二进制文件,主要记录对hdfs的增删改操作的信息,类似于MySQL的二进制日志。其中 edits_inprogress_xxxxx 表示是最新的edits日志,是目前正在使用的。 可以使用命令查看 edits文件的内容:

//格式:hdfs oev -i 输入文件 -o 输出文件(xml格式)
[root@bigdata121 current]# hdfs oev -i edits_inprogress_0000000000000000038 -o /tmp/edits_inprogess.xml

[root@bigdata121 current]# cat /tmp/edits_inprogess.xml
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
  <EDITS_VERSION>-63</EDITS_VERSION>
  <RECORD>
    <OPCODE>OP_START_LOG_SEGMENT</OPCODE>   表示操作的类别,这里是表示日志开始记录
    <DATA>
      <TXID>38</TXID>  类似于操作的ID,是唯一的
    </DATA>
  </RECORD>
</EDITS>

<RECORD>
    <OPCODE>OP_ADD_BLOCK</OPCODE>     //像这个就表示上传文件的操作
    <DATA>
      <TXID>34</TXID>
      <PATH>/jdk-8u144-linux-x64.tar.gz._COPYING_</PATH>
      <BLOCK>
        <BLOCK_ID>1073741825</BLOCK_ID>
        <NUM_BYTES>134217728</NUM_BYTES>
        <GENSTAMP>1001</GENSTAMP>
      </BLOCK>
      <BLOCK>
        <BLOCK_ID>1073741826</BLOCK_ID>
        <NUM_BYTES>0</NUM_BYTES>
        <GENSTAMP>1002</GENSTAMP>
      </BLOCK>
      <RPC_CLIENTID></RPC_CLIENTID>
      <RPC_CALLID>-2</RPC_CALLID>
    </DATA>
  </RECORD>

(2)fsimage文件

hdfs中的数据的元数据文件。记录hdfs文件系统中各个数据块的信息,但并不是最新的。需要定时将edits文件合并到这里,才是最新的。可以使用命令查看 fsimage 文件的内容:

//格式 : hdfs oiv -p 输出格式 -i 输入文件 -o 输出文件
[root@bigdata121 current]# hdfs oiv -p XML -i fsimage_0000000000000000037 -o /tmp/fsimage37.xml

[root@bigdata121 current]# cat /tmp/fsimage37.xml
<?xml version="1.0"?>
<fsimage><version><layoutVersion>-63</layoutVersion><onDiskVersion>1</onDiskVersion><oivRevision>17e75c2a11685af3e043aa5e604dc831e5b14674</oivRevision></version>
<NameSection><namespaceId>1780930535</namespaceId><genstampV1>1000</genstampV1><genstampV2>1002</genstampV2><genstampV1Limit>0</genstampV1Limit><lastAllocatedBlockId>1073741826</lastAllocatedBlockId><txid>37</txid></NameSection>
<INodeSection><lastInodeId>16387</lastInodeId><numInodes>3</numInodes><inode><id>16385</id><type>DIRECTORY</type><name></name><mtime>1558145602785</mtime><permission>root:supergroup:0755</permission><nsquota>9223372036854775807</nsquota><dsquota>-1</dsquota></inode>
<inode><id>16386</id><type>DIRECTORY</type><name>input</name><mtime>1558105166840</mtime><permission>root:supergroup:0755</permission><nsquota>-1</nsquota><dsquota>-1</dsquota></inode>
<inode><id>16387</id><type>FILE</type><name>jdk-8u144-linux-x64.tar.gz</name><replication>2</replication><mtime>1558145602753</mtime><atime>1558145588521</atime><preferredBlockSize>134217728</preferredBlockSize><permission>root:supergroup:0644</permission><blocks><block><id>1073741825</id><genstamp>1001</genstamp><numBytes>134217728</numBytes></block>
<block><id>1073741826</id><genstamp>1002</genstamp><numBytes>51298114</numBytes></block>
</blocks>
<storagePolicyId>0</storagePolicyId></inode>
</INodeSection>
<INodeReferenceSection></INodeReferenceSection><SnapshotSection><snapshotCounter>0</snapshotCounter><numSnapshots>0</numSnapshots></SnapshotSection>
<INodeDirectorySection><directory><parent>16385</parent><child>16386</child><child>16387</child></directory>
</INodeDirectorySection>
<FileUnderConstructionSection></FileUnderConstructionSection>
<SecretManagerSection><currentId>0</currentId><tokenSequenceNumber>0</tokenSequenceNumber><numDelegationKeys>0</numDelegationKeys><numTokens>0</numTokens></SecretManagerSection><CacheManagerSection><nextDirectiveId>1</nextDirectiveId><numDirectives>0</numDirectives><numPools>0</numPools></CacheManagerSection>
</fsimage>

记录的信息更为详细。文件的元数据,如文件权限、时间戳等都有记录。

(3)seen_txid

txid是类似于事件id的概念,指的是每个操作的一个标识。这个文件中记录的是最新的txid的下一个,即当前最后一个txid是37,那么该文件记录的就是38.

(4)fsimage和edit文件命名方式的联系

edits文件: 我们可以看到edits文件都是 edits_00000xxx-000000xxx的方式命名的,其实意思就是表示该edits文件中记录了txid操作事件的范围。而 edit_inprogess_00000xxx 则表示当前所记录到的最新的txid事件。

fsimage文件: 以fsimage_000000xxx 的方式命名,表示的是该fsimage 文件记录到的最新的txid事件,请注意,因为fsimage是有条件触发之后,edits文件才会合并到fsimage的,否则不会合并。所以一般情况下,edits文件后面的txid肯定是比fsimage 大的。

2、in_use.lock

这个文件主要是对当前的node进行锁操作,避免当前机器同时启动多个namenode。只能启动一个namenode

三、HDFS-DataNode

HDFS的数据节点,主要就是存储数据的block文件的。会在指定的目录下创建一个 dfs/data 目录,看一下目录结构:

[root@bigdata122 dfs]# tree data
data
├── current
│   ├── BP-1130553825-192.168.50.121-1557922928723
│   │   ├── current
│   │   │   ├── finalized
│   │   │   │   └── subdir0
│   │   │   │       └── subdir0
│   │   │   │           ├── blk_1073741825
│   │   │   │           ├── blk_1073741825_1001.meta
│   │   │   │           ├── blk_1073741826
│   │   │   │           └── blk_1073741826_1002.meta
│   │   │   ├── rbw
│   │   │   └── VERSION
│   │   ├── scanner.cursor
│   │   └── tmp
│   └── VERSION
└── in_use.lock

在HDFS中,文件都是被分割成多个等大的数据块进行存储的。 hadoop 1.x 中数据块默认大小是 64M hadoop 2.x 中数据块默认大小是 128M hadoop 3.x 中不再采用多副本的模式存储,而是采用纠删码技术。 请见 https://www.cnblogs.com/basenet855x/p/7889994.html

在上面的目录中 blk_xxxxx 的文件其实就是blk文件,每个的大小为指定的块大小。

四、HDFS-SecondaryNameNode

用来监控HDFS状态的辅助后台程序,主要就是辅助 NameNode节点的工作(并非是 NameNode的备节点),其中主要工作就是 合并edits文件到fsimage文件。 1、根据 checkpoint的 时间间隔(默认3600秒)或者 edits文件到达64M 的触发条件,将edits文件合并fsimage。 2、edits合并到fsimage之后,edits文件可以清空了。