1 什么是Version 配合manifest中的内容看更直观 RocksDB源码-0x08-MANIFEST文件
RocksDB两手抓,一手抓没持久化的数据在内存,一手抓持久化的数据在SST,回放内存数据靠wal,溯源数据在SST的分布情况也需要一个机制,一类比wal就唤出了VersionSet。
从某个具体的CF视角看,它的每次SST变更就会产生一个VersionEdit,一群VersionEdit组成的概念就是这个CF的Version。再把视角扩大到所有CF,就形成了VersionSet。
通过VersionSet,RocksDB就能拿着key定位到这个key在哪个sst文件里面。
2 盘点VersionSet
3 VersionSet的代码结构 3.1 构造DB的时候构建默认的VersionDB对象 1 2 3 4 5 versions_.reset (new VersionSet ( dbname_, &immutable_db_options_, mutable_db_options_, file_options_, table_cache_.get (), write_buffer_manager_, &write_controller_, &block_cache_tracer_, io_tracer_, db_id_, db_session_id_, options.daily_offpeak_time_utc, &error_handler_, read_only));
3.2 ColumnFamilySet 在VersionSet的构造函数中也会构造个默认的column_family_set
1 2 3 4 : column_family_set_ (new ColumnFamilySet ( dbname, _db_options, storage_options, table_cache, write_buffer_manager, write_controller, block_cache_tracer, io_tracer, db_id, db_session_id)),
3.3 CF的映射 在ColumnFamilySet通过map映射CF的信息
1 2 3 4 UnorderedMap<std::string, uint32_t > column_families_; UnorderedMap<uint32_t , ColumnFamilyData*> column_family_data_;
3.4 CF怎么找到自己的Version 在上面ColumnFamilySet里面根据CF的编号索引到ColumnFamilyData后,在Data里面用current指针指向自己的Version
3.5 Version的结构 Version的数据结构是双链表
1 2 3 Version* next_; Version* prev_;
4 启动的时候从manifest构建恢复VersionSet VersionSet中有个函数Recover负责从manifest文件中重建VersionSet
4.1 从CURRENT里面看看MANIFEST是哪个 1 2 3 4 std::string manifest_path; Status s = GetCurrentManifestPath (dbname_, fs_.get (), is_retry, &manifest_path, &manifest_file_number_);
RocksDB源码-0x07-CURRENT文件
RocksDB源码-0x08-MANIFEST文件
4.2 读manifest文件 1 2 handler.Iterate (reader, &log_read_status);
4.2.1 读取日志记录 对于manifest,RocksDB把它和wal一样对待,都抽象成日志,所以读的时候单位是一条条日志记录而不是简单的一行一行
1 reader.ReadRecord (&record, &scratch)
RocksDB源码-0x0F-日志记录 里面有详细的解读
4.3 反序列化 1 2 s = edit.DecodeFrom (record);
序列化/反序列化是协议设计的选择和方案实现,在RocksDB源码-0x0D-协议设计TLV 里面有全面的介绍和RocksDB的手搓TLV的解析
4.4 VersionEdit回放到VersionSet 上面反序列化拿到了VersionEdit
4.4.1 怎么还有事务的事情 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 if (edit.IsInAtomicGroup ()) { if (read_buffer_.IsFull ()) { s = OnAtomicGroupReplayBegin (); for (size_t i = 0 ; s.ok () && i < read_buffer_.replay_buffer ().size (); i++) { auto & e = read_buffer_.replay_buffer ()[i]; s = ApplyVersionEdit (e, &cfd); if (s.ok ()) { recovered_edits++; } } if (s.ok ()) { read_buffer_.Clear (); s = OnAtomicGroupReplayEnd (); } } }
4.4.2 VersionEdit真正的核心 1 s = ApplyVersionEdit (edit, &cfd);