在仅 2GB 总内存 的受限环境中(如小型 VPS、嵌入式服务器或开发测试机),同时运行 MySQL 和 Redis 确实极易触发 OOM(Out of Memory)——尤其当两者默认配置未调优时。关键原则是:严格限制各自最大内存用量,预留系统基础开销,并禁用非必要功能。以下是经过生产验证的合理分配与配置方案:
✅ 一、内存分配建议(总 2GB = 2048MB)
| 组件 | 分配内存 | 说明 |
|---|---|---|
| 操作系统 + 基础服务 | 300–400MB | 内核、SSH、日志、cron 等必需开销(free -h 观察空闲内存) |
| MySQL | 900–1100MB | 主要用于 innodb_buffer_pool_size(核心缓存),其余参数极简 |
| Redis | 500–600MB | 通过 maxmemory 严格限制,启用 LRU/LFU 驱逐策略 |
| 缓冲/安全余量 | ≥100MB | 防止瞬时峰值导致 OOM(如 MySQL 排序、Redis 大 key 操作) |
✅ 推荐分配(保守稳妥):
- MySQL:1024MB
- Redis:512MB
- 系统+余量:≈512MB(含 swap 缓冲)
✅ 二、MySQL 关键调优(my.cnf)
[mysqld]
# ▶️ 核心内存控制(必须!)
innodb_buffer_pool_size = 1024M # 占 MySQL 分配的 90%+,勿超 1024M
innodb_log_file_size = 64M # 减小日志文件(默认 48M→64M 可接受,勿过大)
innodb_flush_method = O_DIRECT # 避免双重缓存(Linux)
# ▶️ 降低连接与临时内存
max_connections = 32 # 默认151→大幅缩减
sort_buffer_size = 256K # 每连接排序缓存(默认2M→压到256K)
read_buffer_size = 128K # 同上
join_buffer_size = 128K # 同上
tmp_table_size = 32M # 内存临时表上限(超过转磁盘)
max_heap_table_size = 32M # MEMORY 表上限
# ▶️ 禁用非必要功能(省内存+提速)
skip_log_bin # 关闭 binlog(若无需主从/恢复)
skip_performance_schema # 关闭性能库(节省 100MB+)
skip_log_error # 或设 log_error=/dev/null(减少 I/O)
innodb_file_per_table = ON # 必须开启,避免 ibdata1 膨胀
# ▶️ 其他安全项
wait_timeout = 60 # 空闲连接 60s 断开
interactive_timeout = 60
🔍 验证命令:
# 查看实际内存占用(启动后)
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
# 检查当前连接数和临时表使用
mysql -e "SHOW STATUS LIKE 'Threads_connected'; SHOW STATUS LIKE 'Created_tmp_disk_tables';"
✅ 三、Redis 关键调优(redis.conf)
# ▶️ 内存硬限制(必须!)
maxmemory 512mb # 严格上限
maxmemory-policy allkeys-lru # 或 volatile-lru(推荐 allkeys-lru,简单有效)
# maxmemory-samples 5 # 默认值即可
# ▶️ 禁用持久化(除非必须)→ 节省内存和 I/O
save "" # 关闭 RDB 自动保存
appendonly no # 关闭 AOF(若需持久化,改用 AOF rewrite + fsync everysec)
# ▶️ 降低后台任务开销
lazyfree-lazy-eviction yes # 驱逐时异步释放内存(防阻塞)
lazyfree-lazy-expire yes # 过期键异步删除
lazyfree-lazy-server-del yes # DEL 异步处理(Redis 4.0+)
# ▶️ 网络与连接
tcp-keepalive 300 # 保持连接活跃
timeout 300 # 空闲连接超时
maxclients 100 # 限制客户端数(默认 10000→大幅缩减)
# ▶️ 其他
hash-max-ziplist-entries 128 # 小哈希用压缩列表(省内存)
list-max-ziplist-size -2 # 小列表用压缩列表
set-max-intset-entries 512 # 小整数集合用 intset
🔍 验证命令:
redis-cli info memory | grep -E "(used_memory_human|maxmemory_human|mem_fragmentation_ratio)"
# 应看到:used_memory_human ≤ 512MB,mem_fragmentation_ratio < 1.5
✅ 四、系统级防护(防止 OOM Kill)
-
启用并合理配置 swap(救命稻草)
# 创建 512MB swap(不推荐 SSD 频繁写,但 2GB 内存下必要) sudo fallocate -l 512M /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab # 调低 swappiness(减少主动 swap) echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf sudo sysctl -p -
配置 OOM Score(让 MySQL/Redis 不优先被 kill)
# 查看当前 OOM score(越低越不易被 kill) cat /proc/$(pgrep mysqld)/oom_score_adj # 设置 MySQL 为 -500(最高保护),Redis 为 -300 echo -500 | sudo tee /proc/$(pgrep mysqld)/oom_score_adj echo -300 | sudo tee /proc/$(pgrep redis-server)/oom_score_adj # (需写入 service 文件持久化,见下方) -
Systemd 服务文件加固(推荐)
/etc/systemd/system/mysqld.service.d/oom.conf:[Service] OOMScoreAdjust=-500 MemoryLimit=1100M # systemd 级别硬限制(内核 4.5+)/etc/systemd/system/redis.service.d/oom.conf:[Service] OOMScoreAdjust=-300 MemoryLimit=550Msudo systemctl daemon-reload
✅ 五、监控与告警(上线后必做)
- 实时监控脚本(每5分钟检查):
#!/bin/bash mem=$(free | awk '/Mem:/ {printf("%.0f"), $3/$2*100}') mysql_mem=$(ps aux --sort=-%mem | grep mysqld | head -1 | awk '{print $6/1024 "MB"}') redis_mem=$(ps aux --sort=-%mem | grep redis | head -1 | awk '{print $6/1024 "MB"}') echo "$(date): Mem:${mem}%, MySQL:${mysql_mem}, Redis:${redis_mem}" [ $mem -gt 90 ] && echo "ALERT: System memory >90%" | mail -s "OOM Warning" admin@example.com - 工具推荐:
htop、glances、Prometheus + Grafana(轻量版)。
❌ 绝对禁止的操作
- ❌ 不设
maxmemory(Redis 默认无上限 → 内存耗尽) - ❌ 不调
innodb_buffer_pool_size(默认可能 128MB,但其他缓存叠加仍爆) - ❌ 开启
performance_schema(2GB 下可吃掉 200MB+) - ❌ 同时开启 RDB + AOF(双持久化 → 内存+I/O 压力翻倍)
- ❌ 使用
innodb_buffer_pool_instances > 1(小内存下反而增加开销)
✅ 最终效果预期
| 指标 | 目标值 |
|---|---|
| 系统空闲内存 | ≥300MB(free -h) |
| MySQL RSS 内存 | ≈1050–1100MB |
| Redis RSS 内存 | ≈520–560MB |
mem_fragmentation_ratio (Redis) |
< 1.3 |
| OOM Killer 触发次数 | 0(长期稳定) |
💡 提示:若业务允许,优先考虑分离部署(MySQL 和 Redis 分在不同机器),或改用更轻量替代方案(如 SQLite + Redis,或 TiDB Lite)。2GB 是极限场景,务必做好降级预案(如 Redis 降级为本地缓存)。
需要我为你生成完整的 my.cnf / redis.conf 模板文件,或 systemd service 配置?欢迎随时提出 👇
云服务器