一台小服务器跑 5 个 WordPress:内存到底该怎么分-第三维度MokIII

场景

一台 2 核 4G、5M 带宽的云服务器,跑 5 个 WordPress 站点,共用一个 PHP-FPM 池、一个 Redis、一个 nginx。

数据库不在本机——用的是独立的云数据库(2 核 2G)。

这种配置最容易出的问题不是"CPU 跑满",而是内存被悄悄吃光,然后 OOM Killer 随机杀进程——表现出来就是"站点时好时坏,重启就好"。

下面是我在这台机器上实际的内存分配账。

一、先列清楚谁在吃内存

linux 说"4G",实际 MemTotal 只有约 3.5 GB(系统保留部分)。扣掉系统和面板之后,能动的更少:

角色占用说明
PHP-FPM worker40~57 MB/个,上限 24 个 ≈ 1.3 GB最大头,5 个站共用一个池
Redis上限 256 MB(实测只用十几 MB)对象缓存
nginx约 100~190 MBRSS 会把共享内存重复计入,实际独占更小
系统 + 面板约 300~500 MB面板本身不轻
swap1 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 只作兜底。做到这四条,"站点时好时坏"这类玄学问题基本就消失了。