14.8.6 容量规划与扩缩容实践

容量规划与扩缩容实践围绕业务增长曲线、读写比例、连接峰值与后端实例能力展开。本节给出基线采集、容量估算、扩缩容流程、排错与练习示例,并包含原理草图与关键命令说明。

文章图片

基线指标采集(含安装与命令说明)#

1)安装与启用采集工具(示例:proxysql 自带管理接口 + node_exporter)

# 安装 ProxySQL(示例,基于 Debian/Ubuntu)
sudo apt-get update
sudo apt-get install -y proxysql

# 启动并检查
sudo systemctl enable --now proxysql
sudo systemctl status proxysql --no-pager

# 安装 node_exporter(示例)
cd /opt
curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar -xf node_exporter-1.6.1.linux-amd64.tar.gz
/opt/node_exporter-1.6.1.linux-amd64/node_exporter --version

2)采集 ProxySQL 基线指标(连接池、QPS、延迟)

# 进入 ProxySQL 管理接口(默认端口6032)
mysql -u admin -padmin -h 127.0.0.1 -P6032

# 关键指标查看
SELECT Variable_name, Variable_value FROM stats.stats_mysql_global WHERE Variable_name IN
('Client_Connections_created','Client_Connections_aborted','MySQL_Query_Cache_count_get','MySQL_Query_Cache_count_set');

SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnOK FROM stats.stats_mysql_connection_pool;

SELECT Hostgroup, srv_host, Queries, Latency_us, Err_count FROM stats.stats_mysql_query_digest ORDER BY Queries DESC LIMIT 10;

3)采集 MySQL 基线指标(QPS/TPS、延迟、复制)

# QPS/TPS 粗略估算(间隔1s)
mysql -e "SHOW GLOBAL STATUS LIKE 'Questions'; SHOW GLOBAL STATUS LIKE 'Com_commit'; SHOW GLOBAL STATUS LIKE 'Com_rollback';"

# 复制延迟
mysql -e "SHOW SLAVE STATUS\G" | egrep "Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running"

说明:
- ConnUsed/ConnFree 反映连接池命中与压力。
- Latency_us 用于评估热点查询延迟。
- QuestionsCom_commit 用于估算峰值吞吐能力。

容量规划方法与示例#

容量估算建议采用“峰值负载×安全系数”,并区分代理层与后端层:

  • 代理层:按峰值并发连接数、规则数量、SQL解析开销估算CPU与内存。
  • 后端MySQL:按写入放大、索引命中率与磁盘IOPS估算。
  • 安全系数一般1.5~2.0,促销场景2.5以上。

示例估算
- 峰值并发连接 5000,平均每连接 2KB 内存,ProxySQL 规则 500 条
- 估算内存:5000*2KB=10MB(连接池)+ 规则与缓存预留 1~2GB
- 若峰值QPS 30k,单代理CPU可承载 15k QPS,则至少 2 台代理

扩容实践(读扩/写扩)#

1)读扩:新增从库并加入读组(灰度引流)#

-- 在 ProxySQL 管理接口执行
INSERT INTO mysql_servers(hostgroup_id, hostname, port, weight, max_connections)
VALUES(10, '10.0.10.21', 3306, 10, 1000);

-- 先设为低权重灰度
UPDATE mysql_servers SET weight=1, status='ONLINE' WHERE hostname='10.0.10.21';

-- 应用到运行时
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

-- 观察连接池与延迟
SELECT hostgroup, srv_host, status, ConnUsed, ConnFree FROM stats.stats_mysql_connection_pool;
SELECT Hostgroup, srv_host, Latency_us, Err_count FROM stats.stats_mysql_query_digest ORDER BY Latency_us DESC LIMIT 5;

-- 稳定后提升权重
UPDATE mysql_servers SET weight=10 WHERE hostname='10.0.10.21';
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

2)写扩:分库分表或分片路由(示例规则)#

-- 假设按用户ID取模分片到不同写库组
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES (1001, 1, '^SELECT.*FROM orders WHERE user_id%2=0', 20, 1),
       (1002, 1, '^SELECT.*FROM orders WHERE user_id%2=1', 21, 1);

LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

缩容实践(先出流量再下线)#

-- 降低权重逐步出流量
UPDATE mysql_servers SET weight=0 WHERE hostname='10.0.10.21';
LOAD MYSQL SERVERS TO RUNTIME;

-- 观察连接消化
SELECT hostgroup, srv_host, ConnUsed FROM stats.stats_mysql_connection_pool WHERE srv_host='10.0.10.21';

-- 连接清零后下线并移除
UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostname='10.0.10.21';
LOAD MYSQL SERVERS TO RUNTIME;

DELETE FROM mysql_servers WHERE hostname='10.0.10.21';
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

排错清单与命令#

1)扩容后无流量:
- 检查规则命中、权重与状态

SELECT rule_id, match_pattern, destination_hostgroup, active FROM mysql_query_rules;
SELECT hostname, status, weight FROM mysql_servers;

2)延迟飙升:
- 查看慢查询与复制延迟

mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';"
mysql -e "SHOW SLAVE STATUS\G" | egrep "Seconds_Behind_Master"

3)连接耗尽:
- 查看连接池使用率

SELECT hostgroup, srv_host, ConnUsed, ConnFree, ConnOK FROM stats.stats_mysql_connection_pool;

练习与验收#

1)练习:新增一台从库并灰度引流,观察 10 分钟延迟与错误率
- 验收标准:Err_count=0Latency_us 不高于原均值 20%

2)练习:模拟缩容
- 将权重降为 0,确认 ConnUsed 归零后删除实例
- 验收标准:代理层无 Client_Connections_aborted 增长

3)练习:容量模型更新
- 采集 1 周峰值 QPS 与延迟分位,计算新安全系数
- 验收标准:形成可复用的容量估算表格与阈值文档