2G 内存跑 LNMP(Linux + Nginx + MySQL/MariaDB + PHP),属于典型的“小马拉大车”。如果不做优化,稍微有点并发或者跑几个动态页面,服务器直接 OOM(Out of Memory)重启,或者 Swap 把磁盘 IO 打满导致响应极慢。
核心思路就两个:极致压缩数据库和 PHP-FPM 的资源占用,以及合理配置 Nginx 的缓冲。别想着加内存,先榨干这 2G 的每一滴性能。
以下是我在实际生产环境(特别是阿里云、腾讯云轻量应用服务器)中验证过的配置方案:
1. MySQL/MariaDB 优化(重中之重)
MySQL 是吃内存大户。默认配置在 2G 机器上基本就是自杀。你需要修改 my.cnf (或 mariadb.conf)。
关键参数调整:
[mysqld]
# 基础设置
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# 连接数限制
# 2G 内存不要开太多连接,默认 151 太多了,设低一点防止瞬间爆内存
max_connections = 50
# 关键:每连接变量
# thread_cache_size: 缓存线程,减少创建销毁开销
thread_cache_size = 8
# table_open_cache: 打开表的数量,根据站点大小调整,一般 200-500 足够
table_open_cache = 400
# 关键:InnoDB 缓冲池 (INNODB_BUFFER_POOL_SIZE)
# 这是最关键的参数。建议设置为物理内存的 30%-40%。
# 2G 内存的话,设 768M 到 1G 比较安全。
# 注意:如果同时跑其他服务,别给太大,否则系统本身会崩。
innodb_buffer_pool_size = 768M
# 日志相关
# 关闭二进制日志(如果是非主从架构,且对数据实时性要求不高,可考虑关闭以节省 IO 和内存)
# log-bin=mysql-bin
# binlog_format=mixed
# 临时表
tmp_table_size = 64M
max_heap_table_size = 64M
# 查询缓存 (Query Cache)
# 注意:MySQL 5.7 之后 Query Cache 被标记为废弃,MariaDB 仍支持。
# 在高并发写场景下,Query Cache 反而成为瓶颈。
# 如果你的网站读多写少,可以开启;如果动静结合或写入频繁,建议关闭。
query_cache_type = 0
query_cache_size = 0
操作建议:
- 使用 MariaDB 代替 MySQL:在 CentOS/RHEL 等系统中,MariaDB 通常更轻量,兼容性极好,且在相同硬件下性能往往略优。
- 监控 QPS/TPS:优化后观察
show status like 'Threads_connected';和show status like 'Created_tmp%';。如果 Created_tmp_disk_tables 很高,说明临时表落盘了,适当调大tmp_table_size。
2. PHP-FPM 优化(控制并发进程数)
PHP-FPM 的每个子进程都会占用独立内存。2G 内存下,必须严格控制 pm.max_children。
找到 php-fpm.d/www.conf 文件,修改以下参数:
; 启动模式:static 或 on-demand
; 对于 2G 内存,推荐 on-demand(按需启动)或者 static 但数值很小
pm = dynamic
; 最小空闲进程数
pm.start_servers = 2
; 最大空闲进程数
pm.min_spare_servers = 2
; 最大空闲进程数
pm.max_spare_servers = 5
; 【最关键】最大子进程数
; 计算公式参考:总内存 / (单个 PHP 进程平均内存 * 1.2)
; 假设你的 PHP 脚本平均每个进程占 30MB-50MB 内存
; 2048MB - 512MB(留给系统和 MySQL) = 1536MB 可用
; 1536 / 40 ≈ 38 个进程。为了保险,设 20-30 个。
pm.max_children = 25
; 单次请求后重启子进程(防止内存泄漏累积)
pm.max_requests = 500
如何估算单个 PHP 进程内存?
你可以用 top 命令查看 php-fpm 进程的 RSS 列平均值。如果不确定,先按 30-40MB 估算。如果你的代码引入了大量第三方库(如 Laravel, WordPress 插件多),单个进程可能高达 100MB+,那 max_children 就要降到 10 左右。
额外建议:
- 启用 OPcache:确保
php.ini中opcache.enable=1。opcache.memory_consumption=128 opcache.max_accelerated_files=10000 opcache.revalidate_freq=60这能极大降低 CPU 和内存开销,避免重复编译 PHP 代码。
3. Nginx 优化(利用内存做缓冲)
Nginx 本身很省内存,但可以通过调整缓冲区来减少对后端 PHP 和上游资源的压力。
http {
# 客户端请求头缓冲区
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# 输出缓冲区
output_buffers 1 32k;
postpone_output 1460;
# 发送文件模式
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 保持连接超时
keepalive_timeout 65;
# 针对静态资源开启 gzip
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
}
重点:
- 开启 Gzip:大幅减少传输数据量,虽然增加一点点 CPU,但对带宽敏感的小服务器非常有效。
- Proxy Cache:如果流量稍大,可以考虑配置 Nginx 的
proxy_cache,将动态生成的 HTML 或 API 响应缓存到磁盘或内存中,减轻 PHP 和 MySQL 的压力。
4. Linux 系统级优化
A. 交换空间 (Swap) —— 救命稻草,但不是主力
2G 内存必须开 Swap,但不能太大,也不能太激进。
# 创建一个 2G 的 swap 文件(与内存 1:1)
dd if=/dev/zero of=/swapfile bs=1M count=2048
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
调整 Swappiness:
# 默认是 60,表示倾向于使用 swap。对于 SSD,可以设为 10,尽量先用物理内存。
sysctl vm.swappiness=10
echo 'vm.swappiness=10' >> /etc/sysctl.conf
B. 内核参数微调
编辑 /etc/sysctl.conf,添加或修改:
# 允许重用 TIME_WAIT sockets
net.ipv4.tcp_tw_reuse = 1
# 缩短 TIME_WAIT 时间
net.ipv4.tcp_fin_timeout = 30
# 本地端口范围扩大
net.ipv4.ip_local_port_range = 1024 65535
# 防火墙连接跟踪表大小(如果并发高,需增大)
net.nf_conntrack_max = 65535
执行 sysctl -p 生效。
5. 应用层建议
- 禁用不必要的服务:
systemctl disable firewalld iptables(如果用云厂商安全组)、disable postfix等不用的服务,释放内存。 - 使用 CDN:这是最便宜的优化。把图片、JS、CSS 全部推到 CDN(阿里云 OSS/CDN,腾讯云 COS/CDN)。2G 服务器的带宽通常只有 3Mbps-5Mbps,静态资源一旦走 CDN,服务器负载下降 80% 以上。
- Redis 缓存:如果业务逻辑复杂,务必上 Redis。2G 内存分 256MB 给 Redis 绰绰有余。将热点数据放入 Redis,能显著减少 MySQL 查询次数。
- 选择轻量级框架:如果还在用大型框架(如 Spring Boot, .NET Core),请慎重。LNMP 最佳搭档是 PHP 轻量框架(ThinkPHP, Laravel 精简版)或原生 PHP。Java/.NET 应用在 2G 内存下几乎无法流畅运行。
总结检查清单
| 组件 | 关键动作 | 目标 |
|---|---|---|
| MySQL | innodb_buffer_pool_size=768M, max_connections=50 |
防止 OOM,提高查询速度 |
| PHP-FPM | pm.max_children=25, on_demand 或 dynamic |
控制并发进程,避免内存爆炸 |
| OPcache | 启用并配置合理内存 | 减少 PHP 解析开销 |
| Nginx | 开启 Gzip, 调整 Buffer | 减少带宽占用,提升响应 |
| System | 开启 2G Swap, swappiness=10 |
提供内存溢出保护 |
| 架构 | 静态资源上 CDN, 引入 Redis | 减轻服务器计算和存储压力 |
最后提醒:
2G 内存适合个人博客、小型企业官网、内部管理系统。如果遇到突发流量(如秒杀、热点事件),这种配置一定会扛不住。这时候,横向扩展(加多台服务器)比纵向升级(加内存)在成本上更合理,或者直接使用云厂商的弹性伸缩服务。
CLOUD云枢