# Overview
## 核心特性
- 设计思想来自 [WiscKey](https://www.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdf)
- 将 value 从 LSM-tree 中分离出来单独存储,以降低**写放大**
## 对比 Rocksdb
### Titan 优势
- 大 value(1 KB 或 512 B 以上)时,**写**、**更新**和**点读**场景性能更好
### Titan 劣势
- **空间占用更大**
- 相同数据量下 RocksDB 磁盘占用的两倍
- 牺牲空间放大来降低写放大
- 压缩效果差(Titan 是逐个 value 压缩,RocksDB 是逐个 block 压缩)
- **范围查询性能更差**
- 在测试中 Titan 范围查询性能相比 RocksDB 下降 40% 到数倍不等
--------
# 架构与实现
- 
- Titan 在 Flush 和 Compaction 的时候将 value 分离出 LSM-tree
## BlobFile
- 
- 一个 block record 存储一个 Key-Value 对
- 每个 record 都保留了 user key 的拷贝,目的是 GC 时按 key 查询 value 是否已经过期(删除或者被更新),但带来了额外的写放大
- compression 的粒度是 record 级别
- BlobFile 中的 KV 有序存放,目的迭代时可以 prefetch
## TitanTableBuilder
- 自定义 TableBuilder,将大于 `min_blob_size` 的 value 分离到 BlobFile。
## GC
- 两种方式:
- 传统 GC:定期重写 Blob 文件将作废的 value 剔除
- Level-Merge:compaction的时候重写 blob 文件。
### 传统 GC
- 使用 TablePropertiesCollector 和 EventListener 收集统计信息:
- BlobFileSizeProperties:记录每个 SST 中引用的各个 BlobFile 的数据量
- EventListener:监听 compaction,根据 inputs 和 outpus 的 BlobFileSizeProperties 差值,来收集每个 BlobFile 的 discardable size(被丢弃的记录大小)。

- 当 discardable size 达到一定比例,对 BlobFile 进行 GC。
- GC:检查每个 record 是否在 DB 中,还在的话写入到新的 BlobFile,并且回写到 LSM Tree。
- 通过 WriteCallback 或者 MergeOperator。
- 重启需要扫描所有 SSTs 来恢复 discardable sizes。
> [!info]
> 问题:GC 代价高,需要查询 LSM tree 和回写。
### Level Merge
- compaction 时将涉及的 blob records 重写到新的 blob 文件。
- 可以使 blob 文件间有序性更强
- 不需要查询和回写。
- 仅对最后两层进行 level merge(大部分数据都在最后两层)。

----
# 参考资料
- [Titan 介绍](https://docs.pingcap.com/zh/tidb/dev/titan-overview)
- [Titan 的设计与实现](https://cn.pingcap.com/blog/titan-design-and-implementation)