本文档风哥主要介绍TiDB高并发写入性能优化的方法和技巧,包括高并发写入相关概念、TiDB写入架构、影响写入性能的因素、性能指标、硬件规划、配置规划、schema设计、优化步骤、调优方法、基准测试流程、实战案例和最佳实践等,风哥教程参考TiDB官方文档性能优化相关内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 高并发写入相关概念
高并发写入相关的基本概念:
## 1. 并发写入
– **并发写入**:多个客户端同时向数据库写入数据的操作
– **写入吞吐量**:单位时间内成功写入的数据量
– **写入延迟**:从写入请求发出到完成的时间
– **并发度**:同时进行的写入操作数量
## 2. 事务相关
– **事务**:一组原子性的数据库操作
– **ACID特性**:原子性、一致性、隔离性、持久性
– **事务隔离级别**:读未提交、读已提交、可重复读、串行化
– **事务大小**:事务中包含的操作数量
## 3. 写入类型
– **单条写入**:每次写入一条数据
– **批量写入**:一次写入多条数据
– **事务写入**:在事务中执行的写入操作
– **非事务写入**:不在事务中执行的写入操作
## 4. 性能瓶颈
– **网络瓶颈**:网络带宽限制
– **CPU瓶颈**:CPU处理能力限制
– **I/O瓶颈**:磁盘I/O速度限制
– **内存瓶颈**:内存容量限制
– **锁竞争**:并发写入导致的锁竞争
1.2 TiDB写入架构
风哥提示:
TiDB的写入架构:
## 1. 写入流程
– **客户端**:发送写入请求
– **TiDB服务器**:接收请求,解析SQL,生成执行计划
– **PD**:提供集群元数据,分配全局ID
– **TiKV**:存储数据,处理写入操作
– **Raft协议**:保证数据一致性
## 2. 写入路径
1. **SQL解析**:TiDB解析SQL语句
2. **执行计划生成**:生成执行计划
3. **事务处理**:处理事务逻辑
4. **数据编码**:将数据编码为Key-Value格式
5. **Raft复制**:通过Raft协议复制数据到多个TiKV节点
6. **持久化**:将数据持久化到磁盘
7. **响应客户端**:返回写入结果
## 3. 关键组件
– **TiDB**:SQL层,处理SQL解析和执行
– **PD**:元数据管理,调度和负载均衡
– **TiKV**:存储层,处理数据存储和复制
– **Raft**:分布式一致性协议
## 4. 写入特点
– **分布式写入**:数据分布在多个TiKV节点
– **强一致性**:通过Raft协议保证数据一致性
– **水平扩展**:支持通过增加节点扩展写入能力
– **事务支持**:支持ACID事务
1.3 影响写入性能的因素
影响TiDB高并发写入性能的因素:
- 硬件配置:CPU、内存、磁盘、网络等硬件性能
- 集群规模:TiKV节点数量和分布
- 配置参数:TiDB、PD、TiKV的配置参数
- Schema设计:表结构、索引设计、分区策略
- 写入模式:单条写入 vs 批量写入,事务写入 vs 非事务写入
- 并发控制:锁竞争、事务冲突
- 数据分布:数据是否均匀分布,是否存在热点
- 网络延迟:节点间网络延迟
- 磁盘I/O:磁盘读写速度,I/O调度策略
- 系统负载:其他业务的影响
1.4 性能指标
TiDB高并发写入的性能指标:
## 1. 写入吞吐量
– **QPS**:每秒执行的查询数
– **TPS**:每秒执行的事务数
– **写入速率**:每秒写入的数据量(MB/s)
## 2. 写入延迟
– **平均延迟**:平均写入响应时间
– **P95延迟**:95%的写入请求的响应时间
– **P99延迟**:99%的写入请求的响应时间
## 3. 资源使用率
– **CPU使用率**:CPU使用百分比
– **内存使用率**:内存使用百分比
– **磁盘I/O**:磁盘读写速度
– **网络带宽**:网络使用带宽
## 4. 系统指标
– **连接数**:当前活跃连接数
– **事务数**:当前活跃事务数
– **锁等待**:锁等待时间和数量
– **Raft复制延迟**:数据复制延迟
## 5. 监控工具
– **Prometheus**:收集和存储监控数据
– **Grafana**:可视化监控数据
– **TiDB Dashboard**:TiDB自带的监控工具
– **sysbench**:基准测试工具
Part02-生产环境规划与建议
2.1 硬件规划
高并发写入场景下的硬件规划:
学习交流加群风哥QQ113257174
## 1. TiDB节点
– **CPU**:8-16核,高主频
– **内存**:32-64GB
– **磁盘**:SSD,200GB以上
– **网络**:万兆网络
## 2. TiKV节点
– **CPU**:16-32核
– **内存**:64-128GB
– **磁盘**:NVMe SSD,1TB以上
– **网络**:万兆网络
## 3. PD节点
– **CPU**:4-8核
– **内存**:16-32GB
– **磁盘**:SSD,100GB以上
– **网络**:万兆网络
## 4. 存储规划
– **TiKV存储**:使用NVMe SSD,提供高I/O性能
– **TiDB存储**:使用SSD,存储日志和临时文件
– **PD存储**:使用SSD,存储元数据
## 5. 网络规划
– **网络拓扑**:使用万兆交换机,确保节点间网络延迟低
– **网络带宽**:确保足够的网络带宽,避免网络瓶颈
– **网络隔离**:将业务网络和管理网络分离
## 6. 硬件推荐
– **TiDB节点**:
– CPU:Intel Xeon Gold 6248或更高
– 内存:64GB DDR4
– 磁盘:2×480GB SSD RAID1
– 网络:10GbE
– **TiKV节点**:
– CPU:Intel Xeon Gold 6248或更高
– 内存:128GB DDR4
– 磁盘:4×1.6TB NVMe SSD
– 网络:10GbE
– **PD节点**:
– CPU:Intel Xeon Gold 6248或更高
– 内存:32GB DDR4
– 磁盘:2×480GB SSD RAID1
– 网络:10GbE
2.2 配置规划
高并发写入场景下的配置规划:
## 1. TiDB配置
– **max-connections**:最大连接数,根据并发量设置
“`toml
max-connections = 10000
“`
– **txn-total-size-limit**:事务总大小限制,默认100MB
“`toml
txn-total-size-limit = 104857600
“`
– **stmt-count-limit**:单个语句的最大执行时间(秒)
“`toml
stmt-count-limit = 1000000
“`
– **tmp-storage-size**:临时存储大小
“`toml
tmp-storage-size = -1
“`
– **oom-action**:OOM时的操作
“`toml
oom-action = “cancel”
“`
## 2. TiKV配置
– **storage.block-cache.capacity**:块缓存大小,建议设置为内存的40%
“`toml
[storage.block-cache]
capacity = “32GB”
“`
– **raftstore.capacity**:Raft存储容量
“`toml
[raftstore]
capacity = “1.6TB”
“`
– **raftstore.raft-base-tick-interval**:Raft基础 tick 间隔
“`toml
[raftstore]
raft-base-tick-interval = “200ms”
“`
– **server.grpc-concurrency**:gRPC并发数,建议设置为CPU核心数
“`toml
[server]
grpc-concurrency = 16
“`
– **rocksdb.max-open-files**:RocksDB最大打开文件数
“`toml
[rocksdb]
max-open-files = 4096
“`
## 3. PD配置
– **replication.max-replicas**:最大副本数
“`toml
[replication]
max-replicas = 3
“`
– **schedule.leader-schedule-limit**: leader 调度限制
“`toml
[schedule]
leader-schedule-limit = 4
“`
– **schedule.region-schedule-limit**: region 调度限制
“`toml
[schedule]
region-schedule-limit = 2048
“`
– **schedule.replica-schedule-limit**:副本调度限制
“`toml
[schedule]
replica-schedule-limit = 64
“`
## 4. 系统配置
– **文件描述符限制**:
“`bash
echo “* soft nofile 65535” >> /etc/security/limits.conf
echo “* hard nofile 65535” >> /etc/security/limits.conf
“`
– **TCP参数**:
“`bash
echo “net.core.somaxconn = 4096” >> /etc/sysctl.conf
echo “net.ipv4.tcp_max_syn_backlog = 4096” >> /etc/sysctl.conf
echo “net.ipv4.tcp_fin_timeout = 30” >> /etc/sysctl.conf
sysctl -p
“`
– **I/O调度**:
“`bash
# 查看当前I/O调度
cat /sys/block/nvme0n1/queue/scheduler
# 设置为none调度器
echo none > /sys/block/nvme0n1/queue/scheduler
“`
2.3 Schema设计
高并发写入场景下的Schema设计:
## 1. 表结构设计
– **使用合适的数据类型**:选择合适的数据类型,减少存储空间
“`sql
— 优化前:使用VARCHAR(255)存储IP地址
CREATE TABLE test.table (ip VARCHAR(255));
— 优化后:使用INT UNSIGNED存储IP地址
CREATE TABLE test.table (ip INT UNSIGNED);
“`
– **避免使用TEXT/BLOB**:大字段会影响写入性能
“`sql
— 优化前:使用TEXT存储大文本
CREATE TABLE test.table (content TEXT);
— 优化后:使用VARCHAR或分离存储
CREATE TABLE test.table (content VARCHAR(1000));
“`
– **合理设置默认值**:为字段设置合适的默认值
“`sql
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
status INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
“`
## 2. 索引设计
– **减少索引数量**:过多的索引会影响写入性能
“`sql
— 优化前:多个索引
CREATE INDEX idx_name ON test.table(name);
CREATE INDEX idx_age ON test.table(age);
CREATE INDEX idx_address ON test.table(address);
— 优化后:只保留必要的索引
CREATE INDEX idx_name_age ON test.table(name, age);
“`
– **合理设计复合索引**:根据查询模式设计复合索引
“`sql
— 复合索引顺序:选择性高的列在前
CREATE INDEX idx_name_age ON test.table(name, age);
“`
– **避免在高并发写入列上创建索引**:会增加写入开销
“`sql
— 避免在频繁更新的列上创建索引
CREATE TABLE test.table (
id INT PRIMARY KEY,
counter INT, — 频繁更新,不创建索引
name VARCHAR(50) — 创建索引
);
“`
## 3. 分区设计
– **使用分区表**:将数据分散到多个分区,提高写入性能
“`sql
— 按时间分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
created_at DATETIME
) PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026)
);
“`
– **使用哈希分区**:均匀分布数据,避免热点
“`sql
— 按ID哈希分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
name VARCHAR(50)
) PARTITION BY HASH (id) PARTITIONS 8;
“`
## 4. 主键设计
– **使用自增主键**:避免热点问题
“`sql
— 使用自增主键
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
“`
– **避免使用UUID作为主键**:会导致数据分布不均匀
“`sql
— 优化前:使用UUID
CREATE TABLE test.table (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(50)
);
— 优化后:使用自增主键
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
uuid VARCHAR(36),
name VARCHAR(50)
);
“`
## 5. 其他设计建议
– **使用批量插入**:减少网络往返
“`sql
— 批量插入
INSERT INTO test.table (name, age) VALUES (‘test1’, 20), (‘test2’, 30), (‘test3’, 40);
“`
– **使用事务批量提交**:减少事务开销
“`sql
— 事务批量提交
START TRANSACTION;
INSERT INTO test.table (name) VALUES (‘test1’);
INSERT INTO test.table (name) VALUES (‘test2’);
INSERT INTO test.table (name) VALUES (‘test3’);
COMMIT;
“`
– **避免长事务**:减少锁持有时间
“`sql
— 优化前:长事务
START TRANSACTION;
— 执行多个操作
SELECT * FROM test.table WHERE id = 1;
— 其他操作
UPDATE test.table SET name = ‘test’ WHERE id = 1;
COMMIT;
— 优化后:短事务
START TRANSACTION;
UPDATE test.table SET name = ‘test’ WHERE id = 1;
COMMIT;
“`
Part03-生产环境项目实施方案
3.1 优化步骤
TiDB高并发写入性能优化的步骤:
## 1. 基准测试
– **步骤1**:使用sysbench进行基准测试
“`bash
# 准备测试数据
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 –report-interval=10 oltp_write_only prepare
# 运行测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 –report-interval=10 oltp_write_only run
“`
– **步骤2**:分析测试结果
– QPS、TPS
– 响应时间
– 资源使用率
## 2. 性能分析
– **步骤1**:使用TiDB Dashboard分析性能
– 查看SQL执行计划
– 分析慢查询
– 监控资源使用
– **步骤2**:使用Prometheus和Grafana监控
– 监控写入延迟
– 监控Raft复制延迟
– 监控磁盘I/O
– **步骤3**:分析系统瓶颈
– CPU瓶颈
– 内存瓶颈
– I/O瓶颈
– 网络瓶颈
## 3. 优化实施
– **步骤1**:硬件优化
– 升级硬件配置
– 增加TiKV节点
– 优化存储配置
– **步骤2**:配置优化
– 调整TiDB配置参数
– 调整TiKV配置参数
– 调整PD配置参数
– 优化系统参数
– **步骤3**:Schema优化
– 优化表结构
– 优化索引设计
– 优化分区策略
– 优化主键设计
– **步骤4**:应用程序优化
– 使用批量写入
– 使用事务批量提交
– 优化写入模式
– 减少长事务
## 4. 验证结果
– **步骤1**:重新运行基准测试
“`bash
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 –report-interval=10 oltp_write_only run
“`
– **步骤2**:分析优化效果
– 对比优化前后的QPS、TPS
– 对比优化前后的响应时间
– 对比优化前后的资源使用率
– **步骤3**:验证业务正常运行
– 测试业务功能
– 监控系统稳定性
– 确认数据一致性
## 5. 持续监控
– **步骤1**:配置监控告警
– 设置写入延迟告警
– 设置资源使用率告警
– 设置系统负载告警
– **步骤2**:定期分析性能
– 定期进行基准测试
– 定期分析慢查询
– 定期检查系统瓶颈
– **步骤3**:持续优化
– 根据业务变化调整配置
– 根据数据增长调整硬件
– 根据性能需求调整Schema
3.2 调优方法
TiDB高并发写入性能的调优方法:
## 1. 硬件调优
– **升级CPU**:使用高主频、多核心的CPU
“`bash
# 查看CPU信息
lscpu
“`
– **增加内存**:为TiKV节点增加内存,提高缓存命中率
“`bash
# 查看内存信息
free -h
“`
– **使用NVMe SSD**:提供更高的I/O性能
“`bash
# 查看磁盘信息
lsblk -d -o NAME,TYPE,SIZE,MODEL
“`
– **优化网络**:使用万兆网络,减少网络延迟
“`bash
# 测试网络延迟
ping 192.168.1.20
# 测试网络带宽
iperf3 -c 192.168.1.20
“`
## 2. 配置调优
– **TiDB配置调优**:
“`toml
# 增加最大连接数
max-connections = 10000
# 增加事务大小限制
txn-total-size-limit = 209715200
# 增加语句计数限制
stmt-count-limit = 1000000
“`
– **TiKV配置调优**:
“`toml
# 增加块缓存大小
[storage.block-cache]
capacity = “64GB”
# 增加gRPC并发数
[server]
grpc-concurrency = 32
# 优化RocksDB配置
[rocksdb]
max-open-files = 8192
[rocksdb.defaultcf]
write-buffer-size = “1GB”
max-write-buffer-number = 4
“`
– **PD配置调优**:
“`toml
# 增加调度限制
[schedule]
leader-schedule-limit = 8
region-schedule-limit = 4096
replica-schedule-limit = 128
# 优化分裂策略
[schedule]
split-merge-interval = “1h”
“`
– **系统配置调优**:
“`bash
# 调整文件描述符限制
echo “* soft nofile 65535” >> /etc/security/limits.conf
echo “* hard nofile 65535” >> /etc/security/limits.conf
# 调整TCP参数
echo “net.core.somaxconn = 4096” >> /etc/sysctl.conf
echo “net.ipv4.tcp_max_syn_backlog = 4096” >> /etc/sysctl.conf
echo “net.ipv4.tcp_fin_timeout = 30” >> /etc/sysctl.conf
echo “net.ipv4.tcp_tw_reuse = 1” >> /etc/sysctl.conf
sysctl -p
# 调整I/O调度
echo none > /sys/block/nvme0n1/queue/scheduler
“`
## 3. Schema调优
– **表结构调优**:
“`sql
— 使用合适的数据类型
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
“`
– **索引调优**:
“`sql
— 减少索引数量,只保留必要的索引
CREATE INDEX idx_name ON test.table(name);
— 合理设计复合索引
CREATE INDEX idx_name_age ON test.table(name, age);
“`
– **分区调优**:
“`sql
— 按时间分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
created_at DATETIME
) PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);
“`
– **主键调优**:
“`sql
— 使用自增主键
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
“`
## 4. 应用程序调优
– **批量写入**:
“`java
// 批量插入
String sql = “INSERT INTO test.table (name, age) VALUES (?, ?)”;
PreparedStatement pstmt = connection.prepareStatement(sql);
for (int i = 0; i < 1000; i++) {
pstmt.setString(1, "test" + i);
pstmt.setInt(2, 20 + i % 30);
pstmt.addBatch();
}
pstmt.executeBatch();
```
- **事务批量提交**:
```java
// 事务批量提交
connection.setAutoCommit(false);
try {
for (int i = 0; i < 1000; i++) {
String sql = "INSERT INTO test.table (name) VALUES (?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "test" + i);
pstmt.executeUpdate();
}
connection.commit();
} catch (SQLException e) {
connection.rollback();
e.printStackTrace();
} finally {
connection.setAutoCommit(true);
}
```
- **减少长事务**:
```java
// 短事务
connection.setAutoCommit(false);
try {
// 只包含必要的操作
String sql = "UPDATE test.table SET name = ? WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "test");
pstmt.setInt(2, 1);
pstmt.executeUpdate();
connection.commit();
} catch (SQLException e) {
connection.rollback();
e.printStackTrace();
} finally {
connection.setAutoCommit(true);
}
```
- **使用连接池**:
```java
// 配置连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://192.168.1.10:4000/test");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(100);
config.setMinimumIdle(20);
config.setIdleTimeout(30000);
config.setConnectionTimeout(30000);
HikariDataSource dataSource = new HikariDataSource(config);
```
## 5. 其他调优方法
- **使用TiFlash**:对于分析查询,使用TiFlash加速
```sql
-- 创建TiFlash副本
ALTER TABLE test.table SET TIFLASH REPLICA 1;
```
- **使用分区表**:将数据分散到多个分区
```sql
-- 按哈希分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
name VARCHAR(50)
) PARTITION BY HASH (id) PARTITIONS 8;
```
- **优化写入模式**:
- 避免热点写入
- 均匀分布写入
- 批量处理写入
3.3 基准测试流程
TiDB高并发写入性能的基准测试流程:
## 1. 准备环境
– **步骤1**:部署TiDB集群
“`bash
tiup cluster deploy fgedudb v6.1.0 topology.yaml –user root -p
tiup cluster start fgedudb
“`
– **步骤2**:创建测试数据库和表
“`sql
CREATE DATABASE test;
USE test;
CREATE TABLE sbtest1 (
id INT PRIMARY KEY,
k INT NOT NULL DEFAULT ‘0’,
c CHAR(120) NOT NULL DEFAULT ”,
pad CHAR(60) NOT NULL DEFAULT ”
);
“`
## 2. 运行基准测试
– **步骤1**:使用sysbench准备测试数据
“`bash
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 prepare
“`
– **步骤2**:运行写入测试
“`bash
# 写入测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 –report-interval=10 oltp_write_only run
# 混合读写测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 –report-interval=10 oltp_read_write run
“`
– **步骤3**:运行不同并发度的测试
“`bash
# 测试不同并发度
for threads in 16 32 64 128 256;
do
echo “Testing with $threads threads…”
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=$threads –time=60 oltp_write_only run
done
“`
## 3. 分析测试结果
– **步骤1**:收集测试结果
– QPS、TPS
– 响应时间(avg、min、max、p95、p99)
– 错误率
– **步骤2**:分析系统资源使用
– CPU使用率
– 内存使用率
– 磁盘I/O
– 网络带宽
– **步骤3**:分析瓶颈
– 识别性能瓶颈
– 分析原因
– 制定优化方案
## 4. 优化和验证
– **步骤1**:实施优化方案
– 硬件优化
– 配置优化
– Schema优化
– 应用程序优化
– **步骤2**:重新运行基准测试
“`bash
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 oltp_write_only run
“`
– **步骤3**:对比优化前后的结果
– QPS、TPS提升
– 响应时间降低
– 资源使用率优化
## 5. 生成报告
– **步骤1**:整理测试数据
– 优化前后的性能对比
– 不同并发度的性能表现
– 资源使用情况
– **步骤2**:生成性能报告
– 测试环境
– 测试方法
– 测试结果
– 优化建议
Part04-生产案例与实战讲解
4.1 批量写入优化
## 1. 环境信息
– **TiDB版本**:6.1.0
– **集群规模**:3个TiDB节点,3个TiKV节点,3个PD节点
– **硬件配置**:TiKV节点使用NVMe SSD
– **操作系统**:Oracle Linux 9.3
## 2. 故障现象
– **写入性能低**:单条写入QPS仅为5000
– **网络开销大**:频繁的网络往返
– **CPU使用率高**:TiDB节点CPU使用率达到80%
## 3. 故障分析
– **原因**:应用程序使用单条写入,每个请求都需要网络往返,导致性能瓶颈
– **影响**:无法满足高并发写入需求
## 4. 解决方案
– **步骤1**:修改应用程序,使用批量写入
“`java
// 批量插入
String sql = “INSERT INTO test.table (name, age) VALUES (?, ?)”;
PreparedStatement pstmt = connection.prepareStatement(sql);
for (int i = 0; i < 1000; i++) {
pstmt.setString(1, "test" + i);
pstmt.setInt(2, 20 + i % 30);
pstmt.addBatch();
}
pstmt.executeBatch();
```
- **步骤2**:调整批量大小
- 测试不同批量大小的性能
- 选择最佳批量大小
- **步骤3**:验证优化效果
```bash
# 运行基准测试
sysbench --db-driver=mysql --mysql-host=192.168.1.10 --mysql-port=4000 --mysql-user=root --mysql-password=password --mysql-db=test --table-size=1000000 --threads=64 --time=60 oltp_write_only run
```
- **结果**:
- 单条写入QPS:5000
- 批量写入QPS:50000(提升10倍)
- CPU使用率:降低到40%
## 5. 预防措施
- **使用批量写入**:减少网络往返
- **调整批量大小**:根据网络带宽和服务器性能调整
- **监控批量写入性能**:及时发现问题
- **优化连接池**:确保足够的连接数
4.2 事务优化
## 1. 环境信息
– **TiDB版本**:6.1.0
– **集群规模**:3个TiDB节点,3个TiKV节点,3个PD节点
– **硬件配置**:TiKV节点使用NVMe SSD
– **操作系统**:Oracle Linux 9.3
## 2. 故障现象
– **事务冲突**:高并发下事务冲突率高
– **写入延迟高**:P99延迟达到1秒以上
– **系统负载高**:TiKV节点CPU使用率达到90%
## 3. 故障分析
– **原因**:长事务导致锁持有时间长,事务冲突增加
– **影响**:写入性能下降,系统不稳定
## 4. 解决方案
– **步骤1**:优化事务大小
– 减少事务中的操作数量
– 将长事务拆分为短事务
– **步骤2**:优化事务隔离级别
“`sql
— 使用读已提交隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
“`
– **步骤3**:使用乐观锁
“`sql
— 使用版本号实现乐观锁
UPDATE test.table SET name = ‘test’, version = version + 1 WHERE id = 1 AND version = 1;
“`
– **步骤4**:验证优化效果
“`bash
# 运行基准测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 oltp_write_only run
“`
– **结果**:
– 事务冲突率:从30%降低到5%
– P99延迟:从1秒以上降低到200ms
– TiKV CPU使用率:降低到60%
## 5. 预防措施
– **使用短事务**:减少锁持有时间
– **优化事务隔离级别**:根据业务需求选择合适的隔离级别
– **使用乐观锁**:减少锁竞争
– **监控事务冲突**:及时发现和解决事务冲突问题
4.3 并发控制优化
## 1. 环境信息
– **TiDB版本**:6.1.0
– **集群规模**:3个TiDB节点,3个TiKV节点,3个PD节点
– **硬件配置**:TiKV节点使用NVMe SSD
– **操作系统**:Oracle Linux 9.3
## 2. 故障现象
– **写入热点**:某些Region成为写入热点
– **负载不均衡**:部分TiKV节点负载高,其他节点负载低
– **写入性能下降**:随着并发度增加,写入性能不升反降
## 3. 故障分析
– **原因**:数据分布不均匀,导致热点Region
– **影响**:热点Region成为性能瓶颈,整体写入性能下降
## 4. 解决方案
– **步骤1**:优化主键设计
“`sql
— 使用自增主键
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
“`
– **步骤2**:使用分区表
“`sql
— 按哈希分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
name VARCHAR(50)
) PARTITION BY HASH (id) PARTITIONS 8;
“`
– **步骤3**:调整PD调度策略
“`toml
# 增加调度限制
[schedule]
leader-schedule-limit = 8
region-schedule-limit = 4096
replica-schedule-limit = 128
# 优化热点调度
[schedule]
hot-region-schedule-limit = 4
“`
– **步骤4**:验证优化效果
“`bash
# 运行基准测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=128 –time=60 oltp_write_only run
“`
– **结果**:
– 写入热点:消除
– 负载均衡:各TiKV节点负载均匀
– 写入性能:随并发度增加而线性提升
## 5. 预防措施
– **使用自增主键**:避免热点写入
– **使用分区表**:均匀分布数据
– **调整PD调度策略**:优化负载均衡
– **监控热点Region**:及时发现和解决热点问题
4.4 硬件升级优化
## 1. 环境信息
– **TiDB版本**:6.1.0
– **集群规模**:3个TiDB节点,3个TiKV节点,3个PD节点
– **硬件配置**:TiKV节点使用SATA SSD
– **操作系统**:Oracle Linux 9.3
## 2. 故障现象
– **I/O瓶颈**:TiKV节点磁盘I/O使用率达到100%
– **写入延迟高**:P99延迟达到500ms
– **写入吞吐量低**:最大写入吞吐量仅为50MB/s
## 3. 故障分析
– **原因**:SATA SSD的I/O性能不足,成为写入瓶颈
– **影响**:无法满足高并发写入需求
## 4. 解决方案
– **步骤1**:升级TiKV节点存储
– 将SATA SSD更换为NVMe SSD
– 增加存储容量
– **步骤2**:优化NVMe SSD配置
“`bash
# 调整I/O调度
echo none > /sys/block/nvme0n1/queue/scheduler
# 调整TRIM设置
fstrim /tidb/data
“`
– **步骤3**:验证优化效果
“`bash
# 运行基准测试
sysbench –db-driver=mysql –mysql-host=192.168.1.10 –mysql-port=4000 –mysql-user=root –mysql-password=password –mysql-db=test –table-size=1000000 –threads=64 –time=60 oltp_write_only run
“`
– **结果**:
– I/O使用率:降低到40%
– P99延迟:降低到100ms
– 写入吞吐量:提升到200MB/s(提升4倍)
## 5. 预防措施
– **使用NVMe SSD**:提供更高的I/O性能
– **合理规划存储容量**:预留足够的存储空间
– **监控磁盘I/O**:及时发现I/O瓶颈
– **定期维护存储**:保持存储性能
Part05-风哥经验总结与分享
5.1 常见问题与解决方案
TiDB高并发写入性能优化的常见问题与解决方案:
## 1. 写入热点
– **问题**:某些Region成为写入热点,导致性能瓶颈
– **解决**:
– 使用自增主键
– 使用分区表
– 调整PD调度策略
– 均匀分布写入
## 2. 事务冲突
– **问题**:高并发下事务冲突率高,导致写入延迟增加
– **解决**:
– 使用短事务
– 优化事务隔离级别
– 使用乐观锁
– 减少事务中的操作数量
## 3. I/O瓶颈
– **问题**:磁盘I/O成为写入瓶颈
– **解决**:
– 使用NVMe SSD
– 优化I/O调度
– 增加TiKV节点
– 合理规划存储容量
## 4. 网络瓶颈
– **问题**:网络带宽成为写入瓶颈
– **解决**:
– 使用万兆网络
– 优化网络配置
– 减少网络往返
– 使用批量写入
## 5. CPU瓶颈
– **问题**:CPU成为写入瓶颈
– **解决**:
– 使用高主频、多核心的CPU
– 优化SQL语句
– 减少事务开销
– 增加TiDB节点
## 6. 内存瓶颈
– **问题**:内存不足,导致性能下降
– **解决**:
– 增加内存容量
– 优化内存配置
– 减少内存使用
– 使用内存监控
## 7. 配置不当
– **问题**:配置参数不合理,影响写入性能
– **解决**:
– 调整TiDB配置参数
– 调整TiKV配置参数
– 调整PD配置参数
– 优化系统参数
## 8. Schema设计不合理
– **问题**:Schema设计不合理,影响写入性能
– **解决**:
– 优化表结构
– 优化索引设计
– 优化分区策略
– 优化主键设计
5.2 最佳实践
TiDB高并发写入性能优化的最佳实践:
- 硬件选择:使用高性能硬件,特别是NVMe SSD和万兆网络
- 集群规模:根据业务需求合理规划集群规模,适当增加TiKV节点
- 配置优化:根据硬件和业务需求调整配置参数
- Schema设计:优化表结构、索引设计和分区策略
- 写入模式:使用批量写入和事务批量提交,减少网络往返
- 并发控制:使用短事务,减少锁持有时间,避免事务冲突
- 负载均衡:使用自增主键和分区表,均匀分布数据
- 监控告警:配置完善的监控和告警,及时发现问题
- 基准测试:定期进行基准测试,验证性能优化效果
- 持续优化:根据业务变化和数据增长持续优化
5.3 优化技巧
TiDB高并发写入性能优化的实用技巧:
## 1. 硬件优化技巧
– **选择合适的CPU**:
– 优先选择高主频、多核心的CPU
– 对于TiKV节点,推荐16-32核CPU
– **增加内存**:
– TiKV节点内存建议64-128GB
– 内存越大,缓存命中率越高
– **使用NVMe SSD**:
– NVMe SSD的I/O性能远高于SATA SSD
– 推荐使用4×1.6TB NVMe SSD
– **优化网络**:
– 使用万兆网络
– 确保节点间网络延迟低
– 优化网络拓扑
## 2. 配置优化技巧
– **TiDB配置**:
“`toml
# 增加最大连接数
max-connections = 10000
# 增加事务大小限制
txn-total-size-limit = 209715200
“`
– **TiKV配置**:
“`toml
# 增加块缓存大小
[storage.block-cache]
capacity = “64GB”
# 增加gRPC并发数
[server]
grpc-concurrency = 32
“`
– **PD配置**:
“`toml
# 增加调度限制
[schedule]
leader-schedule-limit = 8
region-schedule-limit = 4096
“`
– **系统配置**:
“`bash
# 调整文件描述符限制
echo “* soft nofile 65535” >> /etc/security/limits.conf
# 调整TCP参数
echo “net.core.somaxconn = 4096” >> /etc/sysctl.conf
# 调整I/O调度
echo none > /sys/block/nvme0n1/queue/scheduler
“`
## 3. Schema优化技巧
– **表结构优化**:
“`sql
— 使用合适的数据类型
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
“`
– **索引优化**:
“`sql
— 减少索引数量
CREATE INDEX idx_name ON test.table(name);
— 合理设计复合索引
CREATE INDEX idx_name_age ON test.table(name, age);
“`
– **分区优化**:
“`sql
— 按哈希分区
CREATE TABLE test.table (
id INT PRIMARY KEY,
name VARCHAR(50)
) PARTITION BY HASH (id) PARTITIONS 8;
“`
– **主键优化**:
“`sql
— 使用自增主键
CREATE TABLE test.table (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
“`
## 4. 应用程序优化技巧
– **批量写入**:
“`java
// 批量插入
String sql = “INSERT INTO test.table (name, age) VALUES (?, ?)”;
PreparedStatement pstmt = connection.prepareStatement(sql);
for (int i = 0; i < 1000; i++) {
pstmt.setString(1, "test" + i);
pstmt.setInt(2, 20 + i % 30);
pstmt.addBatch();
}
pstmt.executeBatch();
```
- **事务批量提交**:
```java
// 事务批量提交
connection.setAutoCommit(false);
try {
for (int i = 0; i < 1000; i++) {
String sql = "INSERT INTO test.table (name) VALUES (?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "test" + i);
pstmt.executeUpdate();
}
connection.commit();
} catch (SQLException e) {
connection.rollback();
e.printStackTrace();
} finally {
connection.setAutoCommit(true);
}
```
- **减少长事务**:
```java
// 短事务
connection.setAutoCommit(false);
try {
String sql = "UPDATE test.table SET name = ? WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "test");
pstmt.setInt(2, 1);
pstmt.executeUpdate();
connection.commit();
} catch (SQLException e) {
connection.rollback();
e.printStackTrace();
} finally {
connection.setAutoCommit(true);
}
```
- **使用连接池**:
```java
// 配置连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://192.168.1.10:4000/test");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(100);
config.setMinimumIdle(20);
HikariDataSource dataSource = new HikariDataSource(config);
```
## 5. 监控和调优技巧
- **使用TiDB Dashboard**:
- 查看SQL执行计划
- 分析慢查询
- 监控资源使用
- **使用Prometheus和Grafana**:
- 监控写入延迟
- 监控Raft复制延迟
- 监控磁盘I/O
- **使用sysbench进行基准测试**:
```bash
sysbench --db-driver=mysql --mysql-host=192.168.1.10 --mysql-port=4000 --mysql-user=root --mysql-password=password --mysql-db=test --table-size=1000000 --threads=64 --time=60 oltp_write_only run
```
- **定期分析性能**:
- 定期进行基准测试
- 定期分析慢查询
- 定期检查系统瓶颈
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
