MySQL和Redis共用2核4G内存服务器时如何优化资源占用?

在仅2核4GB内存的服务器上同时运行 MySQL 和 Redis,资源竞争非常激烈,需精细化协同优化。以下是兼顾稳定性、性能与安全的实战级优化方案(非理论建议):


🔍 一、前提诊断:先摸清真实负载

# 检查当前内存占用(重点关注 RSS)
ps aux --sort=-%mem | head -10
free -h && cat /proc/meminfo | grep -E "MemAvailable|SwapTotal"

# MySQL 内存实际使用(非配置值)
mysql -e "SHOW VARIABLES LIKE '%buffer%'; SHOW STATUS LIKE 'Threads_connected';"
# 计算 InnoDB 实际内存 = innodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size+read_buffer_size+...)

# Redis 内存使用
redis-cli info memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"

⚠️ 若 MemAvailable < 800MB 或 Redis mem_fragmentation_ratio > 1.5,必须立即干预。


🛠️ 二、硬性资源隔离(必做)

组件 限制方式 推荐值 说明
MySQL my.cnf 配置 innodb_buffer_pool_size = 1024M
max_connections = 50
sort_buffer_size = 256K
tmp_table_size = 32M
缓冲池不超过总内存25%,避免OOM;连接数严格限制
Redis redis.conf 配置 maxmemory 1024mb
maxmemory-policy allkeys-lru
hz 10
lazyfree-lazy-eviction yes
强制内存上限,启用惰性删除防卡顿
系统级 systemd 资源控制 ini<br>[Service]<br>MemoryLimit=3G<br>CPUQuota=150%<br> 防止单个服务吃光资源(需启用 cgroups v2)

关键操作

  • 禁用 MySQL 的 query_cache_type=0(已废弃且耗CPU)
  • Redis 关闭 save ""(禁用RDB持久化),改用 appendonly yes + aof-rewrite-incremental-fsync yes(减少AOF重写IO压力)

⚡ 三、协同优化策略(核心技巧)

1. 数据分层:让Redis真正减负

-- MySQL中避免全表缓存,只缓存高频热点
SELECT id, title, status FROM articles WHERE status='published' ORDER BY created_at DESC LIMIT 20;
-- ✅ 应用层将此结果存入Redis,设置TTL=300s
-- ❌ 不要缓存"SELECT * FROM users"这种全量数据

💡 原则:Redis只存「计算结果」或「聚合数据」,而非原始表镜像。

2. MySQL瘦身:释放内存给Redis

  • 删除无用索引(pt-duplicate-key-checker 检测)
  • 将大文本字段(TEXT/BLOB)迁移到外部存储(如MinIO),MySQL只存URL
  • 使用 TINYINT 替代 ENUM(节省内存且兼容性更好)

3. Redis精简:拒绝“内存黑洞”

# 定期清理无效key(避免过期key堆积)
redis-cli --scan --pattern "session:*" | xargs -r redis-cli del

# 监控大key(>10KB的Hash/List)
redis-cli --bigkeys
# 对大Hash拆分为 hash:key:part1, hash:key:part2...

4. 进程级协作:错峰执行

  • MySQL 备份(mysqldump)和 Redis AOF重写(BGREWRITEAOF绝对禁止同时运行
  • 设置定时任务错峰:
    # /etc/crontab
    0 2 * * * root /usr/bin/redis-cli BGREWRITEAOF  # 凌晨2点
    0 3 * * * root /usr/bin/mysqldump ...           # 凌晨3点

📉 四、监控告警(防患于未然)

# 部署轻量级监控(无需Prometheus)
# /etc/cron.d/db-monitor
*/5 * * * * root bash -c 'echo "$(date): $(free -m | awk "NR==2{print $7}") MB free" >> /var/log/db-mem.log'
*/5 * * * * root bash -c 'echo "$(date): $(redis-cli info memory | grep used_memory_human | cut -d: -f2 | tr -d "[:space:]")" >> /var/log/redis-mem.log'

# 内存低于500MB时自动重启Redis(保MySQL)
if [ $(free -m | awk 'NR==2{print $7}') -lt 500 ]; then
  systemctl restart redis
fi

🚫 五、必须规避的陷阱

错误做法 后果 正解
MySQL innodb_buffer_pool_size=2G Redis启动失败或OOM Killer杀进程 严格按公式:BufferPool ≤ 总内存×25%
Redis maxmemory 不设限 内存爆满触发Linux OOM Killer随机杀进程 必须显式设置且≤1.2G(预留系统缓冲)
同时开启MySQL慢查询日志 + Redis AOF + RDB 磁盘IO 100%,CPU飙升 仅开AOF,关闭RDB和MySQL慢日志(用pt-query-digest按需分析)
使用Redis存储Session但不设TTL 内存持续增长直至崩溃 SET session:abc "data" EX 1800(强制30分钟过期)

✅ 最终效果验证指标

指标 健康阈值 检测命令
系统可用内存 ≥ 800MB free -m | awk 'NR==2{print $7}'
MySQL响应时间 P95 < 150ms mysqlslap --concurrency=10 --iterations=10 -q "SELECT ..."
Redis延迟 redis-cli --latency -u redis://localhost:6379 < 5ms
CPU负载 uptime | awk '{print $NF}' < 1.5

💡 终极建议:若业务增长,优先将Redis迁移至独立1C2G轻量云服务器(成本≈¥30/月),比硬扛更经济稳定。

需要我为你生成:

  • 完整的 my.cnfredis.conf 适配版配置文件?
  • 自动化内存监控+告警脚本?
  • MySQL索引优化检查SQL清单?

欢迎随时提出,可立即输出 👇

未经允许不得转载:CLOUD技术博 » MySQL和Redis共用2核4G内存服务器时如何优化资源占用?