# [Know Issue] TiKV 定位读热点，通过 Split Region 处理热点

## Key Words

TiKV, Hot read, Split Region，Dashboard

## Description

TiDB 请求异常抖动，个别 TiKV 的读请求延迟较高，同时对应 TiKV Unified read pool CPU usage 个别 TiKV 实例明显异常，TiKV-Cluster 监控看到对应的 TiKV 实例的读流量明显异常，超过其他实例的 2 倍读流量，达到 500MB/s 左右。 如何定位读热点具体的情况，并且通过现有的 TiDB 功能处理读热点。

## Root Cause

元信息表数据读热点，导致部分 TiKV 的 Coprocessor 请求过多。需要在表的结构和数据分布两部分做优化，原则上尽量减少热点数据集中在某几个 TiKV 中，另外根据业务逻辑，调整表的结构，提前打散数据分布以及预分配 Region 打散数据分布。

## Diagnostic Steps

1. 通过 TiDB 监控的 KV-Request panel 面板确认一下 TiKV 请求延迟的情况，是否出现突增现象；
    a. TiKV -> KV Request -> Reuqest duration/Reuqest ops
    b. PD -> Hot Read -> Store read keys, 有明显的读 Key 流量集中在 TiKV 8 实例上面；
    ![pd-hot-read-key](/images/TiKV/know-issue-tikv-hot-read-resolution3.png)
    c. TiKV -> Coprocessor Details -> 过滤 TiKV 8 实例的监控流量，可以明显看到 Read key 流量达到 1MB Ops
    ![hot-read-key](/images/TiKV/know-issue-tikv-hot-read-resolution6.png)
2. 通过 TiKV-details 监控的 Thread CPU -〉 United Read Pool 和 TiKV -> MBps 判断是否有大量读流量造成对应 TiKV 实例的 CPU 上涨；
    a. TiKV-details -> Thread CPU -> Unified Read Pool， 有明显的 CPU 异常在 TiKV 8 实例上面：
    ![Unified read pool](/images/TiKV/know-issue-tikv-hot-read-resolution1.png)
    b. TiKV-details -> Cluster -> MBps， 通过 TiKV 的 MBps 有明显的读流量请求，达到 450 MB/s 峰值
    ![read data vps](/images/TiKV/know-issue-tikv-hot-read-resolution2.png)
3. 根据监控中反馈的时间段和现象，通过 TiDB Dashboard 热力图排查是否存在读热点的流量和对应的 Table 和 Rows 的情况；
    a. Dashboard 热力读查看读数据热点情况，该截图中的数据热点，如果是索引热点会在 Table 下一层时对应的 Index Name。
     ![Read data flow](/images/TiKV/know-issue-tikv-hot-read-resolution4.png)   
4. 最后根据 Key range 记录的 Start key 和 End key 通过 Split region 操作进行数据打散；
    a. 通过获取 Start key 和 End key，这里直接右键复制 key 地址信息。
     ![Read data key](/images/TiKV/know-issue-tikv-hot-read-resolution5.png)
    b. 获取的 Key 地址信息举例, 读热点数据段信息

    ```text
    row_6917529027653378215 ~ row_6917529027653572552
    Start Key: 7480000000000006ff205f72e000000000ffbba0a70000000000fa
    End Key: 7480000000000006ff205f72e000000000ffbe97c80000000000fa
    ```

## Resolution

数据读热点情况，最好方案时通过架构层和业务逻辑层设计减少热点读请求在 TiDB 上面处理，最好将读热点数据缓存在业务层。

## Workarounds

1. 通过 [MOK 工具](https://github.com/oh-my-tidb/mok) 将 start key - end key 转化成 Row-id;
    a. 解析后使用 Row 键中存储的值，即为 Int64 位数据，可以通过该数据进行 Region split 操作；
    ![Mok 解析地址信息](/images/TiKV/know-issue-tikv-hot-read-resolution7.png)

2. 将 table 设置为禁止该表 region 被 merge, [参考文档修改表属性](https://docs.pingcap.com/zh/tidb/v5.4/table-attributes#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95-1) 参考样例：
     
    ```sql
     ALTER TABLE {table_name} ATTRIBUTES 'merge_option=deny';
    ```

3. 将 table 进行 split region 操作，拆分成多个 region；

    ```sql
    SPLIT TABLE t BETWEEN (-9223372036854775808) AND (9223372036854775807) REGIONS 16;
    ```

> **注意**
>
> - 该 Workaround 方案仅限于在表无法重建情况下，但是 Split region 对热点打散效果存在局限性，比如 Key range 较小的情况。
> - 建议考虑尽量将高频查询数据的请求前置到缓存层处理，另外如果是小于 64 MB 的配置表，可以通过 v6.0 版本的 [**缓存表功能**](https://docs.pingcap.com/zh/tidb/stable/cached-tables#%E7%BC%93%E5%AD%98%E8%A1%A8) 进行缓存。
> - 如果是索引读流量热点，TiDB v6.0 版本已经提供打散热点索引功能 [TIDB_SHARD](https://docs.pingcap.com/zh/tidb/stable/tidb-functions#tidb_shard) 方案，限制较多合理使用，仅支持单列索引的打散。
>

## Affected Versions

N/A