- 每个 cf 的资源: - Memtable 和 SST 文件独立 - WAL 和 Manifest 共享 ------ # ColumnFamilyHandle - 面向用户,用户使用它来操作 cf。 - 实现类:ColumnFamilyHandleImpl - 主要包含了 `ColumnFamilyData` ------- # SuperVersion - cf 在某个时刻的 LSM 视图,包括内存和磁盘组件。 - 持有/引用了 cf 的 memtable、immutable memtables 和 version。 - **核心成员**: - **`cfd`**:`ColumnFamilyData*`,所属的 cf - **`mem`**: `ReadOnlyMemtable`,当前的 memtable - **`imm`**:`MemTableListVersion*`,已冻结的 memtables - **`current`**:`Version *`,引用的磁盘组件状态 - **`version_number`**: `uint64_t`, 当前 sv 的版本号 - **`write_stall_conditition`**:[[write#^1fc93e|WriteStallCondition]] - **`to_delete`**:`vector<ReadOnlyMemtable>` - SuperVersion Cleanup() 时,对 mem 和 imm 进行 Unref,如果引用计数为0, 就把 memtable 放到 `to_delete` 中,在`~SuperVersion()`中进行 delete 操作。 - 如果 `avoid_unnecessary_blocking_io = true`,释放 SuperVersion 会在后台进行。[#6146](https://github.com/facebook/rocksdb/pull/6146) ## Cleanup() - Unref 关联资源:memtables,version,cfd ---------- # ColumnFamilyData - 包含了一个 cf 所有相关的数据。 - cf 的 id,name 等 - SuperVersion - Memtables - **核心成员**: - **`dummy_versions_`**: `Version*`,Version 循环双链表的头部 - **`current_`**: `Version *`,当前最新的 Version,等于 `dummy_versions->prev_` - **`mem_`**: `MemTable*`, 当前可写入的 Memtable - **`imm_`**:`MemTableList`, 已冻结的 Memtables - **`super_version_`**:`SuperVersion *` ^9e0dbe - **`local_sv_`**:`unique_ptr<ThreadLocalPtr>`,SuperVersion 的 thread local 缓存 - 用于无锁化获取当前 sv - ThreadLocalPtr 是特殊的 thread local,确保不同 DB 实例的同名变量不冲突。 - **`super_version_number_`**:`atomic<uint64_t>`, 每次 `InstallSuperVersion()` 会加 1 - **`next_`**, **`prev_`**: `ColumnFamilyData*`, 所有 ColumnFamilyData 组成循环双链表 - **`last_memtable_id_`**:`atomic<uint64_t>`,用于分配 memtable ID - **`log_number_`**: `uint64_t`,包含该 cf 当前 unflushed 数据的最早的 WAL 文件编号^21d38a - 该编号 WAL 内可能存在当前 cf 未 flush (即 memtable 内的)的数据,大于等于 `log_number_` 的 WAL 不能被回收(保证数据持久化) - 对于该 cf,小于它的 WAL 中的数据已经 flush 到 SST,因此 recover 时不需要加载,否则会造成重复数据(例如重复的 merge 操作) - 每次 SwitchMemtable 时将要冻结的 memtable 绑定新创建的 WAL log number,当 memtable Flush 后从 VersionEdit 中更新该字段 ## local_sv 访问 - **GetThreadLocalSuperVersion()** - 从 `local_sv_` 缓存读取 SuperVersion,并将 `local_sv_` 置为 kSVInUse - 如果读到 kSVObsolete,表示已经失效(install 了新 Version),则加锁读取非 thread local 的 `super_version_`,并进行 Ref 操作 - **ReturnThreadLocalSuperVersion()** - 入参:`SuperVersion *sv` - CAS 操作:如果 `local_sv_`当前为 kSVInUse,则赋值 `local_sv_` 为 sv,返回 true - kSVInUse 表示上次调用 GetThreadLocalSuperVersion() 获取的 sv 没有失效(每次 Get 都会设置 kSVInUse),则可以写回 cache - **特殊情况**:上次不是从 `local_sv_` 中而是从 global 中获取的 sv(且已经 Ref 过),也可以写回,起到了==更新 cache== 的作用。 - 否则返回 false,sv 需要 Unref - **ResetThreadLocalSuperVersions()** - 安装新 sv 时调用,失效所有线程的 `local_sv_` - 如果失效之前为有效 sv(非 kSVInUse),则对它进行 Unref - **GetReferencedSuperVersion()** 1. 调用 GetThreadLocalSuperVersion() 获取 sv,进行 Ref 操作 2. 将 sv 通过 ReturnThreadLocalSuperVersion 放回 `local_sv_`,失败则调用 Unref - **kSVInUse** 的作用 - 表明上次 Get 时获取的 sv 是否失效 - ResetThreadLocalSuperVersions 时只 Unref 非 kSVInUse 的,避免另一线程 t2 拿到了 cache 的 sv 但还没有进行 Ref 操作,此时 Unref 的话 t2 拿到的 sv 就被释放了。 ## InstallSuperVersion() - `DBImpl::InstallSuperVersionAndScheduleWork()` 中调用。 - 更新 cf 的 SuperVersion: 1. 利用 ColumnFamilyData 的当前状态(mem, imm, current version) 初始化新的 sv,并更新到 `super_version_`; 2. 对新 sv 调用 RecalculateWriteStallConditions() 3. ResetThreadLocalSuperVersions():失效 thread local cache 4. UnRef old sv -------- # ColumnFamilySet ^09f276 - cf 集合,保管所有的 cf。 - 核心成员: - **`column_families_`**:`Map<string, uint32_t>`,名字到 cf ID 的映射 - **`column_family_data_`**:`Map<uint32_t, ColumnFamilyData*>`,cf ID 到 Data 的映射 - **`dummy_cfd_`**:`CoumnFamilyData *`,CoumnFamilyData 循环双链表头部 ---------- # 总结 - SuperVersion 的更新 - 入口 - SwitchMemtable():更新 mem 和 imm - flush 或者 compaction 完成后:更新 Version 和 imm(flush) - CreateColumnFamily/Recovery时:初始化 sv - 更新方式: 1. 先更新 ColumnFamilyData 的相关成员, 例如: - compaction 后通过 ProcessManifestWrites 往 ColumnFamilyData 追加新 Version 并设为 current - SwitchMemtable() 是直接更新 cfd 的 mem 和 imm - flush 后通过 TryInstallMemtableFlushResults 触发 ProcessManifestWrites 更新 Version 后删除 imm 2. 再根据 ColumnFamilyData 当前状态创建新 sv - ColumFamilyData::InstallSuperVersion() - 通常通过 InstallSuperVersionAndScheduleWork 触发 ## Column family 类关系图 ```mermaid classDiagram DBImpl <|-- VersionSet : 一对一 DBImpl : unique_ptr~VersionSet~ versions_ VersionSet <|-- ColumnFamilySet : 一对一 VersionSet : unique_ptr~ColumnFamilySet~ column_family_set_ ColumnFamilySet <|-- ColumnFamilyData : 包含多个 ColumnFamilySet : UnorderedMap~uint32_t, ColumnFamilyData*~ column_family_data_ ColumnFamilyData : -SuperVersion* super_version_ ColumnFamilyData : -Version* current_ ColumnFamilyData : -MemTable* mem_ ColumnFamilyData : -MemTableList imm_ ``` ---- # TODO - [ ] create/drop cf 流程