在 MySQL 和 Redis 共用同一台 Linux 服务器时,资源竞争主要集中在 内存(RAM)和 磁盘 I/O。若配置不当,极易出现“争抢”现象:Redis 因内存不足触发 Swap 导致延迟飙升,或 MySQL 因 I/O 阻塞而查询变慢。
以下是针对内存和磁盘 IO 的系统级优化与配置策略:
一、核心原则:明确资源分配比例
在物理机资源有限的情况下,必须根据业务场景进行“切分”。
- 内存分配:通常建议 MySQL : Redis = 60% : 40% 或 50% : 50%。
- 如果 Redis 主要用于缓存热点数据且数据量可控,可给 Redis 更多内存。
- 如果 MySQL 是主存储且涉及大量排序/临时表操作,需预留足够内存给 Buffer Pool。
- I/O 优先级:Redis 对延迟极其敏感(毫秒级),MySQL 对吞吐量更敏感。应确保 Redis 的 I/O 不被 MySQL 的大批量写入阻塞。
二、内存优化配置 (RAM)
1. 操作系统层面
-
关闭 Swap(关键):
Redis 和 MySQL 都极度依赖物理内存。一旦触发 Swap,性能会下降几个数量级。# 临时关闭 sudo swapoff -a # 永久关闭 (修改 /etc/fstab,注释掉 swap 行) echo "vm.swappiness = 1" | sudo tee -a /etc/sysctl.conf sudo sysctl -p注:将
vm.swappiness设为 1,表示仅在极端情况下才使用 Swap。 -
透明大页 (Transparent Huge Pages, THP):
对于 MySQL 和 Redis,THP 往往会导致抖动。建议禁用。# 检查状态 cat /sys/kernel/mm/transparent_hugepage/enabled # 设置为 never echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
2. MySQL 配置 (my.cnf)
- innodb_buffer_pool_size:
这是最重要的参数。建议设置为可用物理内存的 50%-70%(扣除 Redis 占用后)。[mysqld] innodb_buffer_pool_size = 8G # 假设总内存 16G,Redis 占 4G,留 4G 给系统和其他进程 innodb_log_file_size = 2G # 适当调大,减少刷盘频率 innodb_flush_log_at_trx_commit = 2 # 权衡安全与性能,若非X_X级可设为 2 - 其他内存相关:
限制sort_buffer_size,read_buffer_size等会话级参数,避免并发高时内存爆炸。
3. Redis 配置 (redis.conf)
- maxmemory:
必须显式设置,防止 Redis 吃光所有内存导致 OOM Killer 杀掉 MySQL。maxmemory 4gb # 硬上限 maxmemory-policy allkeys-lru # 当内存满时,淘汰策略(推荐 lru 或 volatile-lru) - 内存碎片率控制:
Redis 在高负载下可能产生碎片。activedefrag yes # 开启主动碎片整理 active-fraction 0.1 # 阈值
三、磁盘 I/O 优化配置
1. 文件系统与挂载选项
- 文件系统选择:
推荐使用 XFS(默认)或 EXT4。避免使用 NFS 作为本地数据存储。 - 挂载参数优化:
在/etc/fstab中调整挂载选项,减少元数据开销。# 示例:data 分区挂载 /dev/sdb1 /data xfs noatime,nodiratime,logbufs=8 0 0noatime/nodiratime:不更新访问时间,显著减少写 I/O。logbufs=8:增加日志缓冲区(针对 XFS)。
2. I/O 调度器 (Scheduler)
根据硬盘类型选择调度算法:
- SSD/NVMe:建议使用
none或mq-deadline(现代内核默认)。 - 机械硬盘 (HDD):建议使用
deadline或bfq。# 查看当前调度器 cat /sys/block/sda/queue/scheduler # 修改为 deadline (以 sda 为例) echo deadline > /sys/block/sda/queue/scheduler
3. 隔离读写路径 (关键策略)
由于 MySQL 和 Redis 对 I/O 需求不同,尽量将数据文件分离到不同的物理磁盘或分区。
- 方案 A:多磁盘
- Disk 1 (NVMe/SSD): 专门用于 Redis RDB/AOF 快照及 MySQL 的 Binlog。
- Disk 2 (HDD/大容量 SSD): 存放 MySQL 的 InnoDB Data File (
ibdata1和.ibd)。
- 方案 B:单磁盘分区
如果只有一块盘,利用ionice和cgroups限制 MySQL 的 I/O 权重,优先保障 Redis。
4. cgroups v2 限流 (高级)
如果无法物理隔离磁盘,可使用 Linux Cgroups 限制 MySQL 的 I/O 带宽,防止其全速写入阻塞 Redis。
# 示例:限制 mysql 进程的写入带宽为 50MB/s
echo 50000000 > /sys/fs/cgroup/io/mysql/write_bps_max
(注意:具体命令取决于 cgroups 版本和内核版本)
四、监控与调优闭环
配置完成后,必须通过监控验证效果:
-
监控指标:
- 内存:
free -h观察 Buffers/Cached,确保没有频繁 Swap。 - I/O:使用
iostat -x 1观察%util(利用率)和await(平均等待时间)。- 若
await持续超过 10ms (SSD) 或 50ms (HDD),说明存在瓶颈。
- 若
- Redis:关注
used_memory_rss和evicted_keys。 - MySQL:关注
Innodb_buffer_pool_read_requestsvsInnodb_buffer_pool_reads(命中率应>99%)。
- 内存:
-
压测验证:
在低峰期模拟高负载(如sysbench跑 MySQL,redis-benchmark跑 Redis),观察是否出现互相卡顿。
五、总结清单
| 维度 | 关键动作 | 推荐值/策略 |
|---|---|---|
| Swap | 彻底关闭 | vm.swappiness = 1 |
| THP | 禁用 | never |
| 内存分配 | 静态切分 | MySQL 60%, Redis 40% (根据业务调整) |
| Redis | 内存上限 | maxmemory 严格限制,开启 activedefrag |
| MySQL | Buffer Pool | innodb_buffer_pool_size = 可用内存的 50-70% |
| 文件系统 | 挂载参数 | noatime, nodiratime |
| I/O 调度 | 匹配硬件 | SSD=none, HDD=deadline |
| 隔离 | 物理/逻辑分离 | 优先分离磁盘;次选 Cgroups 限流 |
通过以上配置,可以在单台服务器上实现 MySQL 和 Redis 的稳定共存,最大程度减少资源争抢带来的性能抖动。
轻量云Cloud