【TiDB 4.0 PCTA 学习笔记】- 2.5.6 TiKV Tuning Guide(TIDB 的 TiKV 性能优化指南)@2班+元峥

课程名称:课程版本(101/201/301)+ 课程名称

学习时长:2h

课程收获:

课程内容:

性能排查Roadmap

  1. 当发现SQL的延迟上涨,优先检查TiDB和TiKV的通信延迟,这个延迟代表着TiKV执行命令且回复到TiDB的大致时间,然后通过对比TiKV侧统计的命令执行时间,可以确定网络部分是否正常,大部分情况这2侧时间是一致的
  2. 当延迟出现在TiKV侧,通过分析TiKV存储引擎的各项指标,可以判断落盘是否出现了问题,如果不是,那么延迟出现在TiKV的其他部分,包括raft同步,等待锁延迟等等

TiKV架构

TiKV分层

TiKV模块

调优思路

  • 当出现异常时候,比如客户端某些SQL较高,我们应该首先在grafana面板中找到对应的时间段,查TiKV的执行延迟和QPS,查看Duration是否符合预期,一般情况99pth读延迟是100ms以下,99pth写延迟是在500ms以下,超出部分就是异常部分

  • 通过Query-Sammary中的监控来判断是什么写入缓慢,可以重点关注Select和Commit操作,后者会启动两阶段提交,SQL的 Select操作和 KV Request中的请求存在对应关系,通过KV Request Duration这个面板可以判断延迟的主要消耗是TiDB进程还是TiKV的进程,如果这一项没有异常,那就证明TiKV的处理是很快的,那就可以缩小问题到TiDB侧,同时也可以通过KV Request QPS 和Query QPS来对比,从侧面推断查询计划是否正确
    image

  • gRPC是TiKV的请求入口,那我们就可以通过gRPC请求入口的message数量以及gRPC Duration来验证上一步在TiKV Request的延迟是否正确,假设问题出在TiKV侧,以prewrite请求为例,prewrite请求会被gRPC转发给事务层的Scheduler库,这里的Scheduler latch wait dutarion是TiKV为了防止多个事务对同一个key进行读写检测造成写倾斜而加的锁,Scheduler Command duraiton就是prewrite请求执行事务冲突检测以及写入raft store的时间之和,如果这些metric都挺正常,就可以继续往下分析

  • 这个面板统计了包括了从raft开始propose,然后发送复制消息,然后follower,然后follower回复ack给leader,leader将数据写入rocksdb,并且写入成功这一系列操作的总耗时,就是事务层下层的总耗时,如果这层的延迟较高,那么就可以推断出延迟不是出现在事务层,而是在raft store层或者是raft store以下的层级

  • 确认问题是出现在store之后,我们就可以细化分析每个步骤,现在raft propose,这里两个指标分别代表了raft store线程和apply线程的执行情况,前者含义为transcation层开始向raft层写入数据到raft层接收到消息并开始处理等待时间,而后者是raft层的leader和follower达成一致,开始异步的写入数据到Apply线程接收到消息准备真正的写入底层的存储引擎及rocksdb的等待时间。这里我们可以优先查看wait,而不用raft IO中真正处理消息所花费的时间,是因为这些wait指标隐含了消息在队列中等待的时间,也从侧面反应出线程的繁忙程度,对于写入请求,当我们看到这部分的时候,基本就可以判断写入延迟造成的原因了,如果是apply延迟很高,那很可能是apply线程数的配比太小,如果是propose的延迟很高,那很可能是盘太差,导致了性能的延迟高,或者是raft线程数的配比太小

  • 如果TiKV中的CPU占用已经达到物理机CPU的上限,那么各个模块的上涨就是理所应当的

  • 如果apply延迟很高,通常4个原因
    1. apply线程的数量,可以通过Async apply CPU来看是否接近了配置的Apply process这个选项,如果利用率已经达到了这个选项所代表的线程池上限80%以上的话,那就可以调大线程池,就是调大apply的线程数量
    2. 整机CPU资源利用率太高,导致线程争抢不到足够的cpu资源,可以通过server cpu判断出来
    3. 产生了write stall,这是因为写入被rocksdb阻塞限流了
    4. TiKV部署的盘太差了,达到了吞吐上限
  • 如果raft store延迟较高,也是有4个原因
    1. 线程CPU不足
    2. 心跳过于频繁,可以开启。。。来减少心跳数,该功能是4.0及以上版本默认开启,整个集群需要全部开启或者全部关闭
    3. 磁盘性能不好
    4. rocksdb 发生了write stall

  • rocksdb的写入流程
    这里认为写入的数据就是简单的多对key-value pair ,一对key-value首先被写入到memory table中,这是一个内存数据结构,用于将数据持久化到盘之前保存数据,一旦memory table写满,后台的线程会将此memory table的数据刷入ssd文件中,成功后销毁之前写入过的memory table,成功将memory table写入的ssd文件我们称为L0层文件,但是如果写请求过多,以致于快过了rocksdb能处理的线程,rocksdb就会限制写入,这就是rocksdb 的write stall来源。如果没有write stall 的限制,写方会导致rocksdb很快占用大量的磁盘空间,同时也降低了磁盘的IO性能,如果想判断rocksdb是否正在被write stall限制,而导致TiKV持久化缓慢,可以通过rocksdb本身的log文件判断,这个log文件一般存储在tikv/data/db目录
  • 产生write stall的原因
    1. 过多memory table,当需要落盘的memory table超过了最大的缓存数量限制,那就必须触发write stall,来避免来产生更多的memory table
    2. 过多的L0层文件,当处于L0的lst连接数量达到预值也会触发,否则会导致更多写盘影响后续的compaction性能
    3. 过多等待compaction数据,这是因为compaction的速度已经达到极限,更多的写入会带来更多的compaction,等过了这段compaction高峰,才能继续写入
      避免write stall
  • 增加memory table缓存数量
  • 增加racksdb线程

  • 简单的查询,被Storage ReadPool处理
  • 复杂的聚合计算和范围查找,被coprocessor处理
  • 4.0及以后版本支持统一线程池,即unified read pool,同时支持这2类请求的查询,避免更多的线程分配

错误的查询计划也会导致过多的查询请求发送给TiKV(如何查看错误的执行计划不在本次课程)

学习过程中遇到的问题或延伸思考:

  • 问题 1:
  • 问题 2:
  • 延伸思考 1:
  • 延伸思考 2:

学习过程中参考的其他资料