TiDB热点问题

为什么TiDB会有热点问题?

  1. 数据分布不均匀:
    TiDB 将数据分散存储在多个 TiKV 节点上,数据通过 Region 来组织,每个 Region 是一段连续的 Key 范围。如果数据的写入或访问模式导致某些 Region 的负载远高于其他 Region,就会出现热点。
  2. 表设计和主键选择:
    如果表的主键是单调递增的(如自增 ID),那么新插入的数据都会集中在一个 Region 上,这会导致写入热点。类似地,如果查询模式总是围绕某个特定的键值集中,那么这部分数据所在的 Region 也会成为读取热点。
  3. 调度和负载均衡策略:
    TiDB 依赖调度算法来实现数据的负载均衡。如果调度策略不够灵活或响应不够及时,可能无法迅速缓解热点问题。
  4. TiKV 节点性能差异:
    如果集群中的 TiKV 节点性能参差不齐,那么性能较低的节点可能会成为热点,因为它们处理请求的速度跟不上其他节点。
  5. 事务和访问模式:
    某些特定的事务或访问模式可能会频繁访问同一组数据,尤其是在业务高峰期间,这也可能导致热点。

1 AUTO_INCREMENT的热点

TiDB的数据是按照有序的range进行划分的,主键自增,会导致写入都发生在做最后的range上,因此最后的range会是热点。

从 TiDB 编码规则可知,同一个表的数据会在以表 ID 开头为前缀的一个 range 中,数据的顺序按照 RowID 的值顺序排列。在表 insert 的过程中如果 RowID 的值是递增的,则插入的行只能在末端追加。当 Region 达到一定的大小之后会进行分裂,分裂之后还是只能在 range 范围的末端追加,永远只能在一个 Region 上进行 insert 操作,形成热点。
常见的 increment 类型自增主键就是顺序递增的,默认情况下,在主键为整数型时,会用主键值当做 RowID ,此时 RowID 为顺序递增,在大量 insert 时形成表的写入热点。
同时,TiDB 中 RowID 默认也按照自增的方式顺序递增,主键不为整数类型时,同样会遇到写入热点的问题。

解决AUTO_INCREMENT的热点
使用AUTO_RANDOM来生成主键,将主键做了随机化。
弊端:失去了宏观上的有序性。

2 DATETIME的热点

TiDB中索引的编码方式:

Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue_rowID

在比较大小的时候从前往后比较,如果前面可以比较出大小就不往后比较。
有序的indexID DATETIME类型数据,让前段indexId值都不同,导致索引值和DATETIME分布完全相同,数据分布就没有随机性了。

DATETIME类型,包含了日期与时分秒(微秒)信息。按时间不停写入的数据,不停的在增长的有序数据,与AUTO_INCREMENT的主键类似,它也会不停的往最后一个range进行写入,因此最后一个range会成为热点。

解决DATETIME的热点

  1. 使用DATE类型,并且主键使用AUTO_RANDOM。缺点是无法存储时分秒,主键也失去了宏观上的自增性;
  2. 使用DATE类型,并且和另一个不自增的离散列创建组合索引。例如idx_gmt_create;
  3. 使用DATE类型,并且主键使用SHARD_ROW_ID_BITS。缺点是无法存储时分秒,主键失去了宏观上的自增性,并且SHARD_ROW_ID_BITS与主键使用聚簇相冲突,这会造成写入的放大以及主键查询需要做回表;
  4. 注意DATE类型即使在平时没有热点,在0点时刻也可能带来剧烈抖动
  5. 使用分区表,这样时间索引成为了分区内的Local索引,等于按分区做了打散。这是目前能想到的DATETIME类型上使用索引又避免热点的唯一方法,但代价也很大,TiDB目前不支持在分区表上创建全局索引,不带分区键的查询性能上也容易有问题,这对业务代码有很强的侵入性。

如何解决热点问题?

  1. 调整表结构和索引:优化数据模型,避免使用自增主键,因为这会导致写入操作集中在表的末尾。可以使用哈希、UUID 或者其他策略来分散写入。
  2. 分裂热点 Region:手动或自动分裂负载较高的 Region,使得热点数据分散到多个 Region 和多个 TiKV 节点上。
  3. 调整调度策略:通过调整 TiDB 的调度策略,使得热点数据能够更均匀地分布在多个 TiKV 节点上。
  4. 扩容集群:增加 TiKV 节点数量,提高集群的处理能力和存储容量。
  5. 使用 TiFlash:对于读取热点,可以使用 TiFlash 列存引擎来分担读取压力,TiFlash 能够加速分析型查询。
  6. 流量控制:对于高并发的写入或读取操作,可以通过限流等方式来控制单个节点的压力。

相关推荐

  1. TiDB热点问题

    2024-07-22 05:30:04       18 阅读
  2. 如何解决redis热点key问题

    2024-07-22 05:30:04       46 阅读
  3. hbase热点问题排查及处理

    2024-07-22 05:30:04       24 阅读
  4. 修复 Ubuntu 2204 Wi-Fi 热点无法连接问题

    2024-07-22 05:30:04       55 阅读
  5. 使用Qt在小米平板上热点使用问题记录

    2024-07-22 05:30:04       41 阅读
  6. 如何发现并解决 Redis 热点 Key 问题

    2024-07-22 05:30:04       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 05:30:04       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 05:30:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 05:30:04       45 阅读
  4. Python语言-面向对象

    2024-07-22 05:30:04       55 阅读

热门阅读

  1. setup中如何获取组件实例

    2024-07-22 05:30:04       17 阅读
  2. 编程中的智慧五:工厂设计模式

    2024-07-22 05:30:04       19 阅读
  3. 模型瘦身术:目标检测中的剪枝与量化

    2024-07-22 05:30:04       17 阅读
  4. 前端面试题日常练-day100 【Less】

    2024-07-22 05:30:04       15 阅读
  5. C++顶层const和底层const

    2024-07-22 05:30:04       17 阅读
  6. HOW - React 处理不紧急的更新和渲染

    2024-07-22 05:30:04       18 阅读
  7. kafka 基础知识

    2024-07-22 05:30:04       16 阅读
  8. 欧拉路径与欧拉回路

    2024-07-22 05:30:04       19 阅读
  9. Linux grep技巧 提取log中的json数据

    2024-07-22 05:30:04       12 阅读
  10. Python 异常处理

    2024-07-22 05:30:04       13 阅读
  11. Python中的__new__方法及实现单例模式

    2024-07-22 05:30:04       14 阅读