hdfs 中元数据 fsimage,edits详解

前言

我们知道,namenode作为hdfs的元数据管理节点,其将所有的元数据都存储在fsimage中,本文结合实际目录文件,了解namenode的元数据到底是什么

fsimage元数据存储在哪?

namenode的image存储目录在hdfs-site.xml中进行配置,配置参数为

1
2
dfs.namenode.name.dir
默认值: file://${hadoop.tmp.dir}/dfs/name

其中hadoop.tmp.dir的配置在core-site.xml中进行配置,默认值为

1
/tmp/hadoop-${user.name}

也就是说如果你不就想配置,namenode的默认目录为

1
/tmp/hadoop-${user.name}/dfs/name

而seconarynamneode,用于做checkpoint合并image和editslog,他的工作配置目录为

1
2
dfs.namenode.checkpoint.dir
默认值: file://${hadoop.tmp.dir}/dfs/namesecondary

这些对应的配置功能可以在官方默认配置文档中找到

元数据文件有哪些?

进入到fsimage目录下,通过ls -l命令查看,如下图所示

可以看到,文件分为以下6类

  1. edits_0000xxxx-0000xxxx
    此类文件为已完结历史edits日志文件,这类文件的命名规则为edits_19位txid,未满19位的txid用0补齐
  2. edits_inprogress_0000xxxx
    该文件为当前正在写入的edits日志文件,规则和edits类似,只是中间多了ingrogress表示正在写入
  3. fsimage_0000xxx
    该文件为镜像文件,命名规则为fsimage_19位txid,其中txid表示该镜像合并到的最新edits日志。
    镜像文件一般为2个。
  4. fsiamge_000xxx.md5
    该文件为镜像文件对应的md5码,用于校验镜像文件是否一致。
  5. seen_txid
    该文件存储了最新的txid,新的edits日志文件命名都在此txid上+1
  6. VERSION
    该文件存储的是namenode的一些版本信息

元数据的文件内容长什么样?

日志文件edits_0000xxxx-0000xxxx

直接通过cat或vi命令查看日志文件的话,会发现edits文件有一堆乱码

想要查看edits文件,需要使用到 hdfs oev命令,该命令为hadoop官方提供的解析工具

常用的一个命令为

1
2
3
hdfs oev -i edits_0000000000000157832-0000000000000158267 -o test_edits.xml
# -i 为输入edits文件地址
# -o 为输出的xml地址

此时,我们再来看已经被解析为xml的test_edits.xml文件,就可以看到如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EDITS>
<EDITS_VERSION>-66</EDITS_VERSION>
<RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>157832</TXID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_MKDIR</OPCODE>
<DATA>
<TXID>157833</TXID>
<LENGTH>0</LENGTH>
<INODEID>42861</INODEID>
<PATH>/tmp/hive/hdfs/76876549-32f3-4f95-90e4-54e8846432d4</PATH>
<TIMESTAMP>1663027209019</TIMESTAMP>
<PERMISSION_STATUS>
<USERNAME>hdfs</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>448</MODE>
</PERMISSION_STATUS>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_MKDIR</OPCODE>
<DATA>
<TXID>157834</TXID>
<LENGTH>0</LENGTH>
<INODEID>42862</INODEID>
<PATH>/tmp/hive/hdfs/76876549-32f3-4f95-90e4-54e8846432d4/_tmp_space.db</PATH>
<TIMESTAMP>1663027209046</TIMESTAMP>
<PERMISSION_STATUS>
<USERNAME>hdfs</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>448</MODE>
</PERMISSION_STATUS>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_DELETE</OPCODE>
<DATA>
<TXID>157835</TXID>
<LENGTH>0</LENGTH>
<PATH>/user/hive/warehouse/stock.db/finance_indicator</PATH>
<TIMESTAMP>1663027213944</TIMESTAMP>
<RPC_CLIENTID>fa9f4009-c253-4109-a73e-6dfae064020f</RPC_CLIENTID>
<RPC_CALLID>14</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_MKDIR</OPCODE>
<DATA>
<TXID>157836</TXID>
<LENGTH>0</LENGTH>
<INODEID>42863</INODEID>
<PATH>/user/hive/warehouse/stock.db/finance_indicator</PATH>
<TIMESTAMP>1663027213948</TIMESTAMP>
<PERMISSION_STATUS>
<USERNAME>hdfs</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>493</MODE>
</PERMISSION_STATUS>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_ACL</OPCODE>
<DATA>
<TXID>157837</TXID>
<SRC>/user/hive/warehouse/stock.db/finance_indicator</SRC>
<ENTRY>
<SCOPE>ACCESS</SCOPE>
<TYPE>USER</TYPE>
<PERM>rwx</PERM>
</ENTRY>
<ENTRY>
<SCOPE>ACCESS</SCOPE>
<TYPE>GROUP</TYPE>
<PERM>r-x</PERM>
</ENTRY>
<ENTRY>
<SCOPE>ACCESS</SCOPE>
<TYPE>OTHER</TYPE>
<PERM>r-x</PERM>
</ENTRY>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_DELETE</OPCODE>
<DATA>
<TXID>157838</TXID>
<LENGTH>0</LENGTH>
<PATH>/user/hive/warehouse/stock.db/stock_price_none</PATH>
<TIMESTAMP>1663027214022</TIMESTAMP>
<RPC_CLIENTID>fa9f4009-c253-4109-a73e-6dfae064020f</RPC_CLIENTID>
<RPC_CALLID>22</RPC_CALLID>
</DATA>
</RECORD>

可以看到,edits日志是由一条一条record组成的,record的oprecode一共有53种,具体可以查看org.apache.hadoop.hdfs.server.namenode.FSEditLogOpCodes 这个枚举类,这里就不再展开了

具体的操作内容,则可以查看 org.apache.hadoop.hdfs.server.namenode.FSEditLogOp,这个类里的静态子类封装了edits的各种操作抽象,xml种对应的属性在里面都可以找到,这里也不再展开。

edits_inprogress_0000xxxx

文件内容同 日志文件edits_0000xxxx-0000xxxx

fsimage_0000xxx

直接通过cat或vi命令查看image镜像文件的话,会发现image文件有一堆乱码

想要查看image文件,需要使用到 hdfs oiv命令,该命令为hadoop官方提供的镜像解析工具

常用的一个命令为

1
2
3
4
hdfs oiv -i fsimage_0000000000000161098 -o test_image.xml -p XML
# -i 为输入image文件地址
# -o 为输出的xml地址
# -p 表示使用什么格式进行处理

解析结束后,我们再来看已经被解析为xml的test_image.xml文件,就可以看到如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<?xml version="1.0"?>
<fsimage>
<version>
<layoutVersion>-66</layoutVersion>
<onDiskVersion>1</onDiskVersion>
<oivRevision>a3b9c37a397ad4188041dd80621bdeefc46885f2</oivRevision>
</version>
<NameSection>
<namespaceId>1614349331</namespaceId>
<genstampV1>1000</genstampV1>
<genstampV2>13399</genstampV2>
<genstampV1Limit>0</genstampV1Limit>
<lastAllocatedBlockId>1073754220</lastAllocatedBlockId>
<txid>161098</txid>
</NameSection>
<ErasureCodingSection>
<erasureCodingPolicy>
<policyId>1</policyId>
<policyName>RS-6-3-1024k</policyName>
<cellSize>1048576</cellSize>
<policyState>DISABLED</policyState>
<ecSchema>
<codecName>rs</codecName>
<dataUnits>6</dataUnits>
<parityUnits>3</parityUnits>
</ecSchema>
</erasureCodingPolicy>
<erasureCodingPolicy>
<policyId>2</policyId>
<policyName>RS-3-2-1024k</policyName>
<cellSize>1048576</cellSize>
<policyState>DISABLED</policyState>
<ecSchema>
<codecName>rs</codecName>
<dataUnits>3</dataUnits>
<parityUnits>2</parityUnits>
</ecSchema>
</erasureCodingPolicy>
<erasureCodingPolicy>
<policyId>3</policyId>
<policyName>RS-LEGACY-6-3-1024k</policyName>
<cellSize>1048576</cellSize>
<policyState>DISABLED</policyState>
<ecSchema>
<codecName>rs-legacy</codecName>
<dataUnits>6</dataUnits>
<parityUnits>3</parityUnits>
</ecSchema>
</erasureCodingPolicy>
<erasureCodingPolicy>
<policyId>4</policyId>
<policyName>XOR-2-1-1024k</policyName>
<cellSize>1048576</cellSize>
<policyState>DISABLED</policyState>
<ecSchema>
<codecName>xor</codecName>
<dataUnits>2</dataUnits>
<parityUnits>1</parityUnits>
</ecSchema>
</erasureCodingPolicy>
<erasureCodingPolicy>
<policyId>5</policyId>
<policyName>RS-10-4-1024k</policyName>
<cellSize>1048576</cellSize>
<policyState>DISABLED</policyState>
<ecSchema>
<codecName>rs</codecName>
<dataUnits>10</dataUnits>
<parityUnits>4</parityUnits>
</ecSchema>
</erasureCodingPolicy>
</ErasureCodingSection>
<INodeSection>
<lastInodeId>43596</lastInodeId>
<numInodes>1572</numInodes>
<inode>
<id>16385</id>
<type>DIRECTORY</type>
<name></name>
<mtime>1659683329779</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>9223372036854775807</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16386</id>
<type>DIRECTORY</type>
<name>tmp</name>
<mtime>1659770965040</mtime>
<permission>hdfs:supergroup:0733</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16387</id>
<type>DIRECTORY</type>
<name>hive</name>
<mtime>1659772693233</mtime>
<permission>hdfs:supergroup:0733</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16388</id>
<type>DIRECTORY</type>
<name>hdfs</name>
<mtime>1663029189271</mtime>
<permission>hdfs:supergroup:0700</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16391</id>
<type>DIRECTORY</type>
<name>hive</name>
<mtime>1662261600810</mtime>
<permission>hive:supergroup:0700</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16396</id>
<type>DIRECTORY</type>
<name>user</name>
<mtime>1659683329779</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16397</id>
<type>DIRECTORY</type>
<name>hive</name>
<mtime>1659683329779</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16398</id>
<type>DIRECTORY</type>
<name>warehouse</name>
<mtime>1660102421896</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16399</id>
<type>DIRECTORY</type>
<name>stock.db</name>
<mtime>1663029031404</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16405</id>
<type>DIRECTORY</type>
<name>stk_balance_sheet</name>
<mtime>1661338700499</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16495</id>
<type>DIRECTORY</type>
<name>valuation__7c02ecf9_3e09_44c0_8121_7eb3e7c1d079</name>
<mtime>1660718214011</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16646</id>
<type>DIRECTORY</type>
<name>valuation__4ef5e657_b1b9_4dfb_bb2f_d04e25a4902a</name>
<mtime>1660718214009</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16650</id>
<type>DIRECTORY</type>
<name>valuation__940421e3_2ba0_4c20_b8d3_e01066c21156</name>
<mtime>1660718214012</mtime>
<permission>hdfs:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16678</id>
<type>DIRECTORY</type>
<name>46d8d97e-87df-4dff-baa4-c83024cfbce5</name>
<mtime>1659770965946</mtime>
<permission>hdfs:supergroup:0700</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16679</id>
<type>DIRECTORY</type>
<name>_tmp_space.db</name>
<mtime>1659770910781</mtime>
<permission>hdfs:supergroup:0700</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16743</id>
<type>DIRECTORY</type>
<name>hadoop-yarn</name>
<mtime>1659770965040</mtime>
<permission>hdfs:supergroup:0700</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>32524</id>
<type>FILE</type>
<name>job_1646050356665_0363.summary</name>
<replication>1</replication>
<mtime>1661397832374</mtime>
<atime>1661397831960</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>hdfs:supergroup:0770</permission>
<blocks>
<block>
<id>1073747785</id>
<genstamp>6961</genstamp>
<numBytes>482</numBytes>
</block>
</blocks>
<storagePolicyId>0</storagePolicyId>
</inode>

可以看到,image的xml有一下几个特征

  1. 总的被fsimage语句块包围

  2. 里面子的有

    • version
    • NameSection
    • ErasureCodingSection
    • INodeSection
  3. version描述的一些版本信息

    1
    2
    3
    4
    5
    <version>
    <layoutVersion>-66</layoutVersion>
    <onDiskVersion>1</onDiskVersion>
    <oivRevision>a3b9c37a397ad4188041dd80621bdeefc46885f2</oivRevision>
    </version>
  4. NameSection 描述的是命名空间的一些信息

    1
    2
    3
    4
    5
    6
    7
    8
       <NameSection>
    <namespaceId>1614349331</namespaceId>
    <genstampV1>1000</genstampV1>
    <genstampV2>13399</genstampV2>
    <genstampV1Limit>0</genstampV1Limit>
    <lastAllocatedBlockId>1073754220</lastAllocatedBlockId>
    <txid>161098</txid>
    </NameSection>
  5. ErasureCodingSection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <ErasureCodingSection>
    <erasureCodingPolicy>
    <policyId>1</policyId>
    <policyName>RS-6-3-1024k</policyName>
    <cellSize>1048576</cellSize>
    <policyState>DISABLED</policyState>
    <ecSchema>
    <codecName>rs</codecName>
    <dataUnits>6</dataUnits>
    <parityUnits>3</parityUnits>
    </ecSchema>
    </erasureCodingPolicy>
    <erasureCodingPolicy>
    <policyId>2</policyId>
    <policyName>RS-3-2-1024k</policyName>
    <cellSize>1048576</cellSize>
    <policyState>DISABLED</policyState>
    <ecSchema>
    <codecName>rs</codecName>
    <dataUnits>3</dataUnits>
    <parityUnits>2</parityUnits>
    </ecSchema>
    </erasureCodingPolicy>

    ErasureCodingSection 由一个一个erasureCodingPolicy片段组成,如果了解Erasure Code技术的话,就会明白这是一种纠删码,具体可以查看此篇纠删码Erasure Coding (分布式存储系统)
    常见的纠删码技术有阵列纠删码(Array Code: RAID5、RAID6等)、RS(Reed-Solomon)里德-所罗门类纠删码和LDPC(LowDensity Parity Check Code)低密度奇偶校验纠删码。 LDPC码目前主要用于通信、视频和音频编码等领域。

    看到image中的

    1
    <policyName>RS-3-2-1024k</policyName>

    就能猜测,hdfs中使用的是RS(Reed-Solomon)里德-所罗门类纠删码,感兴趣的可以自行搜索扩展。

  6. INodeSection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <INodeSection>
    <lastInodeId>43596</lastInodeId>
    <numInodes>1572</numInodes>
    <inode>
    <id>16385</id>
    <type>DIRECTORY</type>
    <name></name>
    <mtime>1659683329779</mtime>
    <permission>hdfs:supergroup:0755</permission>
    <nsquota>9223372036854775807</nsquota>
    <dsquota>-1</dsquota>
    </inode>
    <inode>
    <id>32524</id>
    <type>FILE</type>
    <name>job_1646050356665_0363.summary</name>
    <replication>1</replication>
    <mtime>1661397832374</mtime>
    <atime>1661397831960</atime>
    <preferredBlockSize>134217728</preferredBlockSize>
    <permission>hdfs:supergroup:0770</permission>
    <blocks>
    <block>
    <id>1073747785</id>
    <genstamp>6961</genstamp>
    <numBytes>482</numBytes>
    </block>
    </blocks>
    <storagePolicyId>0</storagePolicyId>
    </inode>

    INodeSection 由一段一段inode组成,是image中内容最大部分,除了上述的几个片段,image中剩下的内容全部都是inode。

    Node类在Namenode中代表了一个树状结构即Namespace,表示的是目录和文件的抽象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <inode>
    <id>16386</id>
    <type>DIRECTORY</type>
    <name>tmp</name>
    <mtime>1659770965040</mtime>
    <permission>hdfs:supergroup:0733</permission>
    <nsquota>-1</nsquota>
    <dsquota>-1</dsquota>
    </inode>

    以上述为例,表示的tmp目录的信息,具体可以hadoop的org.apache.hadoop.hdfs.server.namenode.INode

fsiamge_000xxx.md5

该文件为镜像文件对应的md5码,用于校验镜像文件是否一致。

seen_txid

该文件存储了最新的txid,新的edits日志文件命名都在此txid上+1

可以看到seen_txid里的文字为161099
而edists_inprogress的结尾也是161099,保存的是最新的txid事务id

VERSION

该文件存储的是namenode的一些版本信息

参考文章

Hadoop分布式文件系统:架构和设计
纠删码Erasure Coding (分布式存储系统)