
场景
一台 2 核 4G、5M 带宽的云服务器,跑 5 个 WordPress 站点,共用一个 PHP-FPM 池、一个 Redis、一个 nginx。
数据库不在本机——用的是独立的云数据库(2 核 2G)。
这种配置最容易出的问题不是"CPU 跑满",而是内存被悄悄吃光,然后 OOM Killer 随机杀进程——表现出来就是"站点时好时坏,重启就好"。
下面是我在这台机器上实际的内存分配账。
一、先列清楚谁在吃内存
linux 说"4G",实际 MemTotal 只有约 3.5 GB(系统保留部分)。扣掉系统和面板之后,能动的更少:
| 角色 | 占用 | 说明 |
|---|---|---|
| PHP-FPM worker | 40~57 MB/个,上限 24 个 ≈ 1.3 GB | 最大头,5 个站共用一个池 |
| Redis | 上限 256 MB(实测只用十几 MB) | 对象缓存 |
| nginx | 约 100~190 MB | RSS 会把共享内存重复计入,实际独占更小 |
| 系统 + 面板 | 约 300~500 MB | 面板本身不轻 |
| swap | 1 GB | 兜底,不参与日常 |
数据库外置这一条是这台机器能跑 5 个站的关键前提:省下的不只是几百 MB 内存,更是 MySQL 自己的 buffer pool 峰值——它会让"这台机器到底还剩多少内存"变得不可预测。挪出去之后,内存账才算是算得清的。
二、PHP-FPM:按内存反推进程数
5 个站共用一个池时,pm.max_children 是所有站共享的额度,不是每站一份。算法见另一篇,这里给结论:
55 MB × 24 = 1.3 GB
剩下的留给 Redis、nginx、面板、系统和页缓存。宁可在高峰期偶尔排队,也不要 OOM——排队只是慢,OOM 是全站一起挂。
三、Redis:一定要设上限
Redis 默认没有内存上限,缓存一堆积就会一路吃上去,直到把 PHP-FPM 挤掉。必须显式设:
maxmemory 256mb
maxmemory-policy allkeys-lru
bind 127.0.0.1
protected-mode yes
appendonly yes
maxmemory+allkeys-lru:满了按最近最少使用淘汰,永远不会吃爆。对象缓存丢几条无所谓,命中率略降而已;bind 127.0.0.1:只允许本机访问。
顺带一个量级参考:我这边 5 个站的对象缓存加起来,used_memory 平时只有十几 MB——256 MB 的上限不是拿来用满的,是拿来兜底的。
多站共用一个 Redis:必须做 key 隔离
同一个 Redis、同一个 db,如果几个站不区分前缀,站点之间会互相读到对方缓存的对象——症状是偶尔显示别站的内容、或选项莫名其妙错乱,极其难查。
WordPress 侧加一行常量即可,每个站写自己的域名:
define( 'WP_CACHE_KEY_SALT', 'https://www.example.com' );
这一行让每个站的缓存 key 带上独立前缀,共用实例也互不干扰。
四、swap:不是性能手段,是保命手段
fallocate -l 1G /www/swap && chmod 600 /www/swap && mkswap /www/swap && swapon /www/swap
# 持久化(/etc/fstab)
/www/swap swap swap defaults 0 0
再把积极性调低,让内核尽量别用它(用到了就是内存不够的信号,不该是常态):
vm.swappiness = 10
swap 的作用是:内存瞬时峰值时不至于直接 OOM Kill,给你留出反应时间。它不是拿来扛日常负载的——如果你发现 swapon --show 的 USED 长期居高不下,那说明该加内存或者降并发,而不是"有 swap 就不怕"。
五、几个便宜的收益项
fs.file-max = 65535
net.core.somaxconn = 65535
vm.overcommit_memory = 1
net.ipv4.tcp_tw_reuse = 1
fs.file-max/somaxconn:高并发时不被文件描述符和连接队列卡住;overcommit_memory = 1:Redis 官方建议值,避免 fork 时因内存判定失败;tcp_tw_reuse:短连接多时重用 TIME-WAIT。
六、怎么确认真的分对了
free -m # 看 MemAvailable,不是看 free
swapon --show # USED 长期偏高 = 内存不够
dmesg -T | grep -iE 'oom|killed' # 有记录说明已经杀过了
redis-cli info memory | grep -E 'used_memory_human|maxmemory_human'
三条判断标准:MemAvailable 长期留有 1 GB 以上、dmesg 里没有 OOM 记录、swapon 的 USED 只在峰值短暂升高。
看内存一定要看 MemAvailable:linux 会把闲置内存拿去做文件缓存,
free那一列常年很小是正常的,被缓存占的内存随时可以还回来。
一句话总结:几 G 内存跑多个 WordPress,重点是把不确定性砍掉——数据库外置、Redis 设死上限并做 key 隔离、PHP 进程数按内存反推、swap 只作兜底。做到这四条,"站点时好时坏"这类玄学问题基本就消失了。

评论 (0)