当 MySQL 和 Redis 共存于同一台 Linux 服务器时,需谨慎协调资源(尤其是内存和磁盘 I/O),避免相互争抢导致性能劣化。以下是系统性、可落地的优化配置建议,兼顾稳定性与性能:
✅ 一、核心原则(先决条件)
- 明确角色分工:
- MySQL:持久化、复杂查询、事务保障 → 依赖磁盘 I/O + 内存(Buffer Pool)
- Redis:纯内存缓存/高速数据结构 → 绝对不依赖磁盘(除非启用 RDB/AOF,且应严格管控)
- 拒绝“内存全给 Redis”或“MySQL 独占磁盘”等粗放策略
- 监控先行:部署
htop,iotop,vmstat 1,mysqld_exporter+redis_exporter+ Prometheus/Grafana
✅ 二、内存优化(最关键!)
| 组件 | 推荐配置 | 说明 |
|---|---|---|
| Redis | maxmemory = 总内存 × 40%~55%(预留足够 OS 缓存 + MySQL)maxmemory-policy = allkeys-lru 或 volatile-lru(避免 OOM kill) |
❗禁止 noeviction(易触发 OOM Killer 杀 Redis)✅ 设置 maxmemory-samples 5 平衡精度与开销⚠️ 若用 Redis 6.0+,开启 lazyfree-lazy-eviction yes 降低淘汰延迟 |
| MySQL | innodb_buffer_pool_size = 总内存 × 35%~50%(必须 ≤ Redis maxmemory + Buffer Pool ≤ 总内存 × 85%)key_buffer_size = 16M(MyISAM 已淘汰,仅兼容) |
✅ 必须小于物理内存!超配将触发频繁 swap → 性能雪崩 ✅ 检查 Innodb_buffer_pool_wait_free ≈ 0(否则 Buffer Pool 不足) |
| OS 层 | vm.swappiness = 1(非 0!保留紧急 swap 防 OOM)vm.vfs_cache_pressure = 50(降低 inode/dentry 缓存回收压力) |
❌ 禁止 swappiness=0(OOM Killer 更激进)✅ echo 'vm.swappiness=1' >> /etc/sysctl.conf && sysctl -p |
🔍 内存分配示例(64GB 内存服务器):
- Redis
maxmemory: 28GB(43%)- MySQL
innodb_buffer_pool_size: 24GB(37.5%)- OS + 其他进程:≥ 12GB(含 page cache、网络缓冲、进程栈等)
→ 总占用 ≤ 64GB × 90% = 57.6GB,留 6.4GB 安全余量
✅ 三、磁盘 I/O 优化(减少争抢)
| 场景 | 优化措施 | 命令/配置示例 |
|---|---|---|
| 磁盘分离(强烈推荐) | MySQL 数据目录 & Redo Log 放 SSD Redis RDB/AOF(如启用)放另一块 SSD 或 NVMe OS 系统盘独立 |
bash # 查看磁盘拓扑 lsblk -f; ls -l /sys/block/*/queue/rotational # 0=SSD, 1=HDD |
| I/O 调度器 | SSD/NVMe:none(禁用调度器)HDD: deadline(MySQL 随机读多) |
bash echo 'none' > /sys/block/nvme0n1/queue/scheduler # 永久生效见 /etc/default/grub |
| Redis 持久化克制 | ✅ 生产环境建议:仅开启 RDB(关闭 AOF) → RDB 是 fork + 全量快照,I/O 可控 ❌ 避免 AOF everysec(每秒刷盘,与 MySQL redo log 争 I/O) |
conf # redis.conf save 300 10 # 5min内10次变更才save(降低频率) stop-writes-on-bgsave-error yes # 失败时报警而非静默 rdbcompression yes # 压缩减小写入量 |
| MySQL I/O 优化 | innodb_io_capacity = SSD: 2000~4000, NVMe: 8000+innodb_io_capacity_max = 2× capacityinnodb_flush_method = O_DIRECT(绕过 OS cache,避免双缓存) |
ini # my.cnf [mysqld] innodb_io_capacity=3000 innodb_io_capacity_max=6000 innodb_flush_method=O_DIRECT |
| 文件系统 | XFS(推荐):支持大文件、延迟分配、noatime挂载选项: noatime,nodiratime,logbufs=8,logbsize=256k |
bash # /etc/fstab /dev/nvme0n1p1 /var/lib/mysql xfs defaults,noatime,nodiratime,logbufs=8,logbsize=256k 0 0 |
✅ 四、进程级协同优化
| 项目 | 配置 | |
|---|---|---|
| CPU 亲和性(可选) | 将 MySQL 分配到 CPU0-3,Redis 到 CPU4-7(taskset),避免上下文切换争抢 |
taskset -c 4-7 redis-server /etc/redis.conf |
| OOM Killer 优先级 | 降低 Redis 的 oom_score_adj(更不易被杀),提高 MySQL(关键业务) | bash echo -500 > /proc/$(pgrep redis-server)/oom_score_adj echo -800 > /proc/$(pgrep mysqld)/oom_score_adj # 永久化需 systemd drop-in |
| 日志分离 | MySQL error log / slow log → SSD Redis log → 独立小容量 SSD 或 /dev/shm(内存盘) |
logfile /dev/shm/redis.log(需注意重启丢失) |
✅ 五、必须规避的高危配置
| ❌ 危险操作 | ✅ 正确做法 |
|---|---|
Redis maxmemory 设为 0(无限制) |
显式设置合理上限 + LRU 策略 |
MySQL innodb_buffer_pool_size > 物理内存 |
必须 ≤ 总内存 × 50%(留足 Redis + OS) |
Redis 启用 appendonly yes + appendfsync always |
改为 appendfsync no(依赖 OS 刷盘)或 everysec(若必须 AOF) |
| 使用 HDD 承载 MySQL + Redis 持久化 | 至少 MySQL 必须 SSD;Redis RDB/AOF 也建议 SSD |
关闭 swap(swapoff -a) |
保留 small swap(如 2GB),设 swappiness=1 |
✅ 六、验证与监控清单
- 内存健康:
free -h # total, used, available(关注 available ≥ 2GB) cat /proc/meminfo | grep -E "MemAvailable|Buffers|Cached" - I/O 压力:
iotop -oP # 查看 top I/O 进程(MySQL/Redis 是否霸占) iostat -x 1 3 # %util < 70%, await < 10ms(SSD) - Redis 健康:
redis-cli info memory | grep -E "used_memory|maxmemory|mem_allocator" redis-cli info persistence | grep -E "rdb_bgsave_in_progress|aof_rewrite_in_progress" - MySQL 健康:
SHOW ENGINE INNODB STATUSG -- 查看 BUFFER POOL HIT RATE > 99% SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%';
💡 终极建议
- 短期:按上述内存比例 + 关闭 AOF +
O_DIRECT+swappiness=1快速见效 - 中期:拆分磁盘(MySQL/Redis/RDB 日志各用独立 SSD)
- 长期:业务增长后务必物理分离 —— Redis 用内存服务器,MySQL 用高 I/O 服务器,这是云厂商的标准架构(如阿里云 PolarDB + ApsaraDB for Redis)
如需具体配置模板(
my.cnf/redis.conf/sysctl.conf),我可为你生成完整可部署版本。欢迎补充你的服务器规格(CPU/内存/磁盘类型/数量)和业务场景(读写比、数据量级),我来定制化调优。
是否需要我为你生成一份 一键检查脚本(自动检测冲突配置并给出修复建议)?
CLOUD技术博