1. 首页 > 国产数据库教程 > TiDB教程 > 正文

tidb教程FG066-TiDB热点问题解决与优化

本文档风哥主要介绍TiDB热点问题解决与优化,包括热点问题的概念、热点问题的原因、热点问题的影响、预防策略、检测方法、优化原则、检测实施方案、优化实施方案、监控配置等内容,风哥教程参考TiDB官方文档性能优化相关内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。更多视频教程www.fgedu.net.cn

Part01-基础概念与理论知识

1.1 热点问题的概念

热点问题是指数据访问集中在某个Region或TiKV节点,导致该Region或节点负载过高的现象:学习交流加群风哥微信: itpux-com

热点问题的特点:

  • 访问集中:数据访问集中在某个Region或节点
  • 负载不均:部分节点负载过高,其他节点负载较低
  • 性能下降:整体系统性能下降,响应时间变长
  • 影响稳定性:可能导致节点过载,影响系统稳定性

1.2 热点问题的原因

热点问题的常见原因:

# 热点问题的原因

## 1. 写入热点
– 现象:大量写入操作集中在某个Region
– 原因:
– 自增主键:数据集中在末尾Region
– 顺序写入:数据按顺序写入,集中在少数Region
– 热点键:某些键被频繁写入
– 影响:导致对应Region成为热点,写入性能下降

## 2. 读取热点
– 现象:大量读取操作集中在某个Region
– 原因:
– 热门数据:某些数据被频繁读取
– 范围查询:范围查询覆盖的Region被频繁访问
– 全表扫描:全表扫描导致所有Region被访问
– 影响:导致对应Region成为热点,读取性能下降

## 3. 范围热点
– 现象:数据集中在某个范围的Region
– 原因:
– 数据分布不均:数据在物理存储上分布不均
– 索引设计不当:索引数据集中在少数Region
– 分区策略不当:分区数据集中在少数分区
– 影响:导致对应Region成为热点,性能下降

## 4. 业务逻辑问题
– 现象:业务操作导致数据集中访问
– 原因:
– 批量操作:批量插入、更新或删除操作
– 热点用户:某些用户的操作频率远高于其他用户
– 定时任务:定时任务集中执行,导致系统负载突增
– 影响:导致系统负载不均,性能下降

## 5. 系统配置问题风哥提示:
– 现象:系统配置不当导致热点问题
– 原因:
– Region分裂参数设置不当:导致Region过大或过小
– PD调度参数设置不当:导致Region分布不均
– TiKV参数设置不当:导致节点性能瓶颈
– 影响:系统性能下降,热点问题难以解决

1.3 热点问题的影响

热点问题的影响:

# 热点问题的影响

## 1. 性能下降
– 写入性能下降:热点Region写入竞争激烈,导致写入延迟增加
– 读取性能下降:热点Region读取并发高,导致读取延迟增加
– 系统吞吐量下降:整体系统处理能力下降
– 响应时间变长:业务操作响应时间变长,用户体验下降

## 2. 资源浪费
– 部分节点资源利用率低:负载低的节点资源未充分利用
– 存储不均衡:部分节点存储压力大,其他节点存储空闲
– 网络带宽浪费:热点节点网络流量大,其他节点网络带宽空闲

## 3. 系统不稳定
– 节点过载:热点节点可能因负载过高而崩溃
– 网络拥塞:热点节点网络流量大,可能导致网络拥塞
– 数据丢失风险:节点过载可能导致数据写入失败或丢失
– 服务不可用:严重的热点问题可能导致服务不可用

## 4. 维护困难
– 备份恢复时间长:热点数据备份恢复时间增加
– 升级迁移困难:热点数据升级迁移时间增加
– 故障处理复杂:热点问题导致故障定位和处理更加复杂
– 系统扩展困难:热点问题限制系统扩展能力

风哥提示:热点问题是TiDB集群常见的性能问题,需要及时发现和处理,避免影响系统性能和稳定性。学习交流加群风哥QQ113257174

Part02-生产环境规划与建议

2.1 预防策略

预防策略要点:

# 预防策略

## 1. 主键设计
– 使用分散的主键:如UUID、哈希值等,避免自增ID导致的热点
– 复合主键:结合多个字段作为主键,增加数据分布的均匀性
– 避免使用字符串作为主键:字符串长度差异大,可能导致数据分布不均

## 2. 索引设计
– 合理选择索引列:选择取值范围大、重复值少的列作为索引
– 复合索引:结合多个列创建索引,增加索引的选择性
– 避免在高频更新的列上创建索引:减少索引维护开销

## 3. 分区设计
– 合理分区:根据业务需求和数据分布进行分区
– 分区键选择:选择分布均匀的列作为分区键
– 分区数量:根据数据量和查询模式确定合理的分区数量

## 4. 数据导入
– 批量导入:使用TiDB Lightning等工具进行批量导入
– 数据打散:导入数据时对数据进行打散,避免顺序写入
– 并发导入:使用多线程并发导入,提高导入速度

## 5. 业务逻辑优化
– 避免热点操作:如避免频繁更新同一数据
– 错峰操作:避开业务高峰期进行批量操作
– 数据预热:提前加载热点数据,减少突发访问
– 异步处理:将非实时操作异步处理,降低同步压力

## 6. 系统配置优化
– 调整Region分裂参数:根据数据量和访问模式调整
– 调整PD调度参数:优化Region分布和Leader分布
– 调整TiKV参数:根据硬件配置调整内存、IO等参数
– 调整TiDB参数:优化SQL执行计划,提高查询性能

2.2 检测方法

检测方法要点:

# 检测方法

## 1. 监控工具
– TiDB Dashboard:查看集群整体状态,包括热点Region、节点负载等
– Prometheus + Grafana:监控TiKV节点的CPU、内存、IO、网络等指标
– 系统工具:top、iostat、iftop等,查看节点负载情况

## 2. SQL查询
– 查看热点Region:
SELECT * FROM information_schema.tikv_region_status WHERE db_name = ‘fgedudb’ ORDER BY region_size DESC LIMIT 10;
– 查看TiKV节点负载:
SELECT store_id, COUNT(*) AS region_count, SUM(region_size) AS total_size FROM information_schema.tikv_region_status GROUP BY store_id;
– 查看SQL执行计划:学习交流加群风哥QQ113257174
EXPLAIN SELECT * FROM fgedu_orders WHERE id > 1000;

## 3. 日志分析
– TiKV日志:分析TiKV节点的日志,查看是否有热点Region相关的警告
– PD日志:分析PD调度日志,查看是否有Region均衡相关的问题
– TiDB日志:分析TiDB的SQL执行日志,查看是否有慢查询

## 4. 性能测试
– 压力测试:使用sysbench等工具进行压力测试,观察系统性能
– 负载测试:模拟业务负载,观察系统响应时间
– 并发测试:测试系统在高并发下的性能表现

## 5. 业务监控
– 应用层监控:监控应用的响应时间和错误率
– 用户体验监控:监控用户操作的响应时间
– 业务指标监控:监控业务关键指标,如订单处理速度等

2.3 优化原则

优化原则要点:

# 优化原则

## 1. 热点分散
– 目标:分散热点数据,避免单点热
– 方法:
– 手动分裂热点Region
– 优化业务逻辑,避免热点操作
– 使用分散的主键
– 合理设计索引

## 2. 负载均衡
– 目标:各TiKV节点的负载均衡
– 方法:
– 调整PD调度参数
– 优化Region分布
– 合理配置TiKV节点资源
– 增加TiKV节点,扩展集群

## 3. 性能优化
– 目标:提高系统性能和响应速度
– 方法:
– 优化SQL语句
– 调整TiDB参数
– 合理配置硬件资源
– 使用缓存,减少数据库访问

## 4. 稳定性保障
– 目标:确保系统稳定运行
– 方法:
– 定期监控和维护
– 建立完善的告警机制
– 制定应急预案
– 定期备份数据

## 5. 可扩展性
– 目标:系统能够应对业务增长
– 方法:
– 合理规划集群规模
– 预留足够的资源
– 支持水平扩展
– 优化数据分布

生产环境建议:根据业务需求和系统实际情况,选择合适的预防策略和检测方法,及时发现和处理热点问题,确保系统性能和稳定性。更多学习教程公众号风哥教程itpux_com

Part03-生产环境项目实施方案

3.1 检测实施方案

3.1.1 监控配置

# 监控配置

## 1. 配置Prometheus和Grafana

### 1.1 安装Prometheus
$ wget https://github.com/prometheus/prometheus/releases/download/v2.30.3/prometheus-2.30.3.linux-amd64.tar.gz
$ tar -xzf prometheus-2.30.3.linux-amd64.tar.gz
$ mv prometheus-2.30.3.linux-amd64 /tidb/app/prometheus

### 1.2 配置Prometheus
$ vim /tidb/app/prometheus/prometheus.yml

global:
scrape_interval: 15s
evaluation_interval: 15s

alerting:
alertmanagers:
– static_configs:
– targets:
– localhost:9093

rule_files:
– “rules/*.yml”

scrape_configs:
– job_name: ‘tidb’
static_configs:
– targets: [‘192.168.1.10:10080’]

– job_name: ‘pd’
static_configs:
– targets: [‘192.168.1.10:2379’]

– job_name: ‘tikv’
static_configs:
– targets: [‘192.168.1.20:20180’, ‘192.168.1.21:20180’, ‘192.168.1.22:20180’]

### 1.3 启动Prometheus
$ /tidb/app/prometheus/prometheus –config.file=/tidb/app/prometheus/prometheus.yml

### 1.4 安装Grafana
$ wget https://dl.grafana.com/oss/release/grafana-8.3.3.linux-amd64.tar.gz
$ tar -xzf grafana-8.3.3.linux-amd64.tar.gz
$ mv grafana-8.3.3 /tidb/app/grafana

### 1.5 启动Grafana
$ /tidb/app/grafana/bin/grafana-server –homepath=/tidb/app/grafana

### 1.6 配置Grafana数据源
– 登录Grafana:http://192.168.1.10:3000
– 用户名:admin,密码:admin
– 添加数据源:选择Prometheus,URL填写http://localhost:9090
– 导入TiDB dashboard模板

## 2. 配置TiDB Dashboard

### 2.1 访问TiDB Dashboard
– 访问地址:http://192.168.1.10:2379/dashboard
– 用户名:root,密码:空

### 2.2 查看热点Region
– 进入”集群信息” -> “热点可视化”
– 查看热点Region分布情况

### 2.3 查看节点负载
– 进入”集群信息” -> “TiKV Store”
– 查看各Store的CPU、内存、IO等指标

3.1.2 热点检测

# 热点检测

## 1. 检测热点Region
mysql> SELECT region_id, db_name, table_name, region_size, leader_store_id
-> FROM information_schema.tikv_region_status
-> WHERE db_name = ‘fgedudb’
-> ORDER BY region_size DESC
-> LIMIT 10;

# 输出示例
+———–+———+————+————+—————+
| region_id | db_name | table_name | region_size | leader_store_id |
+———–+———+————+————+—————+
| 1 | fgedudb | fgedu_orders | 104857600 | 1 |
| 2 | fgedudb | fgedu_users | 52428800 | 1 |
| 3 | fgedudb | fgedu_products | 26214400 | 2 |
+———–+———+————+————+—————+

## 2. 检测TiKV节点负载
$ top

# 输出示例
top – 10:00:00 up 10 days, 1:00, 1 user, load average: 0.50, 0.40, 0.30
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 5.0 us, 0.5 sy, 0.0 ni, 94.0 id, 0.0 wa, 0.0 hi, 0.5 si, 0.0 st
MiB Mem : 16384.0 total, 8192.0 free, 4096.0 used, 4096.0 buff/cache
MiB Swap: 8192.0 total, 8192.0 free, 0.0 used. 12288.0 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 tidb 20 0 8192.0m 2048.0m 512.0m S 80.0 12.5 1:00.00 tikv-server

## 3. 检测SQL执行计划
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE user_id = 1000;

# 输出示例
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+
| id | estRows | task | access object | operator info | memory | disk | execution info | cost | rows |
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+
| IndexLookUp_10 | 10.00 | root | | | 32.77 KB | N/A | time:0.1ms, loops:2, rows:1 | 10.00 | 1 |
| ├─IndexRangeScan_8 | 10.00 | cop[tikv] | table:fgedu_orders, index:idx_user_id(user_id) | range:[1000,1000], keep order:false | N/A | N/A | time:0.1ms, loops:1, rows:1 | 10.00 | 1 |
| └─TableRowIDScan_9 | 10.00 | cop[tikv] | table:fgedu_orders | | N/A | N/A | time:0.1ms, loops:1, rows:1 | 10.00 | 1 |
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+

## 4. 检测网络流量
$ iftop -i eth0

# 输出示例
interface: eth0
IP address is: 192.168.1.20
MAC address is: 00:00:00:00:00:00

# host last 2s last 10s last 40s cumulative
1 192.168.1.10:2379 <- 192.168.1.20:40000 100Kb 100Kb 100Kb 1000Kb 2 192.168.1.10:4000 <- 192.168.1.20:20160 50Kb 50Kb 50Kb 500Kb 3 192.168.1.21:20160 <-> 192.168.1.20:20160 20Kb 20Kb 20Kb 200Kb

## 5. 检测业务指标
– 查看应用响应时间:监控系统中的应用响应时间指标
– 查看订单处理速度:监控系统中的订单处理速度指标
– 查看错误率:监控系统中的错误率指标

3.2 优化实施方案

3.2.1 写入热点优化

# 写入热点优化

## 1. 手动分裂热点Region

### 1.1 查看热点Region
mysql> SELECT region_id, db_name, table_name, region_size
-> FROM information_schema.tikv_region_status
-> WHERE db_name = ‘fgedudb’ AND table_name = ‘fgedu_orders’
-> ORDER BY region_size DESC
-> LIMIT 5;

# 输出示例
+———–+———+————+————+
| region_id | db_name | table_name | region_size |
+———–+———+————+————+
| 1 | fgedudb | fgedu_orders | 104857600 |
+———–+———+————+————+

### 1.2 手动分裂Region
mysql> ADMIN SPLIT REGION 1 BY ‘t_1000_40000000’, ‘t_1000_60000000’;

# 输出示例
Query OK, 0 rows affected (0.01 sec)

### 1.3 查看分裂后的Region
mysql> SELECT region_id, db_name, table_name, region_size
-> FROM information_schema.tikv_region_status
-> WHERE db_name = ‘fgedudb’ AND table_name = ‘fgedu_orders’;

# 输出示例
+———–+———+————+————+
| region_id | db_name | table_name | region_size |
+———–+———+————+————+
| 1 | fgedudb | fgedu_orders | 34952533 |
| 2 | fgedudb | fgedu_orders | 34952533 |
| 3 | fgedudb | fgedu_orders | 34952534 |
+———–+———+————+————+

## 2. 优化主键设计

### 2.1 查看当前主键
mysql> SHOW CREATE TABLE fgedu_orders;

# 输出示例
+————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+
| Table | Create Table |
+————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+
| fgedu_orders | CREATE TABLE `fgedu_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`amount` decimal(10,2) NOT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+

### 2.2 修改主键为UUID
mysql> ALTER TABLE fgedu_orders DROP PRIMARY KEY, ADD PRIMARY KEY (`id`);
mysql> ALTER TABLE fgedu_orders MODIFY COLUMN `id` VARCHAR(36) NOT NULL;
mysql> UPDATE fgedu_orders SET id = UUID();

# 输出示例
Query OK, 1000000 rows affected (10.00 sec)

## 3. 优化业务逻辑

### 3.1 批量插入优化
– 避免单条插入,使用批量插入
– 分散插入数据,避免顺序写入

### 3.2 热点更新优化
– 减少对同一数据的频繁更新
– 使用缓存,减少数据库访问
– 异步更新,降低同步压力

## 4. 调整PD调度参数

### 4.1 修改PD配置
$ vim /tidb/app/pd/conf/pd.toml

[scheduler]
# 调整热点调度限制
hot-region-schedule-limit = 8
# 调整领导者调度限制
leader-schedule-limit = 8

### 4.2 重启PD
$ systemctl restart pd

### 4.3 手动触发热点调度
mysql> ADMIN SCHEDULER CONFIGURE hot-region, “{\”enable\”: true}”;

# 输出示例
Query OK, 0 rows affected (0.01 sec)

3.2.2 读取热点优化

# 读取热点优化

## 1. 使用缓存

### 1.1 配置Redis缓存
$ wget https://download.redis.io/releases/redis-6.2.6.tar.gz
$ tar -xzf redis-6.2.6.tar.gz
$ cd redis-6.2.6
$ make
$ make install

### 1.2 启动Redis
$ redis-server /etc/redis.conf

### 1.3 应用层集成Redis
– 在应用代码中集成Redis,缓存热点数据
– 设置合理的缓存过期时间
– 实现缓存穿透、缓存击穿、缓存雪崩的防护

## 2. 优化SQL语句

### 2.1 查看慢查询
mysql> SHOW GLOBAL VARIABLES LIKE ‘%slow_query%’;

# 输出示例
+———————+——————————-+
| Variable_name | Value |
+———————+——————————-+
| slow_query_log | ON |
| slow_query_log_file | /tidb/app/tidb/slow-query.log |
| long_query_time | 1.0 |
+———————+——————————-+

### 2.2 分析慢查询
$ cat /tidb/app/tidb/slow-query.log

### 2.3 优化SQL语句
– 添加合适的索引
– 避免全表扫描
– 优化JOIN操作
– 减少查询返回的数据量

## 3. 分区表优化

### 3.1 创建分区表
mysql> CREATE TABLE fgedu_orders_partitioned (
-> id VARCHAR(36) PRIMARY KEY,
-> user_id INT NOT NULL,
-> product_id INT NOT NULL,
-> amount DECIMAL(10,2) NOT NULL,
-> order_time DATETIME NOT NULL
-> ) PARTITION BY RANGE (YEAR(order_time)) (
-> PARTITION p2023 VALUES LESS THAN (2024),
-> PARTITION p2024 VALUES LESS THAN (2025),
-> PARTITION p2025 VALUES LESS THAN (2026)
-> );

# 输出示例
Query OK, 0 rows affected (0.02 sec)

### 3.2 迁移数据到分区表
mysql> INSERT INTO fgedu_orders_partitioned SELECT * FROM fgedu_orders;

# 输出示例
Query OK, 1000000 rows affected (5.00 sec)

### 3.3 查看分区数据分布
mysql> SELECT partition_name, table_rows
-> FROM information_schema.partitions
-> WHERE table_schema = ‘fgedudb’ AND table_name = ‘fgedu_orders_partitioned’
-> ORDER BY partition_name;

# 输出示例
+—————-+————+
| partition_name | table_rows |
+—————-+————+
| p2023 | 300000 |
| p2024 | 500000 |
| p2025 | 200000 |
+—————-+————+

## 4. 调整TiDB参数

### 4.1 修改TiDB配置
$ vim /tidb/app/tidb/conf/tidb.toml

[performance]
# 调整查询内存限制
tidb_mem_quota_query = 1073741824
# 调整并发连接数
max-connections = 1000

### 4.2 重启TiDB
$ systemctl restart tidb

### 4.3 查看TiDB参数
mysql> SHOW CONFIG WHERE type = ‘tidb’ AND name LIKE ‘%mem%’;

# 输出示例
+——+————————-+————-+———-+
| Type | Name | Value | Source |
+——+————————-+————-+———-+
| tidb | performance.tidb_mem_quota_query | 1073741824 | file |
+——+————————-+————-+———-+

3.2.3 监控配置

# 监控配置

## 1. 配置Prometheus告警规则

### 1.1 创建告警规则文件
$ mkdir -p /tidb/app/prometheus/rules
$ vim /tidb/app/prometheus/rules/tidb_alerts.yml

groups:
– name: tidb
rules:
– alert: TiKVHotRegion
expr: |
sum(tikv_server_requests_total{type=”read”}) by (region_id) > 1000
for: 5m
labels:
severity: warning
annotations:
summary: “TiKV Hot Region”
description: “Hot region detected. Region ID: {{ $labels.region_id }}”

– alert: TiKVHighCPU
expr: |
avg(tikv_process_cpu_seconds_total) by (instance) > 80
for: 5m
labels:
severity: warning
annotations:
summary: “TiKV High CPU Usage”
description: “TiKV CPU usage is high. Instance: {{ $labels.instance }}”

– alert: TiKVHighMemory
expr: |
avg(tikv_process_memory_bytes) by (instance) / (1024 * 1024 * 1024) > 8
for: 5m
labels:
severity: warning
annotations:
summary: “TiKV High Memory Usage”
description: “TiKV memory usage is high. Instance: {{ $labels.instance }}”

## 2. 配置AlertManager

### 2.1 安装AlertManager
$ wget https://github.com/prometheus/alertmanager/releases/download/v0.23.0/alertmanager-0.23.0.linux-amd64.tar.gz
$ tar -xzf alertmanager-0.23.0.linux-amd64.tar.gz
$ mv alertmanager-0.23.0.linux-amd64 /tidb/app/alertmanager

### 2.2 配置AlertManager
$ vim /tidb/app/alertmanager/alertmanager.yml

global:
resolve_timeout: 5m

route:
group_by: [‘alertname’]
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: ’email’

receivers:
– name: ’email’
email_configs:
– to: ‘admin@fgedu.net.cn’
from: ‘alertmanager@fgedu.net.cn’
smarthost: ‘smtp.fgedu.net.cn:587’
auth_username: ‘alertmanager’
auth_password: ‘password’

## 3. 启动AlertManager
$ /tidb/app/alertmanager/alertmanager –config.file=/tidb/app/alertmanager/alertmanager.yml

## 4. 验证监控配置
– 访问Prometheus:http://192.168.1.10:9090
– 访问Grafana:http://192.168.1.10:3000
– 访问AlertManager:http://192.168.1.10:9093

风哥提示:监控配置是发现和处理热点问题的关键,需要建立完善的监控体系,及时发现和处理热点问题。from tidb视频:www.itpux.com

Part04-生产案例与实战讲解

4.1 写入热点

4.1.1 写入热点问题

# 写入热点问题

## 1. 问题描述
– 现象:写入操作集中在某个Region,导致该Region所在的TiKV节点负载过高
– 原因:自增主键导致数据集中在末尾Region,顺序写入导致热点
– 影响:写入性能下降,系统响应时间变长

## 2. 检测写入热点

### 2.1 查看热点Region
mysql> SELECT region_id, db_name, table_name, region_size, leader_store_id
-> FROM information_schema.tikv_region_status
-> WHERE db_name = ‘fgedudb’
-> ORDER BY region_size DESC
-> LIMIT 5;

# 输出示例
+———–+———+————+————+—————+
| region_id | db_name | table_name | region_size | leader_store_id |
+———–+———+————+————+—————+
| 1 | fgedudb | fgedu_orders | 104857600 | 1 |
+———–+———+————+————+—————+

### 2.2 查看TiKV节点负载
$ top

# 输出示例
top – 10:00:00 up 10 days, 1:00, 1 user, load average: 0.50, 0.40, 0.30
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 5.0 us, 0.5 sy, 0.0 ni, 94.0 id, 0.0 wa, 0.0 hi, 0.5 si, 0.0 st
MiB Mem : 16384.0 total, 8192.0 free, 4096.0 used, 4096.0 buff/cache
MiB Swap: 8192.0 total, 8192.0 free, 0.0 used. 12288.0 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 tidb 20 0 8192.0m 2048.0m 512.0m S 80.0 12.5 1:00.00 tikv-server

## 3. 解决方案

### 3.1 手动分裂热点Region
mysql> ADMIN SPLIT REGION 1 BY ‘t_1000_40000000’, ‘t_1000_60000000’;

# 输出示例
Query OK, 0 rows affected (0.01 sec)

### 3.2 优化主键设计
mysql> ALTER TABLE fgedu_orders DROP PRIMARY KEY, ADD PRIMARY KEY (`id`);
mysql> ALTER TABLE fgedu_orders MODIFY COLUMN `id` VARCHAR(36) NOT NULL;
mysql> UPDATE fgedu_orders SET id = UUID();

# 输出示例
Query OK, 1000000 rows affected (10.00 sec)

### 3.3 调整PD调度参数
$ vim /tidb/app/pd/conf/pd.toml

[scheduler]
# 调整热点调度限制
hot-region-schedule-limit = 8

### 3.4 重启PD
$ systemctl restart pd

### 3.5 手动触发热点调度
mysql> ADMIN SCHEDULER CONFIGURE hot-region, “{\”enable\”: true}”;

# 输出示例
Query OK, 0 rows affected (0.01 sec)

## 4. 验证优化效果
– 查看TiKV节点CPU使用率:top
– 查看写入性能:sysbench –test=oltp_write_only –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password= –mysql-db=fgedudb –tables=1 –table-size=1000000 –threads=16 –time=60 run
– 查看SQL执行时间:SET profiling = 1; INSERT INTO fgedu_orders VALUES (UUID(), 1000, 2000, 100.00, NOW()); SHOW PROFILES;

4.2 读取热点

4.2.1 读取热点问题

# 读取热点问题

## 1. 问题描述
– 现象:读取操作集中在某个Region,导致该Region所在的TiKV节点负载过高
– 原因:热门数据被频繁读取,范围查询覆盖的Region被频繁访问
– 影响:读取性能下降,系统响应时间变长

## 2. 检测读取热点

### 2.1 查看热点Region
mysql> SELECT region_id, db_name, table_name, region_size, leader_store_id
-> FROM information_schema.tikv_region_status
-> WHERE db_name = ‘fgedudb’
-> ORDER BY region_size DESC
-> LIMIT 5;

# 输出示例
+———–+———+————+————+—————+
| region_id | db_name | table_name | region_size | leader_store_id |
+———–+———+————+————+—————+
| 2 | fgedudb | fgedu_users | 52428800 | 1 |
+———–+———+————+————+—————+

### 2.2 查看慢查询
$ cat /tidb/app/tidb/slow-query.log

# 输出示例
# Time: 2024-01-01T10:00:00.000000+08:00
# User@Host: root[root] @ localhost [] Id: 12345
# Query_time: 1.234567 Lock_time: 0.000000 Rows_sent: 1000 Rows_examined: 1000000
SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;

## 3. 解决方案

### 3.1 使用缓存

#### 3.1.1 安装Redis
$ wget https://download.redis.io/releases/redis-6.2.6.tar.gz
$ tar -xzf redis-6.2.6.tar.gz
$ cd redis-6.2.6
$ make
$ make install

#### 3.1.2 启动Redis
$ redis-server /etc/redis.conf

#### 3.1.3 应用层集成Redis
– 在应用代码中集成Redis,缓存热点数据
– 设置合理的缓存过期时间
– 实现缓存穿透、缓存击穿、缓存雪崩的防护

### 3.2 优化SQL语句

#### 3.2.1 添加索引
mysql> CREATE INDEX idx_name ON fgedu_users (name);

# 输出示例
Query OK, 0 rows affected (1.00 sec)

#### 3.2.2 优化查询
mysql> EXPLAIN SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;

# 输出示例
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+
| id | estRows | task | access object | operator info | memory | disk | execution info | cost | rows |
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+
| TableReader_5 | 1000.00 | root | | data:Selection_4 | 32.77 KB | N/A | time:0.1ms, loops:2, rows:1 | 10.00 | 1 |
| └─Selection_4 | 1000.00 | cop[tikv] | | like(fgedu_users.name, ‘%test%’) | N/A | N/A | time:0.1ms, loops:1, rows:1 | 10.00 | 1 |
| └─TableFullScan_3 | 1000000.00 | cop[tikv] | table:fgedu_users | keep order:false | N/A | N/A | time:0.1ms, loops:1, rows:1 | 10.00 | 1 |
+————————-+———-+———–+————————+——————————–+—————+———+——————————–+——+———-+

### 3.3 分区表优化

#### 3.3.1 创建分区表
mysql> CREATE TABLE fgedu_users_partitioned (
-> id VARCHAR(36) PRIMARY KEY,
-> name VARCHAR(100) NOT NULL,
-> email VARCHAR(100) NOT NULL,
-> phone VARCHAR(20) NOT NULL,
-> create_time DATETIME NOT NULL
-> ) PARTITION BY RANGE (YEAR(create_time)) (
-> PARTITION p2023 VALUES LESS THAN (2024),
-> PARTITION p2024 VALUES LESS THAN (2025),
-> PARTITION p2025 VALUES LESS THAN (2026)
-> );

# 输出示例
Query OK, 0 rows affected (0.02 sec)

#### 3.3.2 迁移数据到分区表
mysql> INSERT INTO fgedu_users_partitioned SELECT * FROM fgedu_users;

# 输出示例
Query OK, 500000 rows affected (5.00 sec)

## 4. 验证优化效果
– 查看TiKV节点CPU使用率:top
– 查看读取性能:sysbench –test=oltp_read_only –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password= –mysql-db=fgedudb –tables=1 –table-size=1000000 –threads=16 –time=60 run
– 查看SQL执行时间:SET profiling = 1; SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’; SHOW PROFILES;

4.3 范围热点

4.3.1 范围热点问题

# 范围热点问题

## 1. 问题描述
– 现象:数据集中在某个范围的Region,导致该范围的Region成为热点
– 原因:数据分布不均,索引设计不当,分区策略不当
– 影响:性能下降,管理开销增加

## 2. 检测范围热点

### 2.1 查看Region分布
mysql> SELECT peer_store_id, COUNT(*) AS region_count, SUM(region_size) AS total_size
-> FROM information_schema.tikv_region_status
-> GROUP BY peer_store_id
-> ORDER BY region_count DESC;

# 输出示例
+————-+————–+————+
| peer_store_id | region_count | total_size |
+————-+————–+————+
| 1 | 1000 | 10737418240 |
| 2 | 800 | 8589934592 |
| 3 | 700 | 7516192768 |
+————-+————–+————+

### 2.2 查看分区数据分布
mysql> SELECT partition_name, table_rows
-> FROM information_schema.partitions
-> WHERE table_schema = ‘fgedudb’ AND table_name = ‘fgedu_orders_partitioned’
-> ORDER BY table_rows DESC;

# 输出示例
+—————-+————+
| partition_name | table_rows |
+—————-+————+
| p202401 | 800000 |
| p202402 | 150000 |
| p202403 | 50000 |
+—————-+————+

## 3. 解决方案

### 3.1 调整分区策略
mysql> ALTER TABLE fgedu_orders_partitioned REORGANIZE PARTITION p202401 INTO (
-> PARTITION p20240101 VALUES LESS THAN (20240102),
-> PARTITION p20240102 VALUES LESS THAN (20240103),
-> …
-> PARTITION p20240131 VALUES LESS THAN (20240201)
-> );

# 输出示例
Query OK, 800000 rows affected (10.00 sec)

### 3.2 优化索引设计

#### 3.2.1 查看当前索引
mysql> SHOW INDEX FROM fgedu_orders;

# 输出示例
+————+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+————+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+
| fgedu_orders | 0 | PRIMARY | 1 | id | A | 1000000 | NULL | NULL | | BTREE | |
+————+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+

#### 3.2.2 添加复合索引
mysql> CREATE INDEX idx_user_product ON fgedu_orders (user_id, product_id);

# 输出示例
Query OK, 0 rows affected (1.00 sec)

### 3.3 调整PD调度参数

#### 3.3.1 修改PD配置
$ vim /tidb/app/pd/conf/pd.toml

[scheduler]
# 调整存储均衡阈值
store-balance-rate = 20
# 调整最大调度数量
max-schedule-count = 32

#### 3.3.2 重启PD
$ systemctl restart pd

#### 3.3.3 手动触发均衡
mysql> ADMIN SCHEDULER CONFIGURE balance-region, “{\”enable\”: true}”;

# 输出示例
Query OK, 0 rows affected (0.01 sec)

## 4. 验证优化效果
– 查看Region分布:SELECT peer_store_id, COUNT(*) AS region_count FROM information_schema.tikv_region_status GROUP BY peer_store_id;
– 查看分区数据分布:SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_schema = ‘fgedudb’ AND table_name = ‘fgedu_orders_partitioned’;
– 查看查询性能:SET profiling = 1; SELECT * FROM fgedu_orders WHERE user_id = 1000 AND product_id = 2000; SHOW PROFILES;

生产环境建议:在处理热点问题时,需要根据具体情况选择合适的解决方案,结合监控工具及时发现和处理热点问题,确保系统性能和稳定性。

Part05-风哥经验总结与分享

5.1 最佳实践

最佳实践:

  • 主键设计:使用分散的主键,如UUID、哈希值等,避免自增ID导致的热点
  • 索引设计:合理选择索引列,避免在高频更新的列上创建索引
  • 分区设计:根据业务需求和数据分布进行分区,选择合适的分区键
  • 数据导入:使用TiDB Lightning等工具进行批量导入,数据打散后导入
  • 业务逻辑优化:避免热点操作,错峰处理批量操作
  • 监控配置:建立完善的监控体系,及时发现和处理热点问题
  • 定期维护:定期检查数据分布,清理无用数据,优化性能
  • 参数调优:根据集群规模和硬件配置调整TiDB参数

5.2 常见问题与解决方案

常见问题与解决方案:

# 常见问题与解决方案

## 1. 写入热点
– 问题:自增主键导致数据集中在末尾Region
– 解决方案:
– 使用UUID或哈希值作为主键
– 手动分裂热点Region
– 调整PD热点调度参数

## 2. 读取热点
– 问题:热门数据被频繁读取
– 解决方案:
– 使用缓存,减少数据库访问
– 优化SQL语句,添加合适的索引
– 分区表优化,分散数据

## 3. 范围热点
– 问题:数据集中在某个范围的Region
– 解决方案:
– 调整分区策略,增加分区数量
– 优化索引设计,选择合适的索引列
– 调整PD调度参数,优化Region分布

## 4. 系统负载不均
– 问题:各TiKV节点负载不均
– 解决方案:
– 调整PD调度参数,优化Region分布
– 手动触发均衡
– 增加TiKV节点,扩展集群

## 5. 性能下降
– 问题:系统性能下降,响应时间变长
– 解决方案:
– 检测并处理热点问题
– 优化SQL语句
– 调整TiDB参数
– 增加硬件资源

## 6. 监控告警
– 问题:无法及时发现热点问题
– 解决方案:
– 配置Prometheus和Grafana
– 设置合理的告警阈值
– 定期分析监控数据

5.3 性能调优技巧

# 性能调优技巧

## 1. 热点分散
– 手动分裂热点Region:提前分裂热点Region,分散热点
– 使用分散的主键:避免自增ID导致的热点
– 优化业务逻辑:避免热点操作,错峰处理批量操作
– 使用缓存:减少数据库访问,缓解热点压力

## 2. 负载均衡
– 调整PD调度参数:优化Region分布和Leader分布
– 手动触发均衡:在集群拓扑变化后手动触发均衡
– 增加TiKV节点:扩展集群,提高系统处理能力
– 合理配置TiKV节点资源:根据硬件配置调整参数

## 3. SQL优化
– 优化SQL语句:避免全表扫描,添加合适的索引
– 优化JOIN操作:减少JOIN操作的复杂度
– 减少查询返回的数据量:只查询必要的字段
– 使用分页查询:避免一次性查询大量数据

## 4. 系统配置优化
– 调整Region分裂参数:根据数据量和访问模式调整
– 调整TiKV参数:根据硬件配置调整内存、IO等参数
– 调整TiDB参数:优化SQL执行计划,提高查询性能
– 调整PD参数:优化调度策略,提高系统性能

## 5. 监控与告警
– 建立完善的监控体系:使用Prometheus + Grafana监控系统状态
– 设置合理的告警阈值:及时发现和处理热点问题
– 定期分析监控数据:根据监控数据优化系统配置
– 建立故障处理流程:快速响应和处理热点问题

## 6. 硬件优化
– 使用高性能存储:如SSD,提高数据读写速度
– 增加网络带宽:提高节点间通信速度
– 优化服务器配置:根据集群规模选择合适的服务器配置
– 合理规划集群拓扑:避免网络瓶颈

风哥提示:热点问题是TiDB集群常见的性能问题,需要从设计、配置、监控等多个方面进行优化。建议建立完善的管理体系,及时发现和处理热点问题,确保系统的性能和稳定性。

持续改进:热点问题处理是一个持续的过程,需要根据系统的变化和业务的增长不断调整和改进。建议定期进行性能评估和优化,确保系统能够满足业务的需求。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息