Skip to content

Commit

Permalink
cherry pick pingcap#4429 to release-4.0
Browse files Browse the repository at this point in the history
Signed-off-by: ti-srebot <[email protected]>
  • Loading branch information
TomShawn authored and ti-srebot committed Sep 24, 2020
1 parent a3f0f71 commit ff58291
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 23 deletions.
18 changes: 8 additions & 10 deletions storage-engine/titan-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ aliases: ['/docs-cn/stable/storage-engine/titan-configuration/','/docs-cn/v4.0/s

# Titan 配置

Titan 是基于 RocksDB 开发的存储引擎插件,通过把 key 和 value 分离存储,在 value 较大的场景下,减少写放大,降低 RocksDB 后台 compaction 对 I/O 带宽和 CPU 的占用,以提高性能。详情参阅 [Titan 介绍](/storage-engine/titan-overview.md)

本文档介绍如何如何通过 Titan 配置项来开启、关闭 Titan,相关参数介绍,以及 level merge 功能。
本文档介绍如何通过 [Titan](/storage-engine/titan-overview.md) 配置项来开启、关闭 Titan、相关参数以及 Level Merge 功能。

## 开启 Titan

Expand All @@ -27,7 +25,7 @@ Titan 对 RocksDB 兼容,也就是说,使用 RocksDB 存储引擎的现有 T
{{< copyable "shell-regular" >}}

```shell
`tiup cluster reload ${cluster-name} -R tikv`
tiup cluster reload ${cluster-name} -R tikv
```

具体命令,可参考[通过 TiUP 修改配置参数](/maintain-tidb-using-tiup.md#修改配置参数)。
Expand Down Expand Up @@ -82,7 +80,7 @@ Titan 对 RocksDB 兼容,也就是说,使用 RocksDB 存储引擎的现有 T

+ Titan 中 value 的缓存大小。

更大的缓存能提高 Titan 读性能,但过大的缓存会造成 OOM。建议在数据库稳定运行后,根据监控把 RocksDB block cache (storage.block-cache.capacity) 设置为 store size 减去 blob file size 的大小,`blob-cache-size` 设置为 `内存大小 * 50% 再减去 block cache 的大小`。这是为了保证 block cache 足够缓存整个 RocksDB 的前提下,blob cache 尽量大。
更大的缓存能提高 Titan 读性能,但过大的缓存会造成 OOM。建议在数据库稳定运行后,根据监控把 RocksDB block cache (`storage.block-cache.capacity`) 设置为 store size 减去 blob file size 的大小,`blob-cache-size` 设置为 `内存大小 * 50% 再减去 block cache 的大小`。这是为了保证 block cache 足够缓存整个 RocksDB 的前提下,blob cache 尽量大。

```toml
[rocksdb.defaultcf.titan]
Expand All @@ -99,7 +97,7 @@ Titan 对 RocksDB 兼容,也就是说,使用 RocksDB 存储引擎的现有 T

写放大上界 = 1 / discardable_ratio

空间放大上界 = 1 / (1 - discarable_ratio)
空间放大上界 = 1 / (1 - discardable_ratio)

可以看到,减少这个阈值可以减少空间放大,但是会造成 Titan 更频繁 GC;增加这个值可以减少 Titan GC,减少相应的 I/O 带宽和 CPU 消耗,但是会增加磁盘空间占用。

Expand All @@ -120,25 +118,25 @@ Titan 对 RocksDB 兼容,也就是说,使用 RocksDB 存储引擎的现有 T
- 当设置为 `read-only` 时,新写入的 value 不论大小均会写入 RocksDB。
- 当设置为 `fallback` 时,新写入的 value 不论大小均会写入 RocksDB,并且当 RocksDB 进行 compaction 时,会自动把所碰到的存储在 Titan blob file 中的 value 移回 RocksDB。

当需要关闭 Titan 时,可以设置 `blob-run-mode = "fallback"`,并通过 tikv-ctl 执行全量 compaction。此后通过监控确认 blob file size 降到 0 以后,可以更改 rocksdb.titan.enabled = false 并重启 TiKV。
当需要关闭 Titan 时,可以设置 `blob-run-mode = "fallback"`,并通过 tikv-ctl 执行全量 compaction。此后通过监控确认 blob file size 降到 `0` 以后,可以更改 `rocksdb.titan.enabled = false` 并重启 TiKV。

> **注意:**
>
> 关闭 Titan 是实验性功能,非必要不建议使用。

## Level Merge(实验功能)

TiKV 4.0 中 Titan 提供新的算法提升范围查询性能并降低 Titan GC 对前台写入性能的影响。这个新的算法称为 level merge。Level merge 可以通过以下选项开启:
TiKV 4.0 中 Titan 提供新的算法提升范围查询性能并降低 Titan GC 对前台写入性能的影响。这个新的算法称为 [Level Merge](/storage-engine/titan-overview.md#level-merge)。Level Merge 可以通过以下选项开启:

```toml
[rocksdb.defaultcf.titan]
level-merge = true
```

开启 level merge 的好处如下:
开启 Level Merge 的好处如下:

- 大幅提升 Titan 的范围查询性能。
- 减少了 Titan GC 对前台写入性能的影响,提升写入性能。
- 减少 Titan 空间放大,减少磁盘空间占用(默认配置下的比较)。

相应地,level merge 写放大会比 Titan 稍高,但依然低于原生的 RocksDB。
相应地,Level Merge 的写放大会比 Titan 稍高,但依然低于原生的 RocksDB。
28 changes: 15 additions & 13 deletions storage-engine/titan-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ Titan 适合在以下场景中使用:

Titan 的基本架构如下图所示:

![1-Architecture.png](/media/titan/titan-1.png)
![Architecture](/media/titan/titan-1.png)

Titan 在 Flush 和 Compaction 的时候将 value 分离出 LSM-tree,这样写入流程可以和 RocksDB 保持一致,减少对 RocksDB 的侵入性改动。

### BlobFile

BlobFile 是用来存放从 LSM-tree 中分离出来的 value 的文件,其格式如下图所示:

![2-BlobFile.png](/media/titan/titan-2.png)
![BlobFile](/media/titan/titan-2.png)

BlobFile 由 blob record 、meta block、meta index block 和 footer 组成。其中每个 blob record 用于存放一个 key-value 对;meta block 支持可扩展性,可以用来存放和 BlobFile 相关的一些属性;meta index block 用于检索 meta block。

Expand All @@ -55,18 +55,18 @@ BlobFile 的实现上有几点值得关注的地方:

### TitanTableBuilder

![3-TitanTableBuilder.png](/media/titan/titan-3.png)
![TitanTableBuilder](/media/titan/titan-3.png)

TitanTableBuilder 是实现分离 key-value 的关键,它通过判断 value size 的大小来决定是否将 value 分离到 BlobFile 中去。如果 value size 大于等于 `min_blob_size` 则将 value 分离到 BlobFile,并生成 index 写入 SST;如果 value size 小于 `min_blob_size` 则将 value 直接写入 SST。

该流程还支持将 Titan 降级回 RocksDB。在 RocksDB 做 compaction 的时候,将分离出来的 value 重新写回新生成的 SST 文件中。

## Garbage Collection

Garbage Collection (GC) 的目的是回收空间。由于在 LSM-tree compaction 进行回收 key 时,存在 blob 文件的 value 并不会一同被删除,因此需要 GC 定期来将已经作废的 value 删除掉。在 Titan 中有两种 GC 方式可供选择:
Garbage Collection (GC) 的目的是回收空间。由于在 LSM-tree compaction 进行回收 key 时,储存在 blob 文件中的 value 并不会一同被删除,因此需要 GC 定期来将已经作废的 value 删除掉。在 Titan 中有两种 GC 方式可供选择:

- 定期整合重写 Blob 文件将作废的 value 剔除(传统 GC)
- 在 LSM-tree compaction 的时候同时进行 blob 文件的重写 (Level-Merge)
- 在 LSM-tree compaction 的时候同时进行 blob 文件的重写(Level-Merge)

### 传统 GC

Expand All @@ -76,15 +76,15 @@ Titan 使用 RocksDB 的 TablePropertiesCollector 和 EventListener 来收集 GC

RocksDB 允许使用自定义的 TablePropertiesCollector 来搜集 SST 上的 properties 并写入到对应文件中去。Titan 通过一个自定义的 TablePropertiesCollector —— BlobFileSizeCollector 来搜集每个 SST 中有多少数据是存放在哪些 BlobFile 上的,将它收集到的 properties 命名为 BlobFileSizeProperties,它的工作流程和数据格式如下图所示:

![4-BlobFileSizeProperties.png](/media/titan/titan-4.png)
![BlobFileSizeProperties](/media/titan/titan-4.png)

左边 SST 中 Index 的格式为:第一列代表 BlobFile 的文件 ID,第二列代表 blob record 在 BlobFile 中的 offset,第三列代表 blob record 的 size。右边 BlobFileSizeProperties 中的每一行代表一个 BlobFile 以及 SST 中有多少数据保存在这个 BlobFile 中,第一列代表 BlobFile 的文件 ID,第二列代表数据大小。

#### EventListener

RocksDB 是通过 Compaction 来丢弃旧版本数据以回收空间的,因此每次 Compaction 完成后 Titan 中的某些 BlobFile 中便可能有部分或全部数据过期。因此便可以通过监听 Compaction 事件来触发 GC,搜集比对 Compaction 中输入输出 SST 的 BlobFileSizeProperties 来决定挑选哪些 BlobFile 进行 GC。其流程大概如下图所示:

![5-EventListener.png](/media/titan/titan-5.png)
![EventListener](/media/titan/titan-5.png)

inputs 代表参与 Compaction 的所有 SST 的 BlobFileSizeProperties,outputs 代表 Compaction 生成的所有 SST 的 BlobFileSizeProperties,discardable size 是通过计算 inputs 和 outputs 得出的每个 BlobFile 被丢弃的数据大小,第一列代表 BlobFile 的文件 ID,第二列代表被丢弃的数据大小。

Expand All @@ -94,20 +94,22 @@ GC 的方式就是对于这些选中的 BlobFile 文件,依次通过查询其

### Level Merge

Level Merge 是 Titan 新加入的一种策略,它的核心思想是 LSM-Tree 在进行 Compaction 的同时,对 SST 文件对应的 BlobFile 进行归并重写产生新的 BlobFile。其流程大概如下图所示:
Level Merge 是 Titan 新加入的一种策略,它的核心思想是 LSM-tree 在进行 Compaction 的同时,对 SST 文件对应的 BlobFile 进行归并重写产生新的 BlobFile。其流程大概如下图所示:

![6-LevelMerge.png](/media/titan/titan-6.png) Level z-1 和 Level z 的 SST 进行 Compaction 时会对 KV 对有序读写一遍,这时就可以对这些 SST 中所涉及的 BlobFile 的 value 有序写到新的 BlobFile 中,并在生成新的 SST 时将 key 的 blob index 进行更新。对于 Compaction 中被删除的 key,相应的 value 也不会写到新的 BlobFile 中,相当于完成了 GC。
![LevelMerge](/media/titan/titan-6.png)

相比于传统 GC,Level Merge 这种方式在 LSM-Tree 进行 Compaction 的同时就完成了 Blob GC,不再需要查询 LSM-Tree 的 blob index 情况和写回新 blob index 到 LSM-Tree 中,减小了 GC 对前台操作影响。同时通过不断的重写 BlobFile,减小了 BlobFile 之间的相互重叠,提高系统整体有序性,也就是提高了 Scan 性能。当然将 BlobFile 以类似 tiering compaction 的方式分层会带来写放大,考虑到 LSM-Tree 中 99% 的数据都落在最后两层,因此 Titan 仅对 LSM-Tree 中 Compaction 到最后两层数据对应的 BlobFile 进行 Level Merge。
Level z-1 和 Level z 的 SST 进行 Compaction 时会对 KV 对有序读写一遍,这时就可以对这些 SST 中所涉及的 BlobFile 的 value 有序写到新的 BlobFile 中,并在生成新的 SST 时将 key 的 blob index 进行更新。对于 Compaction 中被删除的 key,相应的 value 也不会写到新的 BlobFile 中,相当于完成了 GC。

相比于传统 GC,Level Merge 这种方式在 LSM-tree 进行 Compaction 的同时就完成了 Blob GC,不再需要查询 LSM-tree 的 blob index 情况和写回新 blob index 到 LSM-tree 中,减小了 GC 对前台操作影响。同时通过不断的重写 BlobFile,减小了 BlobFile 之间的相互重叠,提高系统整体有序性,也就是提高了 Scan 性能。当然将 BlobFile 以类似 tiering compaction 的方式分层会带来写放大,考虑到 LSM-tree 中 99% 的数据都落在最后两层,因此 Titan 仅对 LSM-tree 中 Compaction 到最后两层数据对应的 BlobFile 进行 Level Merge。

#### Range Merge

Range Merge 是基于 Level Merge 的一个优化。考虑如下两种情况,会导致最底层的有序性越来越差:

- 开启 level_compaction_dynamic_level_bytes,此时 LSM-Tree 各层动态增长,随数据量增大最后一层的 sorted run 会越来越多。
- 开启 `level_compaction_dynamic_level_bytes`,此时 LSM-tree 各层动态增长,随数据量增大最后一层的 sorted run 会越来越多。

- 某个 range 被频繁 Compaction 导致该 range 的 sorted runs 较多
- 某个 range 被频繁 Compaction 导致该 range 的 sorted runs 较多

![7-RangeMerge.png](/media/titan/titan-7.png)
![RangeMerge](/media/titan/titan-7.png)

因此需要通过 Range Merge 操作维持 sorted run 在一定水平,即在 OnCompactionComplete 时统计该 range 的 sorted run 数量,若数量过多则将涉及的 BlobFile 标记为 ToMerge,在下一次的 Compaction 中进行重写。

0 comments on commit ff58291

Please sign in to comment.