WordPress 对象缓存:Redis、Memcached 和本机 API
已发表: 2017-11-04可以随意扩展的企业级 WordPress 站点需要一种超越页面和图像的持久缓存机制,一种可以缓存实际 PHP 对象的机制。 尽管 WordPress 通过 WordPress 对象缓存提供对象缓存机制,但还有其他解决方案可以提供强大的杠杆作用和功能。 但在我们进入所有这些之前,首先,我们需要了解什么是对象缓存以及它在 PHP 中是如何工作的。
什么是对象缓存?
PHP 是一种面向对象的语言。 它使用对象范式来构造代码。 因此,您的 WordPress 站点由许多不同的 PHP 对象组成,这些对象不断创建、实例化和销毁(由内存管理器)。 创建和销毁对象会产生开销,尤其是在对象很多的情况下。 但是,由于它们代表核心功能,因此它们中的大多数往往会被大量重用。 这意味着每次应用程序再次需要它们时,都需要从一开始就实例化它们。
如果您可以缓存一个经常使用的实例化对象,这样您就不需要一直销毁和创建它会怎样?
您可以使用 PHP 的serialise()
函数将对象或原语转换为可以存储在内存或磁盘中以供以后访问的数字表示(字节 blob)。 然后使用hash()
函数计算字节 blob 的哈希数并存储它们。 哈希作为键,字节块作为值。 为了检索它,您使用最初存储为键的字节 blob 的计算哈希数。 您可以通过这种方式将任何内容(字符串、整数、对象、布尔值、数组等)转换为值的可存储表示。
例子:
$serialized = serialize( array ( 'test' ));
使用 unserialize() 执行相反的操作:
$original = unserialize ( $serialized );
一般来说,可以通过三种方式缓存对象:使用本机 WordPress 对象缓存、Transients API 或外部键值存储,如 Redis 或 Memcached。
WordPress 对象缓存
WordPress 提供了两个对象缓存 API:原生 WordPress 对象缓存和瞬态 API。 它们是相同的,虽然这可能会引起混淆,但其背后是有逻辑的。
原生 WordPress 对象缓存可以在缓存中存储对象和原语,但默认情况下不能以持久方式存储。 这意味着缓存发生在内存中,并且缓存的对象不会超出请求的生命周期。 因此,您不能在不同的页面加载之间共享您的缓存对象。 您需要使用 Drop-Ins 提供您自己的商店实现,这些插件是可以扩展 WordPress 功能的“高级”插件。 您可以在 WordPress 仪表板上的插件列表中看到它们:

另一方面,Transients API 开箱即用。 您可以将与到期日期绑定的变量、数组、对象直接保存在数据库中,并具有持久对象缓存。 但是,问题是当您的缓存对象过期时,它们仍保留在数据库中占用空间。 这意味着在维护数据库时需要花费额外的开销,每隔一段时间修剪一次过期的对象。
WordPress 会检测您是否实现了自己的持久对象缓存,当它发现是这种情况时,会绕过对 Transients API 的调用并将其路由到 WordPress 对象缓存(因此它们相同的原因)。
开发人员可以实现自己的对象缓存,使用 WordPress 插件(稍后会详细介绍)或我们自己的实现,如果是 Pressidium 客户端。 默认情况下,我们没有打开对象缓存,因为如果在错误的情况下使用这可能会导致性能下降。 对于 WordPress 网站中的对象缓存,没有“一刀切”的解决方案。
Redis 和 Memcached
键值存储不使用表和预定义的数据类型将信息存储在 RDBMS 等记录中。 它们旨在存储和检索键/值对,就像您在编程语言中找到的字典数据结构一样。

这种存储的一个很好的例子是 Redis。 除了字典数据结构外,它还支持许多其他数据结构,包括高级数据结构,例如带有范围查询的排序集,以及带有半径查询的地理空间索引。 它提供持久对象缓存。

Redis 不仅仅是一个键值对存储或缓存。 它支持集群配置中的数据复制、脚本编写和高可用性。 您还可以微调所需的磁盘持久性级别。 Redis 的好处是,如果你重新启动,你的大部分缓存仍然在磁盘上,丢失的数据只是一小部分。 问题是,在重新启动时,服务器将不得不重建缓存,这在大多数情况下会增加负载。 使用 Redis,这不会发生。 此外,过期的对象会立即从数据库中删除。 那里也没有管理开销时间。
Redis Labs 有一个很好的页面展示了 Redis 在企业中的用例:从超大数据集到全文搜索、实时序列、Spark 集成等等。
尽管所有这些功能都以复杂性为代价,并且在某些情况下可能以速度为代价,但优化您的 Redis Drop-In 代码可以获得相当多的收益。 不要忘记 Redis 会进行持久对象缓存这一事实,而 Memcached 不会,尽管它使用起来要简单得多。

Memcached 是根据官网介绍的内存中高性能对象缓存系统,专为加速动态 Web 应用程序和减轻数据库负载而设计。 它的使用也比 Redis 简单直接得多。
由于专门设计用于对网页进行对象缓存,并且它使用内存数据库这一事实使其成为目前最快的对象缓存解决方案。 但是,正如我们之前提到的,如果您的服务器重新启动,您的缓存就会失效。 在重建之前,您可能会遇到负载增加的情况。 但正如创建者所说:“将其视为您网站的短期记忆”,因此这取决于您首先要做什么。
由于 Memcached 使用内存数据库来保存缓存,因此在缓存 SQL 查询、函数调用输出等方面非常有效。
WordPress 插件
- WP Redis,官方 Redis WordPress 插件。 支持 WP-CLI、集群和复制。
- Redis 对象缓存 WordPress 的另一个后端 Redis 插件。
- Memcached 对象缓存,Memcached 的后端。
- Delete Expired Transients,这个插件从数据库中删除过期的瞬态对象。 它也支持多站点!
如何运行基准测试
我们这篇文章的重点是让您对对象缓存感到兴奋并开始自己进行修补。 您可以尝试各种持久缓存实现,看看您的应用程序表现如何。 您可以使用 PHP 的 microsecond() 函数对调用进行基准测试。 例如:在调用 wp_cache_get( microsecond()
之前和之后调用wp_cache_get()
,减去值并存储结果。 对各种缓存实现执行此操作,并查看在哪些情况下您会注意到性能提升。
在 Pressidium,我们没有默认启用对象缓存,尽管这是可以请求的,但我们通常不建议从一开始就支持它。 我们运行测试并确保您的网站将从中受益。
结论
假设为了呈现一个页面,应用程序需要读取 2,000 个瞬态对象。 这意味着对数据库进行 2,000 次读取。 通过使用持久对象缓存系统,这 2,000 次读取被卸载到键值存储。 如果您使用 memcached,那么您可能会在突然重启时丢失所有缓存。 一般来说,Redis 可能不如 Memcached 快,但它的企业特性和持久性从长远来看会让您受益。
然而,一种尺寸并不适合所有人! 例如,我们已经看到 Redis 实例实际上减慢了网站的速度,而在其他情况下,它们的速度令人难以置信。 这与您的应用程序使用的许多对象有关:一般来说,如果您的应用程序使用几个(比如说十几个),您不会从对象缓存中获得太多好处,在最坏的情况下,您将有网络开销。 但是,如果您的应用程序有数百个,那么查看一下可能会有所回报。