暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TiDB 性能优化指南:深入理解 TiDB GC 原理及应用实践

TiDB Club 2024-04-15
822

TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。Garbage Collection(GC)的任务便是清理不再需要的旧数据。


本系列文章将分别介绍 TiDB MVCC 版本堆积相关原理及排查手段和 TiDB、TiKV 组件 GC 原理及常见问题,帮助大家更好地理解 TiDB 事务的实现,确保数据库的稳定与高效运作。

01

TiDB MVCC 版本堆积相关原理及排查手段


TiDB 中的 MVCC 版本的生成原理



●  在 TIDB 层,我们最初收到的是一个关系型表的数据,TiDB 会将这个关系型表数据转化成 key-value,同时调用分布式事务接口,将 key-value 数据写入到 TiKV。


●  在 TIKV 层,我们采用 MVCC 机制提供了分布式事务接口,最终所有的写入都会转化成一条 MVCC key-value 格式写入到 raftstore. 说到 MVCC 格式的 key-value, 无非就是每一个 key 上都有一个版本号,代表其提交的先后顺序。后面我们将这类格式的数据统一称为 MVCC key-value 对。


●  在 raftstore 层,则最终将数据以 key-value 的形式,写入到 rocksdb 中。(注意,rocksdb

(https://docs.pingcap.com/tidb/stable/rocksdb-overview)本身基于 LSM 架构实现,所以它也有 MVCC 的概念,本文不做详细介绍,只对 TiDB 相关的内容点到为止)


数据写入过程


TiDB 侧 SQL table 转为 Key-Value



在 TiDB 层,我们有以上关系型表,上面这一行数据最终会变成三对 key-value(详细原理 https://book.tidb.io/session1/chapter3/tidb-kv-to-relation.html),分别对应:


● 主键对需要保证 key 唯一性:主键值 => 本行所有列数据

● 唯一索引按 key 有序排列加速查询速度:name 列:唯一索引 => 主键

● 非唯一索引按 key 有序排列提升查询性能:age 列:索引+主键 => 空值


TiKV 侧 MVCC 版本写入


在 TiKV 层,分布式事务接口在收到对应的 key-value 对后,会转成对应的 MVCC key-value 写入到 raftstore. 这里我们不展开分布式事务的具体实现逻辑,只用最简单的乐观锁模型

(https://zhuanlan.zhihu.com/p/87608202%EF%BC%89来举例。


TiDB 版本堆积常见排查手段


如前文所说,当 MVCC 版本出现堆积时,会对读写造成性能影响,此时,我们就需要对 GC 参数及状态进行判断,加速旧版本数据的回收,提升集群读写性能。那么,在实际的业务场景中,如何判断我们的 MVCC 数据版本是否出现堆积,并对当前集群读写性能造成了影响呢?


1 Slow log 视角(具体慢 SQL 视角)


MVCC 版本堆积最直接的影响是读写变慢,所以我们从 slow log

(https://docs-archive.pingcap.com/zh/tidb/v7.2/identify-slow-queries) 可以来排查 SQL 执行慢的原因是否是 mvcc 历史版本是否堆积过多。


Step 1 创建表结构

Step 2 插入一条 ID=1 的新数据

Step 3 更新 ID=1 的这行数据

Step 4 删除 ID=1 所在行

Step 5 插入一条 ID=2 的新数据


2 Grafana (集群)视角


因为 slow log 默认只记录 300 ms 以上的 SQL 读取细节,怎么看整个集群 mvcc 读取状态呢?这就需要我们从 grafana 级别来宏观分析了。


● 分布式事务 mvcc

● Rocksdb 层看 MVCC


Region 视角(热点更新表视角)


在实际业务中,我们往往对某些 table 或者 table 中的某些行更新比较频繁,从集群角度看,就只有这些 table 涉及到的 region 的数据版本堆积比较严重。


同时 TiDB 在设计时,要求同一个 key 所在的所有 mvcc 版本数据只能落在一个 region 里面,所以如果 TiDB 中某一行数据更新过于频繁,会导致版本堆积过多而出现大 region 的情况(大于 1 G)。


tikv-ctl(https://docs.pingcap.com/tidb/stable/tikv-control#print-some-properties-about-region)工具提供了命令来查看具体 region 内 mvcc 数据的分布。


其中我们重点关注 mvcc 为前缀的为 mvcc 相关数据:


● mvcc.min_ts:这个 region 里面的所有版本中最小(最老)的 tso

● mvcc.min_ts:本 region 数据中最新的 mvcc 版本 的 tso

● mvcc.num_rows:用户可见的 key 个数(包含已删除的)= mvcc.num_put+mvcc.num_delete

● mvcc.num_put:用户可见的 key 个数(不包含已删除的)

 mvcc.num_delete:用户可见的已删除的 key 数

 mvcc.num_version:用户可见的 mvcc 版本个数

● mvcc.max_row_versions:本 region 中版本数最多的那个 key 拥有的版本数量


Rocksdb 的相关指标不详细展开,只需要关注到 *cf.num_deletes 比较高时,可以通过 手动 compaction (https://docs.pingcap.com/tidb/stable/tikv-control#compact-data-of-each-tikv-manually)指定 CF 来解决。


点击此处查看原文


02

TiDB 组件 GC 原理及常见问题


GC leader


通过对 TiDB 分布式事务

https://tidb.net/blog/7730ed79)实现的了解,我们知道 TiDB 集群具体的数据存储在 TiKV 上,集群的元数据信息存在 PD 上,TiDB 要做数据旧版本的回收,则需要有个类似 GC worker 的角色从 PD 拿到元数据信息然后对 TiKV 中的数据做垃圾回收工作。这个角色目前我们放在 TiDB 中,一个就够,所以我们借助 PD 维护选举出一个 GC leader 的角色,来统一协调整个集群的 GC 工作。


GC leader 是 TiDB 中负责推动集群 GC 工作的一个协程(goroutinue), 一个 TiDB 集群中,同一时刻有且只有一个 TiDB 上会有这个 GC leader 角色。


TiDB GC 整体流程及常见问题


目前我们 TiDB 侧的 GC 流程主要分为四个步骤:


●  计算 GC safepoint, 即 TiDB GC 时需要知道具体删除哪个时间点之前的旧版本。

●  清理 GC safepoint 之前事务留下的锁,即旧版本数据在被清理前,需要明确残留锁所在事务的状态。

●  Delete-ranges 连续范围数据删除,即对于 truncate table 等这类在 TiKV 中连续保存的数据,直接在此阶段进行物理删除以优化性能。

●  将最新 safepoint 同步到集群其他组件(TiKV)


TiDB 中 GC worker 以上行为的发生频率我们可以在 grafana 监控中 tikv-details->GC->TiDB GC worker actions 看到。



Step 1 计算 GC safepoint

Step 2 Resolve locks

Step 3 Delete Ranges

Step 4 Sync gc safepoint


点击此处查看原文


03

TiKV 组件内 GC 原理及常见问题


GC_key in TiKV


当前 key 一共有四个版本,写入顺序如下:


●  1:00 新写入或更新,数据存在 default cf

●  2:00 更新,数据存在 default cf

  3:00 删除

●  4:00 新写入,数据存在 default cf

如果 GC safepoint 是 2:30 , 即最多保证到 2:30 这个时刻的快照一致性,那么我们会保留 2:30 这个时刻读到的版本:key_02:00=>(PUT,01:30), 他之前的版本数据全部删除,这里我们 key_01:00 对应事务的 write-cf 和 default cf 都会被删除掉。如果 GC safepoint 是 3:30 呢?

同样的,保留 3:30 这一时刻读到的 key_03:00=>DELETE,3:00 以前的旧版本就会被删除掉。我们看到,3:30 读到的快照里 key_03:00 的事务是在删除这个 key, 那我们是否有必要保留 03:00 这条 MVCC 呢?当然是不用了,所以正常情况下,如果 gc safepoint = 3:30, 那么这个 key 需要被 GC 的数据为:

以上,就是对于某个明确的 key, GC 所需要具体清理的数据。TiKV 的 GC,则需要把当前 TiKV 实例上,所有的 key 进行扫描并删除符合条件的旧版本。


相关监控

gc_keys 因为需要读取当前 key 的所有版本才能确认是否删除旧版本,所以会对系统产生读压力,相关监控在 tikv-details->GC-> GC scan write/default details:记录了 GC worker 在执行过程中对 rocksdb write/default cf 的压力:

gc_keys 的 duration 可以在 tikv-details->GC-> GC tasks duration 里面看,如果这一块延迟比较高,说明 gc 压力比较大或者系统本身读写压力比较大影响到了 GC。


GC in TiKV


本章,我们来具体介绍每个 TiKV 实例上,GC 的执行原理和相关监控。TiKV 侧主要有两个常驻线程负责驱动和管理 GC:


● GC worker

● GC manager



GC worker


每个 TiKV 侧有一个 GC worker 线程来处理具体的 GC 工作,TiKV 的 GC worker 主要负责处理以下两类请求:


●  GC_keys,简言之,就是对于具体的 key, 扫描并删除符合条件的旧版本。

●  GC(range):就是对于一块连续的范围的数据调用 GC_keys, 对指定范围内中的每个 key 单独进行 GC 处理。

●  unsafe-destroy-range:对于连续范围的数据,直接物理清理。


相关监控

GC tasks QPS/duration: tikv-details->GC->GC tasks/GC tasks duration,一般发现 GC tasks duration 比较高时,需要结合 QPS 及 GC worker 的 CPU 是否够用。GC worker CPU 的使用情况:tikv-details-> thread CPU->GC worker。



GC manager


GC manager 是 TiKV 中负责驱动 GC 工作的线程,主要步骤为:


●  同步 GC safepoint 到本地

●  全局指导实施具体的 GC 工作


1 同步 GC safepoint 到本地

2 实施 GC 作业


TiKV GC 实施方式


1 GC by region(传统 GC)

● GC a round

● 常见问题


2 GC with compaction-filter

2.1  Why compaction in rocksdb

2.2 实现原理


3 相关配置


在 compaction filter 打开的情况,大部份的物理数据回收是在 rocksdb write CF compaction 的时候完成的。对于每个 key:


●  对于 tso > gc safepoint 的,保留并跳过

●  对于 tso <= gc safepoint 的:根据类型确认是否保留最新一个版本,过滤旧版本



4 相关监控


tikv-details->GC-> GC in Compaction-filter:



关键字段定义:在 compaction filter 过程中,遇到的 key-value 符合以下条件时:



5 常见问题


Compaction-fitler 启用下,Delete 方式删除数据后,物理空间长期不释放的问题.


Compaction filter 方式 GC 虽然能够直接在 compaction 阶段就把旧数据清理出局,能够大力缓解 GC 压力,但通过上面对原理的了解我们知道,正因为依赖 rocksdb 的 compaction 来回收数据,当 rocksdb 的 compaction 工作一直没有发生时,就会导致我们的数据在 GC safepoint 过了很久以后还是无法释放出物理空间。


因此在这种情况下,刺激 rocksdb 做 compaction 变得无比重要。


●  Workaround 1:通过参数调整 compaction 的频率

●  Workaround 2:手动 compaction


方法一:在业务低峰期,直接发起整表的 compaction

方法二:如果表内数据量比较大的话,为降低对集群业务的性能影响,可以将整表的 compact 变为按 region 为单位进行 compact

方法三:v7.1.0 之前,可以直接关闭 compaction-filter, 使用传统的 GC 方式。


点击此处查看原文






点击下图,立即咨询 TiDB 企业版

文章转载自TiDB Club,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论