nn与2nn原理图
说明:
1.namenode原始数据来源于历史的镜像文件(fsimage)和编辑日志文件(edits_inprogre)
2.namenode在启动的时候会加载这两个文件到内存中,这样增删元数据就是内存级别操作
3.edits_inprogre是最新的一些元数据操作,2nn会定时定量帮助归档,这样就能防止元数据丢失,造成namenode成为垃圾数据
4.2nn的备份策略是 满足一定可配置的阈值,当edits_inprogre达到一定时间或者达到了一个较大的日志数量时候,2nn开始帮助生成fsimage文件,并且2nn自己备份了一份,即使nn数据丢失,依然可以从2nn中拷贝过来恢复
nn与2nn原理图案例说明
1.准备环境,这样可以原理看的清楚
1.停止hdfs环境 stop-dfs.sh
2.删除之前的数据 rm -rf /tmp/hadoop-root/
3.格式化 hdfs namenode -format
4.重启hdfs start-dfs.sh
2.效果
说明:数据都清光了
说明: 1.初始化有一个fsimage_0000000000000000000的镜像文件
2.目前最新的镜像文件是fsimage_0000000000000000002
3.目前正在进行的日志编辑文件edits_inprogress_0000000000000000003
4.目前最新日志id记录文件 seen_txid
<?xml version="1.0"?>
<fsimage>
<NameSection>
<genstampV1>1000</genstampV1>
<genstampV2>1000</genstampV2>
<genstampV1Limit>0</genstampV1Limit>
<lastAllocatedBlockId>1073741824</lastAllocatedBlockId>
<txid>0</txid>
</NameSection>
<INodeSection>
<lastInodeId>16385</lastInodeId>
<inode>
<id>16385</id>
<type>DIRECTORY</type>
<name></name>
<mtime>0</mtime>
<permission>root:supergroup:rwxr-xr-x</permission>
<nsquota>9223372036854775807</nsquota>
<dsquota>-1</dsquota>
</inode>
</INodeSection>
<INodeReferenceSection></INodeReferenceSection>
<SnapshotSection>
<snapshotCounter>0</snapshotCounter>
</SnapshotSection>
<INodeDirectorySection></INodeDirectorySection>
<FileUnderConstructionSection></FileUnderConstructionSection>
<SnapshotDiffSection>
<diff>
<inodeid>16385</inodeid>
</diff>
</SnapshotDiffSection>
<SecretManagerSection>
<currentId>0</currentId>
<tokenSequenceNumber>0</tokenSequenceNumber>
</SecretManagerSection>
<CacheManagerSection>
<nextDirectiveId>1</nextDirectiveId>
</CacheManagerSection>
</fsimage>
//反序列化镜像文件命令 fsimage_0000000000000000002
hdfs oiv -p XML fsimage_0000000000000000002 -i fsimage_0000000000000000002 -o fsi2.xml
说明:现在镜像文件什么也没有,只是一些初始化日志
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
<EDITS_VERSION>-63</EDITS_VERSION>
<RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>3</TXID>
</DATA>
</RECORD>
</EDITS>
//发序列化编辑日志文件 edits_inprogress_0000000000000000003
hdfs oev -p XML edits_inprogress_0000000000000000003 -i edits_inprogress_0000000000000000003 -o ed03.xml
说明:现在编辑文件日志也什么也没有,目前最新日志id为3
2.上传一个文件
1.上传一个文件 hadoop fs -put /a.txt /a.txt
2.重新反序列化 fsimage_0000000000000000002
3.重新反序列化 edits_inprogress_0000000000000000003
<?xml version="1.0"?>
<fsimage>
<NameSection>
<genstampV1>1000</genstampV1>
<genstampV2>1000</genstampV2>
<genstampV1Limit>0</genstampV1Limit>
<lastAllocatedBlockId>1073741824</lastAllocatedBlockId>
<txid>2</txid>
</NameSection>
<INodeSection>
<lastInodeId>16385</lastInodeId>
<inode>
<id>16385</id>
<type>DIRECTORY</type>
<name></name>
<mtime>0</mtime>
<permission>root:supergroup:rwxr-xr-x</permission>
<nsquota>9223372036854775807</nsquota>
<dsquota>-1</dsquota>
</inode>
</INodeSection>
<INodeReferenceSection></INodeReferenceSection>
<SnapshotSection>
<snapshotCounter>0</snapshotCounter>
</SnapshotSection>
<INodeDirectorySection></INodeDirectorySection>
<FileUnderConstructionSection></FileUnderConstructionSection>
<SnapshotDiffSection>
<diff>
<inodeid>16385</inodeid>
</diff>
</SnapshotDiffSection>
<SecretManagerSection>
<currentId>0</currentId>
<tokenSequenceNumber>0</tokenSequenceNumber>
</SecretManagerSection>
<CacheManagerSection>
<nextDirectiveId>1</nextDirectiveId>
</CacheManagerSection>
</fsimage>
说明: 镜像文件无最新内容,没变化
<RECORD>
<OPCODE>OP_ADD</OPCODE>
<DATA>
<TXID>4</TXID>
<LENGTH>0</LENGTH>
<INODEID>16386</INODEID>
<PATH>/a.txt._COPYING_</PATH>
<REPLICATION>1</REPLICATION>
<MTIME>1615695213595</MTIME>
<ATIME>1615695213595</ATIME>
<BLOCKSIZE>134217728</BLOCKSIZE>
<CLIENT_NAME>DFSClient_NONMAPREDUCE_-945348876_1</CLIENT_NAME>
<CLIENT_MACHINE>172.24.55.121</CLIENT_MACHINE>
<OVERWRITE>true</OVERWRITE>
<PERMISSION_STATUS>
<USERNAME>root</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>420</MODE>
</PERMISSION_STATUS>
<RPC_CLIENTID>a169169b-9bc6-4c12-9bd0-9178d11bc584</RPC_CLIENTID>
<RPC_CALLID>3</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE>
<DATA>
<TXID>5</TXID>
<BLOCK_ID>1073741825</BLOCK_ID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_GENSTAMP_V2</OPCODE>
<DATA>
<TXID>6</TXID>
<GENSTAMPV2>1001</GENSTAMPV2>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_ADD_BLOCK</OPCODE>
<DATA>
<TXID>7</TXID>
<PATH>/a.txt._COPYING_</PATH>
<BLOCK>
<BLOCK_ID>1073741825</BLOCK_ID>
<NUM_BYTES>0</NUM_BYTES>
<GENSTAMP>1001</GENSTAMP>
</BLOCK>
<RPC_CLIENTID></RPC_CLIENTID>
<RPC_CALLID>-2</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_CLOSE</OPCODE>
<DATA>
<TXID>8</TXID>
<LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/a.txt._COPYING_</PATH>
<REPLICATION>1</REPLICATION>
<MTIME>1615695215145</MTIME>
<ATIME>1615695213595</ATIME>
<BLOCKSIZE>134217728</BLOCKSIZE>
<CLIENT_NAME></CLIENT_NAME>
<CLIENT_MACHINE></CLIENT_MACHINE>
<OVERWRITE>false</OVERWRITE>
<BLOCK>
<BLOCK_ID>1073741825</BLOCK_ID>
<NUM_BYTES>26</NUM_BYTES>
<GENSTAMP>1001</GENSTAMP>
</BLOCK>
<PERMISSION_STATUS>
<USERNAME>root</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>420</MODE>
</PERMISSION_STATUS>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_RENAME_OLD</OPCODE>
<DATA>
<TXID>9</TXID>
<LENGTH>0</LENGTH>
<SRC>/a.txt._COPYING_</SRC>
<DST>/a.txt</DST>
<TIMESTAMP>1615695215160</TIMESTAMP>
<RPC_CLIENTID>a169169b-9bc6-4c12-9bd0-9178d11bc584</RPC_CLIENTID>
<RPC_CALLID>9</RPC_CALLID>
</DATA>
</RECORD>
</EDITS>
说明:这里之展示新增内容, 看到编辑日志文件追加了4-9
3.一个小时后,发生了 fsimage文件和edit文件合并
说明:1.edits_inprogress_0000000000000000003文件消失了,其实被存档为
edits_0000000000000000003-0000000000000000010
2.fsimage_0000000000000000010是新生成的镜像文件,由edits_inprogress_0000000000000000003生成
3.继续生成新的编辑日志文件edits_inprogress_0000000000000000011,继续生成追加日志等待归档
4.这个动作其实是2nn做的,2nn辅助nn工作,帮助他进行原始数据备份
5.namenode内存的数据是fsimage-00000000* 和 edits_inprogress_000*组成的原始数据
4.看看nn和2nn的数据
说明:2nn就是少了edits_inprogress_000数据, 2nn会定时去nn取这部分数据的,满足一些阈值,就帮助nn生成新的fsimage-00000000存档
总结
1.这是hdfs为了保证原始数据不丢失在内存掉电丢失的备份方案
2.这是hdfs为了保证操作原始数据达到内存级别的方案,因为可以直接修改一次元数据,然后记录在文件中,这样的话修改元数据就是io级别操作了,会很慢
3.我们看到这个备份方案和mysql的binglog和redis的AOF RDB方案很像,原理都差不多