在2GB内存的机器上同时运行 MySQL 和 Redis 是一个典型的资源受限场景。如果配置不当,极易触发 OOM(Out of Memory),导致服务崩溃。
以下是经过验证的合理分配策略、关键参数配置及监控建议:
🎯 核心原则
- Redis 是“内存大户”:Redis 默认使用
maxmemory限制,但需预留操作系统缓存空间。 - MySQL 依赖文件系统缓存:InnoDB Buffer Pool 不应占满物理内存,否则 OS 无空间做页缓存(Page Cache),反而降低 I/O 性能。
- 预留系统开销:至少保留 200~300MB 给操作系统内核、进程栈、Swap(如有)等。
✅ 推荐内存分配方案(总内存 2GB = 2048MB)
| 组件 | 推荐最大内存 | 说明 |
|---|---|---|
| Redis | 512 MB ~ 768 MB | 设置 maxmemory,启用淘汰策略 |
| MySQL (InnoDB) | 512 MB ~ 768 MB | innodb_buffer_pool_size |
| 其他开销 | ~500 MB | OS + Swap + MySQL/Redis 进程开销 + 临时表 + 日志缓冲 |
💡 更保守的起步配置(适合小项目):
- Redis:
400 MB- MySQL:
400 MB- 剩余:
~1200 MB用于 OS 和突发负载
🔧 关键参数配置
1. Redis 配置(redis.conf)
# 1. 设置最大内存上限(必须!)
maxmemory 512mb
# 2. 当内存达到上限时的淘汰策略(根据业务选择)
# 常用:LRU 最近最少使用,或 TTL 过期键优先
maxmemory-policy allkeys-lru
# 3. 禁用 Swap(Redis 对延迟敏感,Swap 会导致卡顿)
vm-swap-file /dev/null # Redis 4+ 已移除 vm 相关命令,确保系统层面不启用 swap 或设为最低优先级
# 4. 开启内存碎片整理(可选,定期执行)
# redis-cli MEMORY PURGE
⚠️ 注意:Redis 实际占用内存会略高于
maxmemory(因元数据、线程栈等),因此建议将maxmemory设置为可用内存的 70%~80%。
2. MySQL 配置(my.cnf / mysqld.cnf)
[mysqld]
# 1. InnoDB 缓冲池大小(最关键)
# 公式:innodb_buffer_pool_size ≈ 总内存 × 25%~30%
innodb_buffer_pool_size = 512M
# 2. 单实例可设为一个大的 buffer pool(提升性能)
innodb_buffer_pool_instances = 1
# 3. 连接数控制(避免每个连接占用过多内存)
max_connections = 50 # 根据应用并发调整,2GB 机器不宜过高
thread_cache_size = 8
# 4. 临时表内存限制
tmp_table_size = 16M
max_heap_table_size = 16M
# 5. 排序缓冲区(每个连接独立,需谨慎)
sort_buffer_size = 256K
join_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 128K
# 6. 查询缓存(MySQL 5.7 及以下才有效,8.0 已移除)
# query_cache_type = 1
# query_cache_size = 32M # 高并发下可能成为瓶颈,建议关闭或设小
📌 为什么 MySQL Buffer Pool 不能太大?
- 如果
innodb_buffer_pool_size接近物理内存,OS 无法为文件 I/O 分配足够的 Page Cache。- MySQL 本身还会用其他内存(如 sort/join buffer、线程栈、日志缓冲等)。
- 最佳实践:Buffer Pool 占总内存 25%~30%,其余留给 OS 和其他 MySQL 组件。
🛡️ 防止 OOM 的系统级措施
1. 启用 Swap(谨慎使用)
虽然 Redis 不喜欢 Swap,但在 2GB 小内存下,完全禁用 Swap 可能导致内核直接 kill 进程。
# 创建 1GB swap 文件
dd if=/dev/zero of=/swapfile bs=1M count=1024
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# 设置低 swappiness,避免频繁换页
echo 'vm.swappiness=10' >> /etc/sysctl.conf
sysctl -p
2. 使用 cgroups 或 systemd 限制内存(高级)
通过 systemd 限制每个服务的最大内存,防止单个服务拖垮系统:
# /etc/systemd/system/redis.service.d/override.conf
[Service]
MemoryMax=600M
MemoryHigh=500M
[Service]
MemoryMax=600M
MemoryHigh=500M
3. 监控与告警
- 使用
htop、free -m实时观察内存。 - 配置 Prometheus + Node Exporter + Grafana 监控:
node_memory_MemAvailable_bytes- Redis
used_memoryvsmaxmemory - MySQL
Innodb_buffer_pool_pages_free
🔄 运维建议
-
分阶段扩容:
- 初期:Redis 400M + MySQL 400M
- 观察高峰后,逐步调高至 512M/512M
- 若仍不足,优先考虑优化 SQL 和索引,而非盲目加内存。
-
Redis 持久化策略:
- 使用
RDB而非AOF,减少内存压力。 - 或采用
AOF everysec+auto-aof-rewrite-percentage 100,避免重写时内存X_X倍。
- 使用
-
MySQL 优化:
- 确保所有查询都有索引,避免全表扫描消耗大量临时表内存。
- 避免大事务和复杂 JOIN。
-
重启策略:
- 配置自动重启脚本,当检测到 OOM 时快速恢复。
✅ 总结检查清单
| 检查项 | 状态 |
|---|---|
Redis maxmemory 已设置 |
✅ |
Redis maxmemory-policy 已配置 |
✅ |
MySQL innodb_buffer_pool_size ≤ 768M |
✅ |
MySQL max_connections 适中(≤50) |
✅ |
| 系统保留 ≥300MB 给 OS | ✅ |
| Swap 已启用且 swappiness 较低 | ✅ |
| 已部署内存监控告警 | ✅ |
按照以上配置,你可以在 2GB 内存下稳定运行 MySQL + Redis,并大幅降低 OOM 风险。
轻量云Cloud