【TiDB CPU使用率过高之一】Scheduler worker CPU

最近看上了积分兑换里面的衣服,奈何积分不够,搬运整理几篇文章攒积分。

【版本】 v4.0.11
【集群信息】2 TiDB 3 PD 3 TiKV

集群组件:

一、【现象】

Scheduler 线程 CPU 使用率倾斜严重。

Scheduler 线程池有什么用?

scheduler 负责检测事务冲突,将复杂的事务操作转换为简单的 key-value 插入、删除,发送给 raftstore 线程。但是 scheduler 线程池本身不进行任何写操作 。

Scheduler 线程池相关配置参数?

storage.scheduler-worker-pool-size: 8
storage.scheduler-concurrency: 2048000

storage.scheduler-worker-pool-size在 TiKV 检测到机器 CPU 核数大于等于 16 时默认为 8,小于 16 时默认为 4。我这配置的是8。

二、【问题排查】

1、监控 PD-Statistics-hot read

通过监控可以看到热点 region 都集中在了2个节点。

2、 查找热点 region

tiup ctl pd -u http://{pdip:port} hot read > st.txt

过滤并升序输出:
grep ““flow_bytes”” st.txt | awk -F “:” ‘{print $2}’ | sort -n
396624945.6,
489116688.4166667,
499403881.4,

比如我这里使用 499403881 过滤 st.txt 查找到对应的 region id

结果示例:
{
“as_peer”: null,
“as_leader”: {
“1”: {
“total_flow_bytes”: 1245937535.8,
“total_flow_keys”: 2007998.4,
“regions_count”: 40,
“statistics”: [
{
store_id”: 5,
region_id”: 62132,
“hot_degree”: 110,
“anti_count”: 2,
“kind”: 1,
“flow_bytes”: 499403881.4,
“flow_keys”: 201507.55,
“last_update_time”: “2021-06-07T16:21:38.409868198+08:00”,
“version”: 1176
}
}

可以看到 store_id 为 5 ,监控上面绿色的线为 {ip:port}-store-5。是能够对应上的。

或者通过元数据表直接查找热点表:
SELECT * FROM information_schema.TIDB_HOT_REGIONS
WHERE TYPE = ‘read’
ORDER BY flow_bytes DESC;

3、 通过 region id 查找热点表

curl http://{tidbip}:10080/regions/62132

image

4、通过慢查询日志查找对应的SQL

【【慢SQL优化】】

慢日志分析:
Total_keys: 286665 Process_keys: 223050
Total_keys:扫描的总keys
Process_keys:扫描当前keys(不包括旧版本)
这里有6万的旧key,因为这边的GC时长为28h,所以旧版本比较多。

通过上面的Process_keys加上更新SQL,可以分析出扫描这么多的key只有两种情况:
(1)统计信息不准 如果统计信息不准,使用analyze table 更新下。
(2)缺失索引 通过排查是第(2)种情况。

通过添加索引后观察。热点信息有所缓解。

【【热点 region 拆分】】

通过SQL继续排查其它热点表:
SELECT * FROM information_schema.TIDB_HOT_REGIONS WHERE TYPE = ‘read’ ORDER BY flow_bytes DESC;

找到热点表排查region:
SHOW TABLE t_company_gsxt_base_inc regions

t_986_r_23378649 解析:
t:表示table
986:表示table id
r:表示记录
i:表示索引

通过上面的信息可以看到有3个热点 region 。

split merge

operator add split-region 1 --policy=approximate
// 将 Region 1 对半拆分成两个 Region,基于粗略估计值,消耗更少的 I/O,可以更快地完成。

operator add split-region 1 --policy=scan
// 将 Region 1 对半拆分成两个 Region,基于精确扫描值,更加精确

这边使用第1种方式进行拆分,计划将拆分为每个region大概100000个key,所以需要设置一下参数,避免拆分后自动 merge 。

config set max-merge-region-size 10
config set max-merge-region-keys 100000

注意:拆分后需要等待一定时间让 hot leader 自动均衡。并且拆分后的 region 一定要满足以下条件之一,否则 region 会被自动 merge**

max-merge-region-size: 20 // 默认为20MB
max-merge-region-keys: 200000 // 默认为200000

Region Merge 的触发

  1. 如果 Region 的大小大于 max-merge-region-size (默认 20MB)或者 key 数量大于 max-merge-region-keys (默认 200000)不会触发 Merge。
  2. 对于新 Split 的 Region 在一段时间内 split-merge-interval (默认 1h)不会触发 Merge。

另外,也可以调整 coprocessor.region-max-size 默认为96MB,调小使得 hot leader 更加分散。由于我这边生产环境目前设置的为 384MB ,导致热点 region 过于集中,后面将调整回96MB。

经过我的九九八十一次优化,热点region终于分散到了两个节点。 哈哈哈。

三、【解决方案】

根据不同的情况,选用不同的解决方案。
解决方案1:优化慢sql
解决方案2:热点 region 拆分
解决方案3:未完待续

参考:



https://book.tidb.io/session4/chapter7/hotspot-resolved.html#721-确认热点问题

1赞

衣服我们大家可以帮你众筹,但是解决方案能不能发出来~

方案明天整理,不要方。

@Kellen 麻烦审核之后帮忙加分~