概念

Namespace
目录、文件、块合在一起,起了个名称Namespace(命名空间)
拥有单独的目录(blockpool)

BlockMap

除Namespace外,NameNode还管理非常重要的元数据BlocksMap,描述数据块Block与DataNode节点之间的对应关系。NameNode并没有对这部分元数据同样操作持久化,原因是每个DataNode已经持有属于自己管理的Block集合,将所有DataNode的Block集合汇总后即可构造出完整BlocksMap。
BlockMap由三元组构成。每个文件块block有几个副本,就有几个三元组:(DataNodeID, PreBlock, NextBlock)

NameNode硬盘文件信息

目录结构

  • current
    • VERSION
    • edits_${start_txid}-${end_txid}
    • editsinprogress${start_txid}
    • fsimage_${end_txid}
    • fsimage_${end_txid}.md5
  • in_user.lock

edit logs、fsimage、seen_txid、VERSION、in_use.lock

主要文件

edit logs编辑日志文件

edit logs - 它是在NameNode启动后,对文件系统的改动序列
每条记录都是一个事务。有事务ID作为编号。

分段

Editlog被切割成多段(Segment)。
正在写入的Segment叫inprogess状态。其文件名形如 editsinprogress${starttxid},其中${start_txid} 表示这个 segment 的起始事务 id。
已经写入完成的 EditLog Segment 处于 finalized 状态,其文件名形如 edits
${start_txid}-${end_txid}
editlog和fsimage存在磁盘目录${dfs.namenode.name.dir}/current

操作

OP_START_LOG_SEGMENT
OP_ADD
OP_ALLOCATE_BLOCK_ID
OP_SET_GENSTAMP_V2
OP_ADD_BLOCK
OP_CLOSE
OP_RENAME_OLD

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <EDITS>
  3. <EDITS_VERSION>-63</EDITS_VERSION>
  4. <RECORD>
  5. <OPCODE>OP_START_LOG_SEGMENT</OPCODE>
  6. <DATA>
  7. <TXID>6</TXID>
  8. </DATA>
  9. </RECORD>
  10. <RECORD>
  11. <OPCODE>OP_ADD</OPCODE>
  12. <DATA>
  13. <TXID>7</TXID>
  14. <LENGTH>0</LENGTH>
  15. <INODEID>16386</INODEID>
  16. <PATH>/wc.txt._COPYING_</PATH>
  17. <REPLICATION>3</REPLICATION>
  18. <MTIME>1574260053772</MTIME>
  19. <ATIME>1574260053772</ATIME>
  20. <BLOCKSIZE>134217728</BLOCKSIZE>
  21. <CLIENT_NAME>DFSClient_NONMAPREDUCE_-929106461_1</CLIENT_NAME>
  22. <CLIENT_MACHINE>192.168.153.101</CLIENT_MACHINE>
  23. <OVERWRITE>true</OVERWRITE>
  24. <PERMISSION_STATUS>
  25. <USERNAME>root</USERNAME>
  26. <GROUPNAME>supergroup</GROUPNAME>
  27. <MODE>420</MODE>
  28. </PERMISSION_STATUS>
  29. <RPC_CLIENTID>48f6f0ee-0e35-4b0f-86b1-b2df41b2c4cd</RPC_CLIENTID>
  30. <RPC_CALLID>3</RPC_CALLID>
  31. </DATA>
  32. </RECORD>
  33. <RECORD>
  34. <OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE>
  35. <DATA>
  36. <TXID>8</TXID>
  37. <BLOCK_ID>1073741825</BLOCK_ID>
  38. </DATA>
  39. </RECORD>
  40. <RECORD>
  41. <OPCODE>OP_SET_GENSTAMP_V2</OPCODE>
  42. <DATA>
  43. <TXID>9</TXID>
  44. <GENSTAMPV2>1001</GENSTAMPV2>
  45. </DATA>
  46. </RECORD>
  47. <RECORD>
  48. <OPCODE>OP_ADD_BLOCK</OPCODE>
  49. <DATA>
  50. <TXID>10</TXID>
  51. <PATH>/wc.txt._COPYING_</PATH>
  52. <BLOCK>
  53. <BLOCK_ID>1073741825</BLOCK_ID>
  54. <NUM_BYTES>0</NUM_BYTES>
  55. <GENSTAMP>1001</GENSTAMP>
  56. </BLOCK>
  57. <RPC_CLIENTID></RPC_CLIENTID>
  58. <RPC_CALLID>-2</RPC_CALLID>
  59. </DATA>
  60. </RECORD>
  61. <RECORD>
  62. <OPCODE>OP_CLOSE</OPCODE>
  63. <DATA>
  64. <TXID>11</TXID>
  65. <LENGTH>0</LENGTH>
  66. <INODEID>0</INODEID>
  67. <PATH>/wc.txt._COPYING_</PATH>
  68. <REPLICATION>3</REPLICATION>
  69. <MTIME>1574260055275</MTIME>
  70. <ATIME>1574260053772</ATIME>
  71. <BLOCKSIZE>134217728</BLOCKSIZE>
  72. <CLIENT_NAME></CLIENT_NAME>
  73. <CLIENT_MACHINE></CLIENT_MACHINE>
  74. <OVERWRITE>false</OVERWRITE>
  75. <BLOCK>
  76. <BLOCK_ID>1073741825</BLOCK_ID>
  77. <NUM_BYTES>75</NUM_BYTES>
  78. <GENSTAMP>1001</GENSTAMP>
  79. </BLOCK>
  80. <PERMISSION_STATUS>
  81. <USERNAME>root</USERNAME>
  82. <GROUPNAME>supergroup</GROUPNAME>
  83. <MODE>420</MODE>
  84. </PERMISSION_STATUS>
  85. </DATA>
  86. </RECORD>
  87. <RECORD>
  88. <OPCODE>OP_RENAME_OLD</OPCODE>
  89. <DATA>
  90. <TXID>12</TXID>
  91. <LENGTH>0</LENGTH>
  92. <SRC>/wc.txt._COPYING_</SRC>
  93. <DST>/wc.txt</DST>
  94. <TIMESTAMP>1574260055288</TIMESTAMP>
  95. <RPC_CLIENTID>48f6f0ee-0e35-4b0f-86b1-b2df41b2c4cd</RPC_CLIENTID>
  96. <RPC_CALLID>9</RPC_CALLID>
  97. </DATA>
  98. </RECORD>
  99. <RECORD>
  100. <OPCODE>OP_END_LOG_SEGMENT</OPCODE>
  101. <DATA>
  102. <TXID>13</TXID>
  103. </DATA>
  104. </RECORD>
  105. </EDITS>

fsimage命名空间镜像文件

它是在NameNode启动时对整个文件系统的快照。定期对内存中文件系统镜像checkpoint生成,格式fsimage_${end_txid}。
image.png
fsimage 2.4版本之后,采用protobuffer描述。
源码链接如下
https://github.com/apache/hadoop/blob/branch-2.10.0/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/fsimage.proto
seen_txid
存当前transaction_id,格式化会变成0。

in_use.lock

防止单台机器多NN进程冲突。
VERSION
存版本。

元数据恢复

fsimage和editlog合并到一起恢复元数据。fsimage加载到内存,再把fsimage结束事务后的事务从Editlog中读取。

块所在DataNode信息不再本地磁盘,每次启动根据DataNode上报。

NameNode元数据存在内存中,故受JVM heap size限制。每个Block占150Byte元数据。

NodeNode的block管理

与yarn不同,hdfs并没有直接用状态机来管理block,而是将不同状态的block存储在不同的缓冲区中,状态迁移则对应数据块在不同缓冲区中的移动。包括BlockManager#blocksMap,namenode上的数据块状态共涉及以下几种缓冲区:

  • 正在写入的数据块:通过LeaseManager扫描INodeFile,BlockInfo#isComplete()返回false即为正在写入的数据块(不常用)
  • 存储数据块的元信息,可以认为存储已完成等所有状态的数据块:BlockManager#blocksMap,BlockInfo#isComplete()返回true
  • 需要复制的数据块:BlockManager#neededReplications
  • 正在复制的数据块:BlockManager#pendingReplications
  • 复制超时的数据块:BlockManager#pendingReplications#timedOutItems
  • 多余的数据块:BlockManager#excessReplicateMap(即需要删除的数据块)
  • 无效数据块缓冲区BlockManager#invalidateBlocks(即正在删除的数据块)

    CheckPoint

    非HA

    如果HDFS没有做HA的话,checkpoint由SecondNameNode进程(一般SecondNameNode单独起在另一台机器上)来进行。在HA模式下,checkpoint则由StandBy状态的NameNode来进行。
    什么时候进行checkpoint由两个参数

  • dfs.namenode.checkpoint.preiod(默认值是3600,即1小时)

  • dfs.namenode.checkpoint.txns(默认值是1000000)来决定。

period参数表示,经过1小时就进行一次checkpoint,txns参数表示,hdfs经过100万次操作后就要进行checkpoint了。这两个参数任意一个得到满足,都会触发checkpoint过程。
进行checkpoint的节点每隔dfs.namenode.checkpoint.check.period(默认值是60)秒就会去统计一次hdfs的操作次数。

HA

开启HA的HDFS,元数据已经在standby内存中。

  1. 当前的状态保存成一个新的文件fsimage.ckpt_${end_txid}。
  2. 然后为该fsimage文件创建一个MD5文件,并将fsimage文件重命名为fsimage_txid。
  3. SbNN向ANN发送一条HTTP GET请求。请求中包含了SbNN的主机名,端口以及新fsimage的txid。
  4. ANN收到请求后,用获取到的信息反过来向SbNN再发送一条HTTP GET请求,获取新的fsimage文件。这个新的fsimage文件传输到ANN上后,也是先命名为fsimage.ckpt_txid,并为它创建一个MD5文件。然后再改名为fsimage_txid。fsimage过程完成。

    secondarynamenode

    缺点:元数据滞后于NameNode(上次Checkpoint的结果),所以NameNode失效时会丢数据。

    Quorum Journal Manager(QJM群体日志管理器)

    同一时间QJM只允许一个NameNode向EditLog写日志。

    Failover Controller(故障转移控制器)

    有多种,默认使用Zookeeper。

组件

Block Management