在 Linux 服务器上同时运行 MySQL 和 Redis,本质上是在处理两种截然不同的资源竞争模型:MySQL 是 CPU 密集型与随机 IO 密集型(取决于查询模式),而 Redis 是内存密集型与高并发网络 IO 密集型。
当它们共用同一台物理机时,最大的风险在于“资源抢占”导致的抖动。以下是从内核参数、文件系统、应用配置三个层面给出的具体优化方案,旨在隔离干扰、提升吞吐量。
一、 核心原则:隔离与预留
不要试图让两个服务平分资源,而是根据它们的特性进行“硬隔离”或“优先级设定”。
- 内存隔离:Redis 必须独占足够内存以保证全量数据在 RAM 中;MySQL 需要剩余内存用于 Buffer Pool 和 OS Cache。
- IO 隔离:避免两者同时产生大量随机写操作。如果可能,将 MySQL 的 Redo Log 和 Binlog 放在 SSD/NVMe 上,而 Redis 的 RDB/AOF 也尽量利用 OS Page Cache(因为 Redis 本身是内存数据库,持久化频率可控)。
二、 Linux 内核级优化(sysctl.conf)
这是最基础也是最重要的环节。编辑 /etc/sysctl.conf,添加或修改以下参数:
1. 虚拟内存管理(vm.*)
# 1. 降低 swappiness
# 默认值通常是 60。对于 Redis 这种强依赖内存的应用,必须设为 0 或 1。
# 防止 Redis 热点数据被 swap 出去,导致性能断崖式下跌。
vm.swappiness = 0
# 2. 调整 dirty 页面回写策略
# 减少 MySQL 和 Redis 对磁盘刷盘频率的影响,利用更大的 OS Page Cache。
vm.dirty_background_ratio = 5 # 后台进程开始刷脏页的比例(默认10)
vm.dirty_ratio = 10 # 阻塞用户进程直到刷脏页的比例(默认20)
vm.dirty_expire_centisecs = 3000 # 脏页超过此时间强制刷盘
vm.dirty_writeback_centisecs = 500 # 后台线程刷盘间隔
# 3. 提高 inode 缓存上限
# 如果业务涉及大量小文件或小对象,可适当调高
vm.vfs_cache_pressure = 50 # 默认100,降低可保留更多目录项/inode缓存
注意:
vm.swappiness=0是 Redis 运行的必要条件之一。
2. 网络栈优化(net.*)
Redis 是高并发短连接或长连接场景,MySQL 通常是中等并发。优化 TCP 缓冲:
# 增加 TCP 接收/发送缓冲区大小
net.core.rmem_max = 16777216 # 16MB
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
# TCP 拥塞控制算法选择
# bbr 在现代 Linux 内核(4.9+)下通常表现更好,尤其在高延迟网络
net.ipv4.tcp_congestion_control = bbr
# 允许重用 TIME_WAIT 套接字
net.ipv4.tcp_tw_reuse = 1
# 增大本地端口范围,避免高并发下端口耗尽
net.ipv4.ip_local_port_range = 1024 65535
3. 调度器与 CPU 亲和性(可选但推荐)
如果服务器核心数较多(如 8C+),可以考虑使用 cgroups 或 taskset 绑定进程到特定 CPU 核,但这属于高级运维范畴,初期建议先优化系统参数。
三、 文件系统与挂载选项
1. 文件系统选择
- 推荐:XFS 或 ext4。
- 不推荐:老旧的 ext3 或在高性能场景下的 NTFS/FAT。
- 日志模式:确保使用
data=ordered(ext4/XFS 默认),这能平衡性能和一致性。
2. Mount Options 优化
在 /etc/fstab 中挂载数据盘时,添加以下选项:
# 示例:/dev/vdb1 /data xfs defaults,noatime,nodiratime,commit=60 0 0
noatime,nodiratime # 禁止访问时间更新,减少不必要的元数据 IO
commit=60 # XFS 特有,每秒最多刷新一次脏数据到磁盘,降低 IO 压力
barrier=0 # 【谨慎使用】如果使用的是带电池保护的 RAID 卡或 NVMe,可关闭 barrier 提升写入性能;否则保持开启以保数据完整性
重要提醒:
barrier=0会牺牲数据安全性换取性能。如果是云服务器的普通云盘,不建议关闭,因为底层存储可能有断电丢数据风险。如果是自建机房且硬件可靠,可考虑。
3. I/O Scheduler 设置
查看当前调度器:cat /sys/block/sda/queue/scheduler
- HDD(机械硬盘):设置为
deadline或bfq。 - SSD/NVMe:设置为
none或mq-deadline。
# 临时设置
echo none > /sys/block/vda/queue/scheduler
echo mq-deadline > /sys/block/vdb/queue/scheduler
四、 应用层配置优化
1. Redis 配置 (redis.conf)
- maxmemory:设置为物理内存的 70%-80%,留出空间给 OS 和其他进程。
- maxmemory-policy:根据业务选择
allkeys-lru或volatile-lru。 - save/aof:
- 如果追求极致性能,可禁用 RDB(
save ""),仅开启 AOF,并设置appendfsync everysec。 - 避免在高峰时段触发
bgrewriteaof或bgsave,可通过auto-aof-rewrite-percentage调整触发阈值。
- 如果追求极致性能,可禁用 RDB(
- hz:将
hz从默认的 10 改为 100(需重启),提高内部任务执行频率,但会增加 CPU 开销,视情况而定。 - tcp-backlog:适当调大,如 1024 或 2048,配合
somaxconn。
2. MySQL 配置 (my.cnf)
- innodb_buffer_pool_size:设置为物理内存的 50%-70%。
- 关键点:如果 Redis 占用了大部分内存,MySQL 的 Buffer Pool 会变小,可能导致查询变慢。此时应评估是否可以将 MySQL 迁移到独立实例。
- innodb_log_file_size:增大日志文件大小(如 1G~4G),减少 Checkpoint 频率,提升写入吞吐。
- innodb_flush_log_at_trx_commit:
- 设为
1:最高安全性,每次事务都刷盘,IO 压力大。 - 设为
2:每秒刷盘,性能提升显著,宕机最多丢失 1 秒数据。在共用服务器上,建议设为 2,通过应用层重试机制补偿极端情况。
- 设为
- sync_binlog:设为
1或100。如果非X_X级强一致要求,可设为100以上。
五、 监控与告警(关键!)
没有监控的优化是盲目的。重点监控以下指标:
- Redis:
used_memory_rssvsmaxmemory:接近上限时需警惕。blocked_clients:反映客户端等待响应的时间。instantaneous_ops_per_sec:观察峰值。
- MySQL:
Innodb_buffer_pool_read_requestsvsInnodb_buffer_pool_reads:计算缓存命中率,目标 > 99%。Threads_running:并发线程数。
- 系统级:
iostat -x 1:关注%util(利用率)和await(平均等待时间)。如果 await > 20ms,说明 IO 瓶颈已出现。free -m:观察 available memory,确保没有频繁 swap。
六、 终极建议:架构解耦
虽然上述优化能在一定程度上缓解冲突,但从工程角度,强烈建议将 MySQL 和 Redis 部署在不同节点。
原因如下:
- 故障域隔离:Redis 内存泄漏或 OOM Kill 不会影响 MySQL 进程(反之亦然)。
- 资源争用不可控:即使做了 cgroups 隔离,Linux 内核调度仍存在不确定性。
- 扩展性:两者负载增长曲线不同步。Redis 可能因缓存穿透瞬间打满 CPU/Memory,而 MySQL 可能因复杂 JOIN 吃光 IO。
如果受限于成本必须共用一台服务器,请遵循以下底线:
- 使用 SSD/NVMe 存储。
vm.swappiness=0。- Redis 内存不超过总内存 70%。
- MySQL InnoDB Log 文件加大。
- 密切监控
iowait和swap使用情况。
CLOUD云枢