# 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% 到数倍不等 -------- # 架构与实现 - ![架构图](https://docs-download.pingcap.com/media/images/docs-cn/titan/titan-1.png) - Titan 在 Flush 和 Compaction 的时候将 value 分离出 LSM-tree ## BlobFile - ![](https://docs-download.pingcap.com/media/images/docs-cn/titan/titan-2.png) - 一个 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(被丢弃的记录大小)。 ![459](https://docs-download.pingcap.com/media/images/docs-cn/titan/titan-5.png) - 当 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(大部分数据都在最后两层)。 ![](https://docs-download.pingcap.com/media/images/docs-cn/titan/titan-6.png) ---- # 参考资料 - [Titan 介绍](https://docs.pingcap.com/zh/tidb/dev/titan-overview) - [Titan 的设计与实现](https://cn.pingcap.com/blog/titan-design-and-implementation)