1. mainfest文件的作用
mainfest文件是记录lsm tree中的各层tables表的创建删除记录的一个日志文件,主要的作用是badger数据库重启后,重新恢复内存中的各层tables表
2、内容结构
- 先是8个字节的魔数,魔数的结构如下
±----------------------------±------------------------±----------------------±-----------------+
| magicText (4 bytes) | externalMagic (2 bytes) | badgerMagic (2 bytes) |
±----------------------------±------------------------±----------------------±-----------------+ - 再就是pb.ManifestChangeSet结构体进行pb编码后的长度4字节和pb编码后的数据流的checksum
±---------------------------±-------------------------±-----------------+
| pbBufLen(4bytes) | checksum(4bytes) | bpBuf
±---------------------------±-------------------------±-----------------+
3、pb.ManifestChangeSet
type ManifestChange struct {
Id uint64 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"`
Op ManifestChange_Operation `protobuf:"varint,2,opt,name=Op,proto3,enum=badgerpb3.ManifestChange_Operation" json:"Op,omitempty"`
Level uint32 `protobuf:"varint,3,opt,name=Level,proto3" json:"Level,omitempty"`
KeyId uint64 `protobuf:"varint,4,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"`
EncryptionAlgo EncryptionAlgo `protobuf:"varint,5,opt,name=encryption_algo,json=encryptionAlgo,proto3,enum=badgerpb3.EncryptionAlgo" json:"encryption_algo,omitempty"`
Compression uint32 `protobuf:"varint,6,opt,name=compression,proto3" json:"compression,omitempty"`
}
type ManifestChangeSet struct {
// A set of changes that are applied atomically.
Changes []*ManifestChange `protobuf:"bytes,1,rep,name=changes,proto3" json:"changes,omitempty"`
}
changes 是一个切片,把sst文件的每一次创建和删除都记录下来
4、mainfest实现原子性
const (
ManifestFilename = "MANIFEST"
manifestRewriteFilename = "MANIFEST-REWRITE"
)
-
helpRewrite使用两个文件来实现原子性,每次LSM tree 的的sst文件要创建或删除的时候,都是先创建MANIFEST-REWRITE文件,且使用O_TRUNC参数让MANIFEST-REWRITE文件为空文件(清理上次没写完就恰好断电的情况造成MANIFEST-REWRITE是一个脏文件),等数据写都都落盘,存储再MANIFEST-REWRITE文件后,在调用rename函数,把MANIFEST-REWRITE文件改名为MANIFEST-REWRITE,最后修改内存中存储的lsm tree中记录的sst表。
-
ReplayManifestFile函数在回放数据的时候,是在重新打开数据库,数据库目录存在MANIFEST就直接从MANIFEST来读取,即使上次在写MANIFEST-REWRITE的发生断电,内存中的lsm tree的sst表修改是在后的,不会执行,不影响数据可靠性,等下次重新写MANIFEST文件的时候,就会重新把上次的脏数据擦除。
5、和mainfest相关的函数
func (mf *manifestFile) rewrite() error //在lsm tree 任意层要发生变化了调用
func helpRewrite(dir string, m *Manifest, extMagic uint16) (*os.File, int, error)//第一次创建数据和rewrite调用
func ReplayManifestFile(fp *os.File, extMagic uint16)//非第一次打开数据的时候调用,用来重新构建数据lsm tree的各个层的sst 表