速卖通素材
奋斗

在2核4G的服务器上部署LNMP环境,如何优化MySQL和Redis的内存使用?

服务器

在 2 核 4G(约 3.8GB 可用内存)的服务器上部署 LNMP,内存资源非常紧张,必须对 MySQL 和 Redis 进行精细调优,避免 OOM(Out Of Memory)导致服务崩溃。以下是针对该配置的优化建议:


一、总体内存规划(参考)

组件 建议最大占用 说明
Linux 系统 + Nginx + PHP-FPM 600–800 MB 含内核、系统进程、Web 服务
MySQL ≤ 1.5 GB 核心配置项调整
Redis ≤ 1.2 GB 根据数据量设定 maxmemory
预留缓冲 ≥ 300 MB 防止突发负载导致 OOM

✅ 总内存需求 ≈ 800 + 1500 + 1200 = 3500 MB < 4096 MB(留有余地)


二、MySQL 内存优化(以 MariaDB/MySQL 5.7+ 为例)

1. 关键配置项(my.cnfmysqld.cnf

[mysqld]
# 基础设置
innodb_buffer_pool_size = 1G        # 占物理内存 25%~40%,优先分配给 InnoDB
innodb_log_file_size = 256M         # 日志大小,减少刷盘压力
innodb_flush_log_at_trx_commit = 2  # 性能与安全性平衡(生产可设为 1,但需权衡)

# 连接控制(防连接风暴)
max_connections = 150               # 默认 151,适当降低
thread_cache_size = 32              # 缓存线程,减少创建开销

# 临时表与排序
tmp_table_size = 64M                # 内存临时表上限
max_heap_table_size = 64M           # 同上
sort_buffer_size = 2M               # 每连接独立,注意 max_connections * sort_buffer_size 不能过大

# 查询缓存(MySQL 8.0 已移除;5.7 中建议关闭)
query_cache_type = 0
query_cache_size = 0

# 其他安全项
skip-name-resolve                   # 禁用 DNS 解析提速登录
performance_schema = OFF            # 非调试场景可关闭

🔍 验证命令:

mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';" 
# 若读命中率 > 99%,说明 buffer_pool 设置合理

2. 注意事项

  • ❌ 不要设置 key_buffer_size(MyISAM 已少用),除非有旧 MyISAM 表。
  • ⚠️ join_buffer_size / read_buffer_size每连接变量需谨慎,避免 max_connections × buffer_size 超限。
  • 使用 mysqltuner.pl 工具定期分析并给出动态建议。

三、Redis 内存优化

1. 核心配置(redis.conf

# 内存限制(最关键!)
maxmemory 1200mb                    # 略小于 1.2GB,留出余量

# 淘汰策略(根据业务选择)
maxmemory-policy allkeys-lru        # 推荐:LRU 淘汰最近最少使用键
# 或 volatile-lru(仅淘汰带 TTL 的键)
# 或 noeviction(严格防溢出,但可能阻塞写入)

# 内存碎片管理
activedefrag yes
active-memory-defrag-threshold-low 60
active-memory-defrag-threshold-high 100

# 持久化(根据 RDB/AOF 取舍)
save 900 1                          # 1 分钟至少 1 个 key 变化时触发 RDB
# aof-enabled yes
# aof-fsync everysec                # 若选 AOF,注意磁盘 IO 影响

2. 监控与调优技巧

  • 实时查看内存使用:
    redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
  • mem_fragmentation_ratio > 1.5,启用 activedefrag 自动整理碎片。
  • 避免存储大对象(如 >1MB 的字符串),考虑分片或压缩。

四、系统级协同优化

1. 限制 PHP-FPM 内存

# /etc/php/8.x/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 20                # 20 个进程 × ~50MB = 1GB
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
request_terminate_timeout = 30s     # 防止脚本死循环占内存

2. 开启 Swap(谨慎使用)

# 创建 1GB swap(仅作应急,避免频繁交换导致卡顿)
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 调整 swappiness(降低交换倾向)
echo "vm.swappiness=10" >> /etc/sysctl.conf
sysctl -p

3. 使用 cgroups 限制(进阶)

若支持 systemd/cgroup v2,可为 MySQL/Redis 设置内存上限:

# /etc/systemd/system/mysqld.service.d/override.conf
[Service]
MemoryMax=1.5G
MemoryHigh=1.3G

五、验证与监控建议

  1. 压力测试后观察

    htop          # 实时看内存/CPU
    free -h       # 检查 buff/cache 是否异常高
    vmstat 1      # 观察 si/so(swap in/out)
  2. 告警阈值

    • MySQL 内存 > 1.6GB → 报警
    • Redis 内存 > 1.1GB → 报警
    • free 内存 < 200MB → 紧急处理
  3. 长期优化

    • 定期清理慢查询(slow_query_log
    • 分析 Redis 大 Key(--bigkeys 工具)
    • 考虑将热点数据预热到 buffer_pool

总结:在 2C4G 环境下,“小步快跑、保守配置、持续监控” 是核心原则。优先保证 MySQL 的 InnoDB buffer pool 和 Redis 的 maxmemory 不超配,再配合系统级限制与 swap 兜底,即可稳定运行 LNMP。

如需具体某一步的详细操作(如编译参数、Docker 部署调优等),欢迎进一步说明环境细节。

未经允许不得转载:轻量云Cloud » 在2核4G的服务器上部署LNMP环境,如何优化MySQL和Redis的内存使用?