公司 tidb 集群 p95 突然上升。排查监控发现 tikv 同时间有大量 gc worker 开始运行。同时集群的 safepoint 向前跳了一大截。之前的 safepoint 大概是三天以前。
这里就带来了以下几个问题。
- safepoint 为什么会有这么大的 lag。
- safepoint 为什么会突然向前推进。
- safepoint 是如何影响 gc ,进而影响整个集群响应时间的。
safepoint 是什么
- safepoint 是一个时间点。
- commit_ts 早于 safepoint 的多余版本数据都可以被清理掉。
tikv 是基于 rocksdb 的分布式 kv 存储,基于 mvcc 实现 snapshot 级别的隔离。每个数据都会保留多个版本。简单来说,snapshot 级别的隔离要求 start_ts 开始的事务 txn_1,一定可以读到 commit_ts < start_ts 的数据,并且读不到 commit_ts > start_ts 的数据。同时,每隔固定时间就要对多余的版本数据进行清理,否则随着数据的更新,存储空间和读写效率都会下降。清理的同时,还要保证不能破坏 snapshot isolation。tidb 中目前是这么做的:
- 假设当前 safepoint 为 s1。
- 10min 之后,计算一个新的 safepoint,记为 s2。注意此时不能直接把 safepoint 设为 s2,这样会导致 commit_ts < s2 的多余版本数据可能会被清理掉。如果当前有一个事务开始时间为 start_ts1 的事务 txn1 正在运行,数据 tuple1 有两个版本 commit_ts1 和 commit_ts2,其中 commit_ts1 < start_ts1< commit_ts2 < s2。 如果此时 safepoint 被设为 s2。则 tuple1 commit_ts1 版本就可能会被清理掉,txn1 就读不到版本为 commit_ts1 的 tuple1 了。破坏了 snapshot isolation。
- 获取当前正在运行的所有事务中最小的 start_ts,记为 start_ts_min。
- 设置 safepoint 为 min(start_ts_min, s2)。
safepoint 突然跃进的原因
有一个 ticdc 的数据同步任务在三天前卡住没有处理,ticdc 可能是通过 start_ts_min 来控制 safepoint 不再向前推进的,只是猜测,具体实现细节没有细看。然后 DBA 同学在今天清理掉了这个任务,导致 safepoint 向前跳了一大截。
p95 上升的原因
三天时间,集群中积累了大量可以被清理掉的多版本数据。safepoint 向前推进之后,tikv 瞬间启动了大量 gc worker ,由于没有进行限速,这些 gc worker 占用了很多的磁盘 io 和内存资源。导致 cache miss,同时读磁盘的时延也有所上升,最主要的原因还是 cache miss 增多。
解决方式
通过 tikv-ctl 命令对 gc woker 进行限流,实时生效。
也可以限制 gc concurrency,需要重启生效。