TiDB 写入慢流程排查系列(四)— TiKV Server 写入流程

3. Scheduler

gRPC 把对应的请求发送给 tikv scheduler 线程池来执行写操作的不同具体动作,如:prewrite、commit 等。在具体执行这些动作时,会先拿到一个 Snapshot,然后根据这个请求的具体类型执行一些具体逻辑,比如读取锁信息,然后将最终要写入的数据写入 Raftstore。Scheduler duration 等于 latch-wait duration + async-snapshot duration + load lock (all keys total) + async-write duration 的时间总和,具体每个部分的耗时情况下面会逐一讲解。

3.1 Scheduler CPU

TiKV Details → Thread CPU → Scheduler worker CPU:scheduler worker 线程的 CPU 使用率,通常建议 scheduler CPU 使用率不超过scheduler-worker-pool-size*80%:

  • 一般情况下,该 CPU 在各个 TiKV 节点之间使用是均衡的状态。如果出现某个 TiKV 节点的 CPU 在某个时间点或者一个连续的时间段高于其他 TiKV 节点

先要查看是否有较多的锁冲突导致 CPU 使用较高


TiDB–> KV Errors → Lock Resolve OPS:锁冲突的数量

否侧,建议按照写热点进行排查,文档参考写热点处理文档

  • 锁冲突严重导致的问题:

  • 如果各节点 scheduler CPU 使用均衡,但负载较高,对应 Scheduler commands 很多,则建议调大参数:scheduler work pool size 参数来增加线程数。不然请求会因为处理不及时导致延迟加大,此时 CPU 会成为瓶颈。

TiKV Details → Scheduler → Scheduler stage total:每种命令不同阶段的个数,正常情况下,不会在短时间内出现大量的错误
TiKV Details → Scheduler → Scheduler priority commands:不同优先级命令的个数
TiKV Details → Scheduler → Scheduler pending commands:每个 TiKV 实例上 pending 命令的个数

3.2 获取 Snapshot

和读取动作一样,在具体进行写操作之前需要先获得一个 snapshot

TiKV-Detail → Storage → storage async snapshot duration:获取 snapshot 的时间。如果该时间较长,可以参考读流程 snapshot 获取快照慢,如:查看 raftstore 是否较忙 (raft store CPU) 及各节点网络状况是否良好等进行排查

具体动作分析

这里主要关心 Prewrite / Commit 两种类型,并且由于他们的排查方式一样,统一按照下面方式排查,不在单独赘述


TiKV-Detail → Scheduler-prewrite/commit → Scheduler command duration:prewrite/commit 的耗时情况 ,如果上面获取 snapshot 时间及 scheduler CPU 使用没有异常,根据上面的公式,我们需要查看获取 latch 的耗时情况是否正常,以及具体动作的执行情况:


TiKV-Detail → Scheduler-prewrite/commit → Scheduler latch wait duration:prewrite/commit latch wait 的耗时情况,通常获取 latch 的时间都很低,如果 latch wait 时间较长,可能原因如下:

  • 多个事务同时对相同的 key 进行写操作导致冲突,这个时候需要等锁。
  • 同时写入到 TiKV 的 key 的个数非常多(比如大并发导数据场景),超过了 latch 的默认值 2048000,这个时候可以调大 latch 来缓解。对应的参数是[storage] scheduler-concurrency。

如果发现 latch wait duration 不高,则需要查看具体 load lock (all keys total) 动作的情况,判断是否出现扫描过多的 tombstone 导致性能下降,如果没有,建议进入下部分 Raftstore 的写入来进一步排查 async-write duration 的耗时情况。

TiKV-Detail → Scheduler-prewrite → Scheduler keys read:prewrite 命令读取 key 的个数
TiKV-Detail → Scheduler-prewrite → Scheduler keys written:pprewrite 命令写入 key 的个数
TiKV-Detail → Scheduler-prewrite → Scheduler scan details:执行 prewrite 命令时,扫描每个 CF 中 key 的详细情况
TiKV-Detail → Scheduler-prewrite → Scheduler scan details [lock]:执行 prewrite 命令时,扫描每个 lock CF 中 key 的详细情况
TiKV-Detail → Scheduler-prewrite → Scheduler scan details [write]:执行 prewrite 命令时,扫描每个 write CF 中 key 的详细情况
TiKV-Detail → Scheduler-prewrite → Scheduler scan details [default]:执行 prewrite 命令时,扫描每个 default CF 中 key 的详细情况

3 个赞