性能与运维
这一课你将能做到
- 给站点配齐三层缓存(页面缓存 / Redis 对象缓存 / OPcache)并用命令验证命中
- 用 WP-CLI 完成日常运维:备份、更新、搜索替换、定时任务真实化
- 做一轮性能体检:慢查询、autoload 选项、图片与 CDN,并给出可量化的优化前后对比
为什么要学
WP 默认「每次请求都全量执行 PHP + 查库」,裸奔状态撑不了多少并发。但它的性能天花板远比传说中高:缓存配对后 90% 以上请求不碰 PHP。运维能力(备份、更新、排障)则是「你的站点敢不敢上生产」的及格线。
人话:缓存像自取餐柜——页面缓存是「整份餐提前打包」(连 PHP 都不进),对象缓存是「常用配菜提前备好」(查库结果进 Redis),OPcache 是「菜谱翻译一遍反复用」(PHP 字节码缓存)。越靠前的柜子命中,省的力气越多。
先建立图像
请求 → CDN(静态资源/图片) → 页面缓存(整页HTML) → OPcache(字节码)
→ 对象缓存 Redis(查询结果/fragments) → MySQL
命中任一层即短路返回。目标:动态页 90%+ 请求止步于第 2 层。
跟着做
步骤 1:先测量再优化
装 Query Monitor 看每页:SQL 条数、耗时、内存。基线示例:首页 68 条查询、180ms。没有基线,一切「优化」都是玄学。
# 粗测响应时间
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s 总耗时: %{time_total}s\n" http://localhost:8080/
步骤 2:对象缓存上 Redis
docker-compose.yml 加服务:
redis:
image: redis:7-alpine
wp-config.php:
define( 'WP_REDIS_HOST', 'redis' );
define( 'WP_REDIS_PREFIX', 'qrocmq:' );
装 Redis Object Cache 插件并启用:
wp plugin install redis-cache --activate
wp redis enable
wp redis status
验证:连刷几页后 wp cache type 输出 redis;Query Monitor 中重复查询变为命中缓存。代码侧主动用:
$courses = wp_cache_get( 'courses_featured', 'qrocmq' );
if ( false === $courses ) {
$courses = get_posts( array( 'post_type' => 'course', 'numberposts' => 6 ) );
wp_cache_set( 'courses_featured', $courses, 'qrocmq', 3600 );
}
步骤 3:页面缓存
轻量方案用 WP Super Cache(官方系),或 Nginx fastcgi_cache:
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WP:100m inactive=60m;
server {
location ~ \.php$ {
fastcgi_cache WP;
fastcgi_cache_valid 200 301 10m;
# 登录用户、带 cookie 的请求跳过缓存
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache $upstream_cache_status;
}
}
验证:curl -I 第二次请求出现 X-Cache: HIT。注意:含 nonce 的表单页、登录用户必须排除缓存。
步骤 4:OPcache(PHP 层)
生产 php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.validate_timestamps=0 ; 生产关闭时间戳检查(发版需 reload php-fpm)
opcache.jit=tracing
opcache.jit_buffer_size=64M
本地开发保持 validate_timestamps=1,否则改代码不生效。
步骤 5:WP-CLI 运维日常
# 备份:库 + 文件
wp db export backup-$(date +%F).sql
tar -czf uploads-$(date +%F).tar.gz wp-content/uploads
# 更新(先测试环境演练)
wp core update
wp plugin update --all
wp core verify-checksums # 校验核心文件是否被篡改(安全体检)
# 换域名/换路径(能正确处理序列化数据)
wp search-replace 'https://old.com' 'https://new.com' --all-tables
# 定时任务
wp cron event list --due-now
wp transient delete --all
# 清理
wp post list --post_type=revision --field=ID | xargs -r wp post delete
wp db optimize
步骤 6:WP-Cron 真实化
WP-Cron 靠访客触发,低流量站点任务会迟到,高流量站点会并发重跑。改为系统定时:
wp-config.php:define( 'DISABLE_WP_CRON', true );
crontab:*/5 * * * * cd /var/www/html && wp cron event run --due-now
步骤 7:CDN 与图片
- 静态资源(wp-content/uploads、构建产物)走 CDN 域名,设置长 TTL + 文件名 hash
- 图片转 WebP(插件如 Converter for Media)+ 原生 srcset(WP 自动输出)
- 核心指标关注 LCP:首屏大图预加载、字体 swap
讲清楚要点
- 三层缓存的失效纪律:更新内容时 WP 自动 clean_post_cache,但自定义 wp_cache_set 的数据要记得 delete;页面缓存插件在发文时通常有钩子联动,自建 Nginx 缓存要配 purge。
- transients 与对象缓存的关系:有 Redis 时 transient 存 Redis 不落库,没有则写 wp_options 表——所以「transient 泛滥」和「options 表膨胀」是同一个问题。
- autoload 膨胀是隐形杀手:
SELECT SUM(LENGTH(option_value)) FROM wp_options WHERE autoload='yes'超过 1MB 就要警惕。 - WP-Cron 的两个坑:靠流量触发(低流量迟到)与并发重跑(高流量重复执行),生产必改系统 cron。
- 更新策略:测试环境先升 → 备份 → 低峰期生产更新 → 核心校验。一次只动一层(PHP 版本 / WP / 插件),出问题能归因。
你可能会懵的地方
-
对象缓存和页面缓存都需要吗? 需要,且不冲突:页面缓存命中的请求不进 PHP;未命中的动态请求靠对象缓存省 SQL。静态化率越高,对象缓存压力越小。
-
为什么后台改了前台没变? 页面缓存/CDN 把旧 HTML 给了访客。先清页面缓存与 CDN 再排 WP 层;带 nonce 的页面本就不该被缓存(见第 10 课)。
-
wp search-replace 为什么要专门工具? 数据库里有 PHP serialize 格式(长度前缀),直接 SQL 替换会改变字符串长度导致反序列化失败——WP-CLI 会正确重算。
-
CDN 缓存了旧页面怎么办? 短 TTL(内容页 10-60 分钟)+ 发文时调 CDN 清缓存 API(多数服务商有 purge 接口/插件联动)。
-
什么时候做 db optimize? 大量删除(清理修订/垃圾评论)之后;平时每月一次足够。InnoDB 场景收益有限,别神化。
错法对照
| 错法 | 错在哪 | 正解 |
|---|---|---|
| 只做数据库优化不做缓存 | 抓错重点:重复请求才是大头 | 先页面缓存 → 对象缓存 → 再谈 SQL |
| 对象缓存开了却不主动存热点数据 | 只帮核心不帮业务 | wp_cache_get/set 包住重复查询 |
| 备份只备文件不备库 | 内容全在 MySQL | wp db export 定时 + 异地存储 |
| 生产开 SAVEQUERIES | 内存暴涨 | 仅本地调试 |
| PHP/WP/插件/主题一次全升 | 出问题无法归因 | 分层升级,每层验证 |
卡点急救
- Redis 连不上:确认 php-redis 扩展已装(
php -m | grep redis)、host/端口/密码正确;容器环境 host 是服务名。 - wp-env/本地改代码不生效:OPcache validate_timestamps=0 的缓存残留;reload php-fpm 或本地改回 1。
- 内存耗尽(Allowed memory size exhausted):
define( 'WP_MEMORY_LIMIT', '256M' ),同时查是否某插件一次拉全量数据。
面试常问
-
说明 WP 的缓存体系分层。 浏览器缓存 → CDN → 页面缓存(整页 HTML,不进 PHP)→ OPcache(字节码)→ 对象缓存(Redis 存查询/片段)→ MySQL。层间短路,越早命中越省资源。
-
WP-Cron 的原理与生产改造? 默认由用户访问触发(检查到期的 cron 事件),低流量延迟、高流量并发重跑;生产改 DISABLE_WP_CRON + 系统 crontab 调 wp cron event run --due-now。
-
一个大流量 WP 站的优化清单? 页面缓存+CDN 打底、Redis 对象缓存与热点数据、autoload 选项瘦身、慢 SQL 治理(meta_query 换自定义表/索引)、图片 WebP+懒加载、WP-Cron 系统化、监控 TTFB 与核心 Web 指标。
自测三问
- 画出从浏览器到 MySQL 的缓存链,并说明每层命中后短路了什么。
- 为什么 wp search-replace 不能用一句 SQL REPLACE 完成?
- DISABLE_WP_CRON 之后谁来触发定时任务?两种 cron 问题分别是什么?
小结一句话
性能靠「缓存分层、各层短路」,运维靠「WP-CLI 例行化 + 更新纪律」——测量先行、逐层加缓存、备份与升级有节奏,站点就能既快又稳。
延伸
- 官方性能与优化文档
- WP-CLI 命令总览
- 下一课:综合实战——从零交付「课程目录站」,把十二课串成一条完整链路。