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

在仅2核4GB内存的服务器上同时运行 MySQL 和 Redis,资源竞争非常激烈(尤其内存和I/O),需谨慎权衡与精细化调优。以下是务实、可落地的优化方案,兼顾稳定性、性能和运维可持续性:


✅ 一、核心原则(先决条件)

  1. 绝不让两者内存总和超过 3.2GB(预留 0.8GB 给 OS + 系统进程)
  2. MySQL 优先保障(通常是业务主数据库),Redis 定位为缓存层,可降级/容忍部分失效
  3. 禁用 swap(或严格限制):避免内存不足时触发 swap 导致 MySQL/Redis 延迟飙升(vm.swappiness=10
  4. 关闭非必要服务(如 Apache/Nginx 若非必需,改用轻量级 Caddy;禁用 auditd、bluetooth、GUI 等)

✅ 二、MySQL 资源精简调优(目标:≤2.2GB 内存占用)

✅ 修改 /etc/my.cnf(或 /etc/mysql/mysql.conf.d/mysqld.cnf

[mysqld]
# === 内存控制 ===
innodb_buffer_pool_size = 1.6G     # ⚠️ 关键!占 MySQL 总内存 70%+,勿超 1.8G
innodb_log_file_size = 64M         # 减小日志文件(默认 48M~256M),降低恢复时间和内存压力
innodb_flush_method = O_DIRECT     # 避免双重缓冲(Linux 下推荐)

# === 连接与线程 ===
max_connections = 50               # 默认151,按实际并发调低(查 `SHOW STATUS LIKE 'Threads_connected';`)
wait_timeout = 60                  # 空闲连接 60s 断开
interactive_timeout = 120

# === 查询优化 ===
query_cache_type = 0               # ❌ 彻底禁用(MySQL 8.0+ 已移除,5.7 建议关)
tmp_table_size = 32M
max_heap_table_size = 32M          # 防止内存临时表暴增
sort_buffer_size = 256K           # 每连接排序缓冲,勿设过大
read_buffer_size = 128K
read_rnd_buffer_size = 256K

# === 其他瘦身项 ===
skip_log_bin                       # ❌ 关闭 binlog(若无需主从/备份,否则保留但设 expire_logs_days=3)
innodb_file_per_table = ON
innodb_flush_log_at_trx_commit = 2 # 平衡安全性与性能(1=安全但慢,2=折中,0=最快但可能丢1s数据)

🔍 验证内存占用
启动后执行:

SELECT 
  (SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'innodb_buffer_pool_size') / 1024/1024 AS ibp_mb,
  (SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'key_buffer_size') / 1024/1024 AS key_mb;
-- 再结合 `ps aux --sort=-%mem | head -10` 观察 mysqld 实际 RSS 内存

💡 提示:使用 mysqltuner.pl(Perl脚本)自动分析并给出调优建议(官网)


✅ 三、Redis 资源严控(目标:≤800MB 内存 + 低CPU争抢)

✅ 修改 /etc/redis/redis.conf

# === 内存硬限 ===
maxmemory 768mb                    # ⚠️ 必须设置!超限触发淘汰策略
maxmemory-policy allkeys-lru       # 或 volatile-lru(推荐后者,只淘汰带过期时间的key,更安全)
# maxmemory-samples 3                # 默认5,可保持

# === 持久化降载(关键!)===
save ""                            # ❌ 彻底禁用 RDB(避免 fork 大进程卡顿)
appendonly no                      # ❌ 禁用 AOF(除非强需求持久化)
# 若必须 AOF:appendonly yes + appendfsync everysec(不选 always)

# === CPU/连接控制 ===
tcp-keepalive 300                  # 保活检测,及时释放死连接
timeout 300                        # 闲置连接5分钟断开
maxclients 200                     # 根据应用连接池调整(避免过多空闲连接耗内存)
# 限制后台任务(如 bgsave/bgaofrewrite)不抢占CPU:
# 当前无直接参数,但可通过 cgroups(见下文)或禁用持久化规避

# === 其他 ===
lazyfree-lazy-eviction yes         # 淘汰大key时异步释放内存,防阻塞
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes

🔍 监控内存水位

redis-cli info memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
# 理想值:mem_fragmentation_ratio < 1.5(过高说明内存碎片严重)

💡 Redis 内存估算公式:
key数 × (平均key长度 + 平均value长度 + 16~24字节元数据)
redis-cli --bigkeys 扫描大key,MEMORY USAGE key 查单个key内存。


✅ 四、系统级协同优化(防资源互搏)

项目 推荐配置 说明
CPU 绑核隔离 taskset -c 0 mysqld & taskset -c 1 redis-server 将 MySQL 绑定到 CPU0,Redis 到 CPU1,避免上下文切换抖动(需在 service 启动脚本中设置)
I/O 调度器 echo deadline > /sys/block/*/queue/scheduler(SSD)或 none(NVMe) 避免 CFQ 等复杂调度器开销
OOM 优先级 echo -1000 > /proc/$(pgrep mysqld)/oom_score_adj
echo -500 > /proc/$(pgrep redis-server)/oom_score_adj
保证 MySQL 最后被 OOM Killer 杀掉
cgroups 限频(进阶) systemd 为服务设 CPUQuota=80% 防止单一服务吃满 CPU(例:CPUQuota=80%/etc/systemd/system/mysqld.service.d/override.conf

✅ 五、必须做的监控与告警(防雪崩)

  • 内存free -h + cat /proc/meminfo | grep -E "MemAvailable|SwapFree"
  • MySQLSHOW GLOBAL STATUS LIKE 'Threads_connected'Innodb_buffer_pool_wait_free(>0 表示 buffer pool 不足)
  • RedisINFO memorymem_used 接近 maxmemory 时立即告警
  • 磁盘IOiostat -x 1 关注 %util > 90await > 50ms
  • 工具推荐htop(实时)、mytop(MySQL)、redis-cli monitor(抽样)、Prometheus + Grafana(长期)

⚠️ 六、强烈建议的架构演进路径(短期妥协,长期必做)

阶段 方案 理由
立即行动 将 Redis 作为「只读缓存」,所有写操作绕过 Redis 直写 MySQL 避免双写一致性难题和缓存穿透风险
1个月内 使用 redis-cli --bigkeys 清理大Key,用 SCAN 替代 KEYS * 防止 Redis 单命令阻塞
3个月内 将 Redis 迁移至独立 1C2G 轻量云实例(如腾讯云轻量应用服务器) 成本≈¥30/月,彻底解耦,性价比极高
6个月内 MySQL 开启 performance_schema + 慢查询日志(long_query_time=1),用 pt-query-digest 分析瓶颈 从根源减少慢SQL对内存/CPU的消耗

📌 总结:关键数字清单(抄作业版)

组件 推荐上限 检查命令
总内存占用 ≤ 3.2 GB free -h
MySQL Buffer Pool 1.6 GB mysql -e "SELECT @@innodb_buffer_pool_size/1024/1024;"
Redis maxmemory 768 MB redis-cli config get maxmemory
MySQL max_connections ≤ 50 mysql -e "SHOW VARIABLES LIKE 'max_connections';"
Redis maxclients ≤ 200 redis-cli config get maxclients
Swap 使用率 0%(或 <5% swapon --show + free -h

最后叮嘱

  • 不要迷信“优化参数”能解决一切——2核4G 是生产环境的底线,业务增长后必须拆分;
  • 每次调参后压测:用 sysbench(MySQL)和 redis-benchmark 验证稳定性;
  • 备份永远第一:即使资源紧张,也要确保 mysqldumpmydumper 定时成功(用 ionice -c3 降低IO影响)。

如果需要,我可以为你生成:

  • ✅ 完整的 my.cnfredis.conf 生产就绪模板
  • ✅ systemd 服务文件(含 CPU 绑核 + OOM 调整)
  • ✅ 自动化巡检 Shell 脚本(内存/连接/慢查询一键检查)
    欢迎随时提出 👇
未经允许不得转载:CLOUD云枢 » MySQL和Redis共用2核4G内存服务器时如何优化资源占用?