我们都知道 NameNode 中存储的是分布式存储系统的元数据,在 NameNode 重启之后,内存的数据已经丢失了的,所以需要重新加载数据。
这时候我们采用的方法是 FsImage 快照 + editslog 操作日志两种结合的方法;
那它们是怎么结合的呢?换句话说,这两种机制是通过什么联系起来的呢??
FsImage 是由 editslog 经过 checkpoint 机制而得到的,也就是说先有 editslog 再有 FsImage,那么我们来回顾一下 editslog 的组织格式:
message EditLog { int64 txId = 1; // 操作类型 int32 opType = 2; string path = 3; map<string, string> attr = 4; }
可以看到 editslog 中是有一个 txId 的属性的,这个属性是自增的(long 类型,64位取值范围非常大,理论上不会超出了的);txId 是 editslog 的唯一标识。
txId 是在内存中维护着的,每生成一个 editslog 都会将当前 txid 赋值给它,并将 txid + 1;这个在内存维护的 txid 是当前系统中最大的 txid 即 max_txid ,在生成 FsImage 会将系统中所有数据生成快照,并将当前 max_txid 赋值给它。
我们都知道 FsImage 中有两个重要的属性:
public class FsImage { ...... /** * 当前最大的txId */ private long maxTxId; /** * 内容 */ private INode iNode; ...... }
iNode 其实就是元数据,而 maxTxId 其实就是生成 FsImage 时,系统中的 max_txid。
上述我们介绍了 FsImage 和 editslog 数据在内存中的标识,但是这两样数据都是需要持久化的,那么在持久化之后,怎么标识他们呢?
我们都知道他们的数据中包含了 txid ,可是这个数据是需要加载进内存才能看到的。。。
为了在刚恢复数据的时候,也能看到 txid (系统是根据 txid 来联系 FsImage 和 editslog, 进行数据恢复的),所以在持久化的时候,我们对这两种文件的命名进行了特殊的组织格式:
fsimage文件的文件名是"fsimage_txid",其中 txid 是文件系统状态的事务ID
editslog 文件的文件名是类似 “1_1000.log” 这种格式(editslog 记录的可能是多条数据)