普通视图
使用 OPCache 字节码缓存让 WordPress PHP 执行效率提升 300%
前面我们介绍了使用 Memcached 内存缓存来实现 WordPress 站点秒开,其实 WordPress 加速还有个一个大招就是使用 OPcache 字节码缓存来提升 PHP 的执行效率,经测试最高可达提升 300%。
这么强吗?那今天就介绍一下 OPCache!
OPCache 是什么?
OPCache 是 PHP 的官方推出的字节码缓存器(Zend OPcache),通过将 PHP 脚本预编译的字节码存储在共享内存中来提升 PHP 的性能,在 PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展,
缓存预编译字节码的好处就是避免重复解析和编译脚本,省去了每次加载和解析 PHP 脚本的开销,那么这一过程是如何实现的呢?

缓存字节码:PHP 脚本首次被执行的时候,Zend 引擎会将代码转换为 抽象语法树(AST),再编译为 字节码(opcodes),OPCache 扩展会拦截这一过程,将字节码存储在共享内存中,后续请求直接调用内存中的字节码,跳过重复编译的过程。
内存共享机制:OPCache 使用共享内存(mmap
或 shm
)存储字节码,所有 PHP 进程(如 PHP-FPM 子进程)共享同一份缓存,降低了内存的占用,相比其他方案,OPCache 与 PHP 内核深度集成,效率更高。
所以 OPCache 在下面几个关键点提升了性能:
- CPU 节省:避免重复编译,降低 CPU 负载(尤其是 WordPress 这类动态脚本)。
- I/O 优化:减少磁盘读取
.php
文件的次数(对机械硬盘效果显著)。 - 内存效率:字节码比原始 PHP 代码更紧凑,共享内存减少整体内存占用。
所以对于 WordPress 来说,就特别需要 OPCache 了,因为 WordPress 每个页面请求都会加载大量 PHP 文件(主题、插件、核心),这样未优化的 WordPress 在流量高峰时容易因 PHP 编译拖慢响应。
如何启用 OPCache?
PHP PHP 5.5.0 及后续版本默认包含 OPCache,OPcache 只能编译为共享扩展,如果你使用 --disable-all 参数 禁用了默认扩展的构建, 那么必须使用 --enable-opcache 选项来开启 OPcache。
编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。在非 Windows 平台使用 zend_extension=/full/path/to/opcache.so
, Windows 平台使用 zend_extension=C:\path\to\php_opcache.dll
。
汇总一下在 php.ini
中添加下面代码:
zend_extension=opcache.so ; Linux
zend_extension=opcache.dll ; Windows
opcache.enable=1
针对 WordPress,可以加入这些专属优化配置:
[opcache]
opcache.enable=1
opcache.memory_consumption=256 ; WordPress 建议 ≥128MB
opcache.max_accelerated_files=10000 ; 覆盖 WordPress 核心 + 插件文件数
opcache.interned_strings_buffer=16 ; WordPress 大量重复字符串(如钩子名)
opcache.validate_timestamps=0 ; 生产环境关闭自动检查
opcache.revalidate_freq=0 ; 与 validate_timestamps=0 配合
opcache.save_comments=1 ; WordPress 依赖注释(如钩子文档)
opcache.enable_file_override=1 ; 覆盖 include/require 优化
安装好时候,如何检测验证安装成功了呢?
简单可以通过通过 phpinfo()
或命令行 php -v
查看是否加载。也可以在后台 「WPJAM」主菜单下「系统信息」子菜单中的「服务器」标签中「PHP 扩展」看到:OPCache:

当然最重要是「OPCache」标签页:

这里也会罗列出 OPCache 的一些状态,比如已用内存和剩余内存,以及他们之间百分率,命中率和未命中率,以及他们之间百分率等等数据,还有相关的饼图。
生产环境一般建议关闭 validate_timestamps
,避免频繁检查文件修改,文件有更新的时候通过手动重启 OPCache 或 PHP-FPM 来更新代码,也可以在上图中点击「刷新缓存」即可。
下面是一个简单 WordPress 站点在开启 OPCache 前后的性能对比:
场景 | 未启用 OPCache | 启用 OPCache | 优化幅度 |
---|---|---|---|
首页加载时间 | 800ms | 300ms | ↓62.5% |
后台管理页面 | 1200ms | 500ms | ↓58.3% |
并发请求(100 QPS) | CPU 90% | CPU 45% | ↓50% |
所以可以看到启用 OPCache 最高接近 300% 的提升。
简单总结
PHP 代码使用 OPCache 之后,可以提高代码的执行效率,特别是 WordPress 这类文件比较多的 CMS 系统,所以在使用 Memcached 内存缓存来实现 WordPress 站点秒开之后,记得一定要开启 OPCache 来提速,另外 #WPJAM Basic# 也在 WordPress 集成了 OPCache 状态页面,可以看到 PHP 使用 OPCache 的状态。
同台服务器上多个 WordPress 站点如何使用同个 Memcached?
前面我们介绍了「使用 Memcached 内存缓存来实现 WordPress 站点秒开」,很多用户都开始使用 Memcached 来提高 WordPress 站点速度,但是使用的时候碰到第一个或者说最多的问题就是,同台服务器上多个 WordPress 网站怎么同时使用 Memcached?
站点间数据互串
如果同时将 #WPJAM Basic# 插件 template
目录下的 object-cache.php
文件复制到同个服务器上多个 WordPress 站点的 wp-content
目录下来同时开启 Memcached 缓存,可能会出现这样的问题:
访问一个网站会跳转到另外一个网站,也就是说数据会串了。
这是怎么回事呢?这是因为 object-cache.php
默认是使用 WordPress 的表前缀($table_prefix
)来区分不同站点在内存中的缓存的。
如果你在同个服务器多个 WordPress 网站的表前缀都相同,都是默认的 wp_
,那么 object-cache.php
就无法区分是哪个站点了。
那么怎么解决呢?
怎么同时使用 Memcached
定位了问题,那么就非常好解决,有两个解决方法:
1. 修改表前缀,让不同的 WordPress 博客使用不同的表前缀。我开发了一个 WordPress 数据库表前缀修改器,一键生成修改数据库表前缀所需的SQL,让你在 WordPress 修改表前缀之后能够更加方便全站修改。
2. 如果修改表前缀不方便,我还提供了 WP_CACHE_KEY_SALT
这个缓存 key 盐值的常量,你只需要在不同站点的 wp-config.php
文件定义不同的 WP_CACHE_KEY_SALT
值即可。
比如两个站点分别定义为:
define('WP_CACHE_KEY_SALT', 'site1');
define('WP_CACHE_KEY_SALT', 'site2');
如果设置了还不行,可能你的 object-cache.php
不是最新版,那就下载一下最新版的 WPJAM Basic 插件,然后将 wpjam-basic/template/
目录下的 object-cache.php
文件复制到 wp-content
目录下。
如何设置 Memcache 服务器地址
此外还有一些用户服务器的设置,他们的 Memcached 的服务器地址不是默认的 127.0.0.1
,或者它们使用的云服务器的 Memcached 服务,很多聪明的同学会自己修改 object-cache.php
中的 Memcached 服务器地址。
其实不用那么麻烦 #WPJAM Basic# 提供的 object-cache.php
支持自定义服务器地址的, 只要在 wp-config.php
文件填下如下代码,将相应的服务器地址和端口改成自己的即可:
global $memcached_servers;
$memcached_servers = [
[
'127.0.0.1', // Memcached 服务器地址
11211 // Memcached 服务器端口
]
];
最后,关于在 WordPress 中使用 Memcached:
1. 使用 Memcached 内存缓存来实现 WordPress 站点秒开
2. Memcached 和 Redis 有什么区别,做缓存 WordPress 用哪个好?
3. WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!
WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/
目录下的 object-cache.php
文件复制到 wp-content
目录下即可。
如何构建安全的 WordPress 5:禁用搜索结果动态标题,防止 SEO 垃圾攻击
继续「如何构建安全的 WordPress」系列文章,这是 WordPress 搜索安全相关的第二篇,前面我们介绍了「限制搜索频率,防止搜索滥用攻击」,今天讲讲 WordPress 搜索第二个重大的安全隐患, SEO 垃圾攻击(SEO Spam)。
SEO 垃圾攻击
什么是SEO 垃圾攻击(SEO Spam):
SEO 垃圾攻击(SEO Spam),也称为 搜索引擎投毒(Search Engine Poisoning),是指黑客或黑产通过操纵搜索引擎优化(SEO)技术,向目标网站注入垃圾内容或篡改网页元素(如标题、关键词、链接等),使其在搜索引擎结果中显示恶意或无关信息,从而误导用户或提升黑产网站的排名。如下(我做个演示):

它还有一下几个行业通用术语:
- SEO Spam / SEO Poisoning:通过操纵页面元素(如标题、描述)提升黑产网站在搜索引擎中的可见性。
- Title Tag Hijacking:直接劫持标题标签内容,属于 On-Page SEO 攻击 的一种。
- Search Index Pollution:污染搜索引擎索引的恶意行为(Google 官方文档曾用此术语描述类似攻击)。
攻击者通过构造恶意搜索请求(如 ?s=黑产关键词
+域名),利用 WordPress 默认的搜索结果页动态标题机制(例如 wp_title()
函数),将恶意内容注入到 <title>
标签中。这属于 注入攻击(Injection Attack) 的子类,但更贴近 SEO 滥用 场景。
为什么 WordPress 经常被这类攻击呢?因为WordPress 默认将搜索关键词动态插入标题(例如 搜索:{关键词} - 网站名
),而黑产通过自动化工具高频请求含恶意关键词的搜索页(如 ?s=赌博网站
),导致这些关键词被收录到搜索引擎索引中,甚至排名靠前。
这类攻击造成的损害也是很大的,一旦你的网站有这类情况,可能会被搜索引擎误判为关联黑产内容,导致网站降权或标记为恶意。万一用户通过搜索敏感词进入站点,可能触发安全平台(如 Google Safe Browsing)的警告。
静态化搜索结果标题
那么怎么办呢?其实很简单,禁用 WordPress 搜索结果动态标题,静态化搜索结果标题,比如只显示「搜索结果」这四个字:

WPJAM 搜索优化插件 已经集成了该功能,如下图所示,「搜索增强」的第三个选项「搜索结果页面标题不显示关键字,只显示「搜索结果」四个字」勾选上即可:

WPJAM 搜索优化插件 已经集上面所有的功能和相关代码,直接启用即可,点击查看 WPJAM 搜索优化插件 的详细介绍,Modular 主题也集成了,我会在介绍 WordPress 安全这系列文章的时候,将这些安全相关代码也整合到 Modular 主题中,争取打造最安全的 WordPress 主题。
Memcached 和 Redis 有什么区别,做缓存 WordPress 用哪个好?
前面介绍了使用 Memcached 内存缓存来实现 WordPress 站点秒开,但是很多人问到了 Redis,就是做缓存 Redis 和 Memcached 有什么区别,用哪个更好?今天就给大家做一个简单介绍。
Memcached 和 Redis 有什么区别
首先从模型上看,Memcached 是一个分布式内存缓存系统,专注于简单的键-值对存储,设计简单易用,它不支持复杂数据类型,而 Redis 是一个内存数据结构存储,支持更多的数据结构(如列表、集合、排序集合、哈希等),不仅仅是简单的键-值对。

所以 Memcached 是为简单的读写操作优化的,适合需要快速缓存大量数据的场景,而 Redis 提供了丰富的数据操作功能,对复杂数据操作优化良好,同时也提供了高性能的读写速度,并且 Redis 支持数据持久化,可以将内存数据保存到磁盘,Memcached 没有持久性功能,所有数据都存储在内存中,服务器重启时数据就会丢失,作为缓存这个问题不大。
此外,它们还有一点比较大的区别,就是 Memcached 支持多线程,所以支持高并发访问,而 Redis 一般使用单线程模型,虽然通过 I/O 多路复用技术提供高吞吐量,这样就比较在秒杀等场景下使用,不需要考虑并发的问题,因为单线程。
简单做个功能特性对比表格:
特性 | Memcached | Redis |
---|---|---|
数据结构 | 仅支持键值对(String) | 支持 String、List、Hash、Set 等 |
持久化 | 不支持 | 支持 RDB 快照和 AOF 日志 |
线程模型 | 多线程(高并发读优) | 单线程(避免锁竞争,顺序执行) |
内存管理 | 预分配固定内存,LRU 淘汰 | 支持内存淘汰策略,可配置虚拟内存 |
集群模式 | 依赖客户端分片(如 Twemproxy) | 原生 Cluster 模式支持 |
适用场景 | 简单键值缓存(如会话、HTML片段) | 缓存、消息队列、实时统计等复杂场景 |
Redis 的作者的建议
Redis 的作者 Salvatore Sanfilippo 曾经对这两种基于内存的数据存储系统进行过比较:
- Redis 支持服务器端的数据操作:Redis 相比 Memcached 来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在 Memcached 里,你需要将数据拿到客户端来进行类似的修改再 set 回去。这大大增加了网络 IO 的次数和数据体积。在 Redis 中,这些复杂的操作通常和一般的 GET/SET 一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么 Redis 会是不错的选择。
- 内存使用效率对比:使用简单的 key-value 存储的话,Memcached 的内存利用率更高,而如果 Redis 采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于 Memcached。
- 性能对比:由于 Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。
总结一下:Memcached 是解决简单缓存问题的可靠选择,而 Redis 通过提供更丰富的功能和各种各样的特性而优于 Memcached,这些特性对于解决复杂的场景更有优势。
WordPress 使用哪个做缓存好?
如果单纯作为内存缓存来使用,两者其实没有什么区别,那么为什么 WPJAM Basic 为什么使用 Memcached 呢?
这里有一份 4 核 CPU / 8G 内存的服务器上的测试数据:
操作 | Memcached QPS | Redis QPS |
---|---|---|
GET 请求 | 120,000+ | 100,000+ |
SET 请求 | 90,000+ | 80,000+ |
可以看出在 WordPress 这样简单的键-值缓存,并且需要处理大量简单数据,Memcached 是一个更好的选择。
此外我们一开始就选择了 Memcached 做 WordPress 的内存缓存的存储介质,并且在使用 Memcached 做内存缓存过程中,针对出现的各种的问题,我也做了很多的优化,比如我们在后台「WPJAM」菜单下的「系统信息」中展示「Memcached」的各种信息。

当然如果你已经使用了 Redis 做内存缓存或者更熟悉 Redis,WordPress 官方插件库也有很多第三方提供了 Redis 的 object-cache.php
,和使用 Memcached 一样,只需要将对应的 object-cache.php 上传到 wp-content 目录即可。
此外也有小伙伴问,WPJAM Basic 会不会集成 Redis,让大家自己选,这个可以明确的说,目前作为简单缓存功能,Memcached 已经足够好用,不会再花时间集成 Redis。
最后还有个问题,Memcached 和 Redis 可以一起用吗?如果作为缓存,WordPress 只能选择一个,因为你上传谁的 object-cache.php
,就是用谁得了。
但是不等于使用 Memcached 作为缓存,就不能使用 Redis 了,比如我们之前就利用 Redis 的一些特性做过一些开发,比如因为 Redis 单线程天然串行排队的特性,我们在花生小店秒杀的功能中就是使用 Redis 进行处理的,还有一些简单的消息队列的功能处理,也是基于 Redis 进行开发的。
简单总结
所以最后总结说一下,如果简单的 key-value 的内存缓存,建议使用 Memcached,WordPress 绝大部分站点也是使用 Memcached 进行缓存的,此外 WPJAM Basic 也对此优化得比较完善。
如果要进行复杂的程序开发,比如上面说的电商的秒杀功能 ,消息队列系统等,那么 Redis 才是发挥其长处的地方。
使用 Memcached 内存缓存来实现 WordPress 站点秒开
WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!
任何技术要彻底了解它是怎么工作的,则要去了解它的机制和原理,WordPress 优化也是一样,如果要深度理解如何优化 WordPress,那么就要去了解 WordPress 对象缓存的原理和机制。
所以那么今天就来详细讲解一下 WordPress 缓存的底层原理对象缓存(Object Cache),以及在开发的时候如何使用它对 WordPress 进行加速。
WordPress 对象缓存和服务器设置
WordPress 对象缓存(英文名是:Object Cache)就是 WordPress 的缓存机制,它的主要功能是把数据库查询结果或者复杂运算的结果按照 Key-Value
这样的方式存储到对象里面,此外 WordPress 还支持按照 Group 来按组划分,以避免缓存内容的冲突。下次进行同样操作的时候,可以让直接从这个对象中取出数据,不用重复到数据库中或者其他外部获取数据。

WordPress 对象缓存和服务器设置关系很大,如果系统开启了 #Memcached# 内存缓存,则这个对象是直接存入到内存,在数据未过期之前,以后再次读取这个数据都是直接从内存中读取的,这样效率和速度都非常快的。
如果服务器不支持内存缓存的话,则只能保证在当前页面(PHP同个进程下)下同样的查询或者操作不再重复从数据库中读取了。
WordPress 对象缓存的函数
WordPress 对象缓存技术使用是非常简单的,其核心就是掌握下面下面这四个函数:
- 添加数据到缓存中:
wp_cache_add($key, $data, $group='', $expire=0)
- 设置数据到缓存中:
wp_cache_set($key, $data, $group='', $expire=0)
- 获取缓存中的数据:
wp_cache_get($key, $group='', $force=false, &$found=null)
- 删除缓存中的数据:
wp_cache_delete($key, $group='')
这四个函数会涉及到参数我罗列到一起简单讲下,下面知道个大概,可以收藏,方便使用的时候回来查看,重点还是后面的应用:
参数 | 解释 |
---|---|
$key | 数据在缓存中的健名 |
$data | 要缓存的数据,获取和删除函数无需用这个参数 |
$group | 缓存要添加到的组 |
$expire | 过期时间,可选参数,获取和删除函数无需用这个参数 如果是默认缓存,这个参数没用,如果是内存缓存,是设置缓存的时间。 单位是秒,默认为0(0 的意思就是永远,不会自动过期) |
$force | 这个是获取缓存函数独有的函数,设置为 true 则强制使用持久缓存更新本地缓存 |
$ found | 这个也是获取缓存函数独有的函数,它是一个引用参数,用于存储是否在缓存中找到 key,可以用于消除返回 false 的歧义 |
使用 WordPress 对象缓存
下面以我以 WordPress 相关文章为例,讲讲如何使用 WordPress 对象缓存。
我们知道 WordPress 相关文章插件是通过 tag
和分类来获取相关文章,文章使用相同的 tag 和分类越多,则认为为相关性越强,这样就需要进行多个表联合查询来获取相关文章,连表查询效率一般是比较差的。比如下面是一个比较通用的从数据库中查找相关文章的函数:
function wpjam_get_related_posts($post_id){
global $wpdb;
$term_ids = wp_get_post_terms($post_id, ['category', 'post_tag'], ['fields' => 'ids']);
$terms_ids = implode(',', $term_ids);
$related_posts = $wpdb->get_results("
SELECT object_id, COUNT(*) as count
FROM $wpdb->term_relationships
WHERE term_taxonomy_id IN ($terms_string) AND object_id != $post_id
GROUP BY object_id
ORDER BY count DESC
LIMIT 10"
);
foreach($related_posts as &$post){
$post = get_post($post->object_id);
}
return $related_posts;
}
上面的函数,首先获取文章的标签和分类,然后基于使用相同的标签和分类的数量,通过 SQL 获取相似度最高的 10 篇文章的 ID,然后再相应获取对应的文章(这里为了简化,一般应该要根据文章 ID 批量文章,防止同时多条 SQL 请求)。
但是另外一方面,一篇文章,如果它的标签和分类没有修改的话,那么它的相关文章在一段时间内是不会变动的,所以相关文章的功能就非常适合使用 WordPress 对象缓存进行缓存加速加速。
我们就可以使用 wp_cache_set
函数就是把把相关文章的数据写入缓存的例子,使用当前 post_id
作为 key,related_posts
作为 group,缓存时间为一个小时,即 3600 秒。
$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
把数据存到缓存对象之后,在显示相关文章的时候,就可以使用 wp_cache_get
调用这个对象缓存来使用。
一般的流程是这样的,首先检查下是否已经有相应的缓存,如果你要的信息没有在缓存中,或者已经过期,wp_cache_get()
会返回 false,这时,你就要去数据库中重新获取这些信息,否则就返回在缓存中的信息。
$related_posts_data = wp_cache_get($post->ID,'related_posts');
if(false === $related_posts_data){
$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
}
因为设置了一个小时,相关文章的数据就失效,再次显示的时候会重新请求,,如果你在后台更改了设置,需要立即清理缓存,可以通过相关的 Hook 使用 wp_cache_delete
进行清理:
wp_cacache_delete($post->ID,'related_posts');
这里只是简单删除一下,更详细怎么使用 Hook 的例子,可以去 #WPJAM Basic# 的相关文章扩展中查看详情。
WPJAM 终极方法
通过上面的例子,看到使用 object_cache 都是首先要使用 wp_cache_get
函数去获取,如果不存在,再使用 wp_cache_set
函数去存储,有没有更加方便的方法呢?
有的,#WPJAM Basic# 提供了一个 wpjam_cache
的方法,可以将这个过程合并了,比如上面的例子,可以通过下面的代码实现:
$related_posts_data = wpjam_cache($post->ID,'related_posts', fn()=> wpjam_get_related_posts($post->ID), 3600);
它有四个参数,前面两个和 wp_cache_get()
函数一样,第三个参数是一个回调函数,它会在对象缓存不存在的时候被调用,获取数据并存到缓存中,从而实现自动实现缓存的过程,第四个是缓存时长。可以说除了第三个参数之外,其他参数和 wp_cache_xxx
函数的参数基本一致,使用也更加简洁,是一种高阶函数的写法。
总结
WordPress 对象缓存(Object Cache)是 WordPress 缓存机制,是深入了解对 WordPress 优化的基础,如果要熟悉 WordPress 开发和应用,都要有掌握好他。此外,WPJAM Basic 集成的
函数进一步提高使用效率,只需一步就实现 WordPress 对象缓存。wpjam_cache
WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/
目录下的 object-cache.php
文件复制到 wp-content
目录下即可。
WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!
任何技术要彻底了解它是怎么工作的,则要去了解它的机制和原理,WordPress 优化也是一样,如果要深度理解如何优化 WordPress,那么就要去了解 WordPress 对象缓存的原理和机制。
所以那么今天就来详细讲解一下 WordPress 缓存的底层原理对象缓存(Object Cache),以及在开发的时候如何使用它对 WordPress 进行加速。
WordPress 对象缓存和服务器设置
WordPress 对象缓存(英文名是:Object Cache)就是 WordPress 的缓存机制,它的主要功能是把数据库查询结果或者复杂运算的结果按照 Key-Value
这样的方式存储到对象里面,此外 WordPress 还支持按照 Group 来按组划分,以避免缓存内容的冲突。下次进行同样操作的时候,可以让直接从这个对象中取出数据,不用重复到数据库中或者其他外部获取数据。

WordPress 对象缓存和服务器设置关系很大,如果系统开启了 #Memcached# 内存缓存,则这个对象是直接存入到内存,在数据未过期之前,以后再次读取这个数据都是直接从内存中读取的,这样效率和速度都非常快的。
如果服务器不支持内存缓存的话,则只能保证在当前页面(PHP同个进程下)下同样的查询或者操作不再重复从数据库中读取了。
WordPress 对象缓存的函数
WordPress 对象缓存技术使用是非常简单的,其核心就是掌握下面下面这四个函数:
- 添加数据到缓存中:
wp_cache_add($key, $data, $group='', $expire=0)
- 设置数据到缓存中:
wp_cache_set($key, $data, $group='', $expire=0)
- 获取缓存中的数据:
wp_cache_get($key, $group='', $force=false, &$found=null)
- 删除缓存中的数据:
wp_cache_delete($key, $group='')
这四个函数会涉及到参数我罗列到一起简单讲下,下面知道个大概,可以收藏,方便使用的时候回来查看,重点还是后面的应用:
参数 | 解释 |
---|---|
$key | 数据在缓存中的健名 |
$data | 要缓存的数据,获取和删除函数无需用这个参数 |
$group | 缓存要添加到的组 |
$expire | 过期时间,可选参数,获取和删除函数无需用这个参数 如果是默认缓存,这个参数没用,如果是内存缓存,是设置缓存的时间。 单位是秒,默认为0(0 的意思就是永远,不会自动过期) |
$force | 这个是获取缓存函数独有的函数,设置为 true 则强制使用持久缓存更新本地缓存 |
$ found | 这个也是获取缓存函数独有的函数,它是一个引用参数,用于存储是否在缓存中找到 key,可以用于消除返回 false 的歧义 |
使用 WordPress 对象缓存
下面以我以 WordPress 相关文章为例,讲讲如何使用 WordPress 对象缓存。
我们知道 WordPress 相关文章插件是通过 tag
和分类来获取相关文章,文章使用相同的 tag 和分类越多,则认为为相关性越强,这样就需要进行多个表联合查询来获取相关文章,连表查询效率一般是比较差的。比如下面是一个比较通用的从数据库中查找相关文章的函数:
function wpjam_get_related_posts($post_id){
global $wpdb;
$term_ids = wp_get_post_terms($post_id, ['category', 'post_tag'], ['fields' => 'ids']);
$terms_ids = implode(',', $term_ids);
$related_posts = $wpdb->get_results("
SELECT object_id, COUNT(*) as count
FROM $wpdb->term_relationships
WHERE term_taxonomy_id IN ($terms_string) AND object_id != $post_id
GROUP BY object_id
ORDER BY count DESC
LIMIT 10"
);
foreach($related_posts as &$post){
$post = get_post($post->object_id);
}
return $related_posts;
}
上面的函数,首先获取文章的标签和分类,然后基于使用相同的标签和分类的数量,通过 SQL 获取相似度最高的 10 篇文章的 ID,然后再相应获取对应的文章(这里为了简化,一般应该要根据文章 ID 批量文章,防止同时多条 SQL 请求)。
但是另外一方面,一篇文章,如果它的标签和分类没有修改的话,那么它的相关文章在一段时间内是不会变动的,所以相关文章的功能就非常适合使用 WordPress 对象缓存进行缓存加速加速。
我们就可以使用 wp_cache_set
函数就是把把相关文章的数据写入缓存的例子,使用当前 post_id
作为 key,related_posts
作为 group,缓存时间为一个小时,即 3600 秒。
$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
把数据存到缓存对象之后,在显示相关文章的时候,就可以使用 wp_cache_get
调用这个对象缓存来使用。
一般的流程是这样的,首先检查下是否已经有相应的缓存,如果你要的信息没有在缓存中,或者已经过期,wp_cache_get()
会返回 false,这时,你就要去数据库中重新获取这些信息,否则就返回在缓存中的信息。
$related_posts_data = wp_cache_get($post->ID,'related_posts');
if(false === $related_posts_data){
$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
}
因为设置了一个小时,相关文章的数据就失效,再次显示的时候会重新请求,,如果你在后台更改了设置,需要立即清理缓存,可以通过相关的 Hook 使用 wp_cache_delete
进行清理:
wp_cacache_delete($post->ID,'related_posts');
这里只是简单删除一下,更详细怎么使用 Hook 的例子,可以去 #WPJAM Basic# 的相关文章扩展中查看详情。
WPJAM 终极方法
通过上面的例子,看到使用 object_cache 都是首先要使用 wp_cache_get
函数去获取,如果不存在,再使用 wp_cache_set
函数去存储,有没有更加方便的方法呢?
有的,#WPJAM Basic# 提供了一个 wpjam_cache
的方法,可以将这个过程合并了,比如上面的例子,可以通过下面的代码实现:
$related_posts_data = wpjam_cache($post->ID,'related_posts', fn()=> wpjam_get_related_posts($post->ID), 3600);
它有四个参数,前面两个和 wp_cache_get()
函数一样,第三个参数是一个回调函数,它会在对象缓存不存在的时候被调用,获取数据并存到缓存中,从而实现自动实现缓存的过程,第四个是缓存时长。可以说除了第三个参数之外,其他参数和 wp_cache_xxx
函数的参数基本一致,使用也更加简洁,是一种高阶函数的写法。
总结
WordPress 对象缓存(Object Cache)是 WordPress 缓存机制,是深入了解对 WordPress 优化的基础,如果要熟悉 WordPress 开发和应用,都要有掌握好他。此外,WPJAM Basic 集成的
函数进一步提高使用效率,只需一步就实现 WordPress 对象缓存。wpjam_cache
WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/
目录下的 object-cache.php
文件复制到 wp-content
目录下即可。
网站速度很慢?使用 WordPress 短时缓存(Transients)来优化数据库查询和 HTTP 响应!
每个人都想要一个速度很快的网站,网站速度越快,用户停留和点击页面或购买产品的时间就越长,加快网站速度的方法之一是开启缓存,而缓存背后的逻辑就是存储信息,更具体一点说,就是找到一个比连接数据库更快的存储信息的地方。
在 WordPress 中,如果一些复杂的 SQL 查询或者耗时的 HTTP 请求,其实它们的结果在一定时间内是不变的,那么为了网站速度,如果把这些操作的结果缓存起来,这样下次进行同样的 SQL 查询和 HTTP 请求的时候,就可以直接从缓存中获取数据,从而可以显著加快网站的速度,当然一些复杂计算的结果也可以通过该方法进行缓存。

那么在 WordPress 中如何快速缓存 SQL 查询和 HTTP 响应呢?这个时候就要用到 WordPress 的短时缓存(Transients)功能。
什么是短时缓存(Transients)
我们知道 WordPress 缓存有多种类型,比如对象缓存、浏览器缓存、页面缓存甚至数据库缓存,每种类型都有其用途和设置步骤,比如需要安装插件和更改服务器配置以启用对象缓存等。
那么今天介绍的 Transients API,是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,Transients 本身是“短暂的”或“临时的”意思,那么 Transients API 可以理解为临时缓存或者短暂缓存的意思,我这里将它翻译成短时缓存,它是 WordPress 用来缓存一些复杂的 SQL 查询和运算结果的最简单的方法。
它给这些需要缓存的数据一个过期时间,并且时间一到就会自动删除,所以在制作 WordPress 插件的时候,需要存储一些有一定生命周期的数据的时候,Transients API 就是最好的选择。
简单说,Transients 是一种非常强大的工具,它不仅可以用来避免对页面内容进行不必要的数据库请求,还可以加快生成复杂标记的速度并加快耗时的第三方 API 请求。
Transients 相关函数
首先说下,Transients 的存储,如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中,如果没有开启的话,则存储到 WordPress 数据库的 Options 表中
所以它接口函数和 WordPress 的 Option API (get_option
, add_option
, update_option
, delete_option
))基本一样,唯一区别就是 Transients API 有一个过期时间,并且它没有 add 方法,统一合并成 set 了,所以 WordPress Transients API 有以下三个函数:
// 保存一个数据到短时缓存中
set_transient( string $transient, mixed $value, int $expiration )
// 从短时缓存中获取一个数据
get_transient( string $transient )
// 从短时缓存中删除一个数据
delete_transient( string $transient )
函数的使用过非常简单,这里不做详细解释,简单注意下两点:
- 如果使用获取短时缓存函数
get_transient
去获取数据,已经过期或者不存在的情况下是返回 false 的。 - 完全不用担心 Transients API 会将数据库的 Options 表塞满数据,因为临时变量一旦过期,下次获取的时候就会自动被删除,并且上面也说了如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中。
一个应用 Transients 的例子
🙋♀️🌰 假设你要获取博客的浏览最高的 10 篇文章,文章的浏览数据一般是存在 PostMeta 表中,所以这样的数据库查询会用到 Posts 表和 PostMeta 表进行联表查询,如果文章数量比较多的情况下,这样的查询一般是比较慢的。
而事情的另一面,博客浏览最高的 10 篇文章一般来说在一段时间(比如:12小时)之内很可能是不变的,所以这个功能最适合使用 Transients API 进行缓存了:
$top_10_posts = get_transient('top_10_posts');
if(false === $top_10_posts){ // 临时变量过期了或者根本就没有创建
// 通过 SQL 查询获取流量最高的 10 篇文章,
$top_10_posts = wpjam_get_top_viewd_posts(10);
// 把临时变量存到数据库中,时间为 12 个小时
set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12);
}
我们首先使用 get_transient('top_10_posts')
函数从缓存中看看有没有缓存,如果没有,该函数是返回 false
的。
程序获取缓存结果为 false 的时候,就通过 wpjam_get_top_viewd_posts
这个带有复杂 SQL 的函数获取文章,然后通过函数 set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12)
存到缓存中,并且过期时间设置为 12 小时。
这样下次再去获取浏览最高的文章,直接从缓存中返回了,就不用担心不用担心数据库查询过慢的问题了。
使用 Hook 删除短时缓存
如果由于某种原因某篇流行文章删除,这个时候可能流量最高的文章都可能发生变化,我们就可以使用 delete_transient
函数把这个临时变量删除了,这样我们可以使用 WordPress 的删除文章的 Hook delete_post
进行操作:
add_action('delete_post', fn() => delete_transient('top_10_posts'));
如果你想有新文章发布了,虽然这时候一般不会影响浏览最高的文章列表,但是如果想,也可以把缓存清理了,这时候用到是 publish_post
Hook:
add_action('publish_post', fn() => delete_transient('top_10_posts'));
WPJAM 终极方法
虽然 Transients API 的使用非常简单,它主要逻辑就是首先使用 get_transient()
函数获取缓存,=如果没有,再通过函数 set_transient()
将数据存到缓存中。
但是这里都有要写个判断,并且缓存的名称也要重复写两次,对于我这么懒的程序是不可能接受的,另外它的逻辑感觉上在破坏了程序的主逻辑,所以我在 #WPJAM Basic# 中集成了 wpjam_transient
函数,它通过回调的方式,让只需一步就实现 WordPress 短时缓存:
首先我们实现看看我的 wpjam_transient
函数的实现:
function wpjam_transient($name, $callback, $expire=86400){
$data = get_transient($name);
if($data === false){
$data = $callback();
if(!is_wp_error($data)){
set_transient($name, $data, $expire);
}
}
return $data;
}
可以看到 wpjam_transient
函数把获取和设置短时缓存的函数都内置到了函数中,你只需要关注你程序的主逻辑,所以上面的缓存的浏览最高的 10 篇文章的代码可以简化为 1 行代码:
wpjam_transient('top_10_posts', fn()=> wpjam_get_top_viewd_posts(10), HOUR_IN_SECONDS*12);
是不是非常简洁。🤭
总结
WordPress 短时缓存(Transients API)是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,该功能用的好,特别是用于缓存复杂的 SQL 查询,耗时 HTTP 请求,以及复杂计算的结果等,对于站点有明显的提高,#WPJAM Basic# 集成的 wpjam_transient
函数进一步提高使用效率,只需一步就实现 WordPress 短时缓存。