leveldb日志文件格式

这篇文章是levelDB官方文档的译文,原文链接:Format of a log file

日志文件是一系列32KB大小的记录块,唯一例外就是文件的末尾可能包含一个部分记录块。

    block := record* trailer?       // 译者注:多个record块,可能包含一块几个字节的空白。
    record :=
        checksum: uint32    // crc32c of type and data[] ; little-endian; 校验码
        length: uint16      // little-endian;
        type: uint8     // One of FULL, FIRST, MIDDLE, LAST;  类型
        data: uint8[length]     // 数据内容

如果一个block最后还有6个字节,那就不在这剩余的六个字节里面插入新的record了。(译者注:校验码4个字节,长度两个字节,这样就6个字节了,都无法表示这个块是什么类型。)因此,任何在block尾部剩余的小于等于6个字节的空白就是空白,必须用全部的0填充,并且在读取的时候要忽略掉。
副作用:如果在尾部剩余7个字节的话,那个就要填充一个新的记录的FIRST部分,这7个字节里面并没有任何的用户数据,所有的用户数据都在后续的block里面。
将来可能会增加更多的类型,读者可以忽略那些不理解的类型,或者忽略一些不懂得数据。
类型的定义:

FULL == 1
FIRST == 2
MIDDLE == 3
LAST == 4

FULL类型的record表示这个record包含了全部的用户数据。
FIRST, MIDDLE, LAST 使用的场景是用户record被分成多片的情况,(典型的原因就是block的边界),FIRST表示这个用户记录的第一个分片,LAST表示用户记录的最后一个分片,用户记录的所有除了第一个和最后一个分片的内部分片用MIDDLE表示。
例如:考虑这样一个用户记录序列:

A: length 1000B
B: length 97270B
C: length 8000B

-记录A将会以FULL类型全部存储在第一个block里面。(译者注:FULL:7B+1000B)
-记录B被分成3个分片,第一个分片放在第一个block的其余部分(译者注:FIRST: 7B+31754B)。第二个分片占据第二个block的全部空间(译者注:MIDDLE: 7B+32761B),第三个分片占据第三个分片前面的绝大部分,最后剩余6个字节的空白(译者注:LAST: 7B+32755B+6B)。
-记录C将会以FULL类型存储在第四个block里面。(译者注:FULL:7B+8000B)

好处:
1. 重同步的时候不需要启发式查找,只需要到下一个block的边界查找。如果遇到损坏,则直接跳到下一个block。这样带来的意外的好处是,如果一个log文件的部分内容作为记录被放在另一个日志文件里面也不必疑惑。
2. 在边界做分割(例如mapreduce)非常简单:找到下一个block的边界,直到找到一个FULL或者FIRST类型的record。
3. 不需要为大的记录做额外的缓存。
一些副作用:
1. 小的记录没有打包。这个可用通过增加新的记录类型的方式来解决。
2. 没有压缩。这个也可以通过增加新的记录类型的方式来解决。

你可能感兴趣的:(leveldb)