- 每个 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 流程