如何通过正确的缓存加速 Drupal:OPcache、APCu 和共享后端(Redis 或 Memcached)
2025-08-13•10 min read
如果您的 Drupal 网站感觉缓慢,缓存通常是解决方案。但不是单一的解决方案。不同的层级解决不同的问题。这就是为什么 OPcache、APCu 和像 Redis 或 Memcached 这样的共享后端经常一起出现。它们各自加速了堆栈的特定部分。正确使用它们,Drupal 会变得敏捷。错误使用它们,它仍然会拖沓。
警告:为 Drupal 缓存分区选择一个共享后端。使用 Redis或Memcached,不要为同一分区同时使用两者。
一览:必须做 vs 高级
- 必须做:在 PHP 中启用 OPcache。为本地缓存打开 APCu。在多服务器设置中为分区选择一个共享后端。
- 高级:映射特定分区,调整 Redis 客户端超时,调整 Memcached 条目大小,压缩大型 Redis 值,根据实际使用情况调整池大小。
快速决策指南
设置 | 必须做 | 共享后端 | 最适合 | 备注 |
---|---|---|---|---|
单服务器 | OPcache + APCu | 可选 | 单节点上的小型网站 | 数据库缓存可能就足够了。如果流量增长,可以添加 Redis 或 Memcached。 |
多服务器 | OPcache + APCu | Redis 或 Memcached | 负载均衡集群 | 为渲染、动态页面缓存、页面、默认、数据使用一个共享后端。 |
高变动性内容 | OPcache | Redis | 复杂的标签和失效 | 结构和持久化选项有帮助。 |
精简简单 | OPcache | Memcached | 纯粹的缓存,开销最小 | 非常快,本质上是短暂的。 |
每个缓存的作用
- OPcache:通过缓存编译后的脚本来加速 PHP 本身。
- APCu:本地、每个服务器的键值缓存,用于微小的查找。
- Redis:用于缓存、队列、锁、会话的共享内存数据存储。
- Memcached:共享内存键值缓存,非常简单快速。
这些如何融入 Drupal
- OPcache:在 PHP 层启用。不是 Drupal 模块。
- APCu:服务本地缓存和引导数据。
- Redis 或 Memcached:将渲染、动态页面缓存、页面、默认、数据映射到共享后端。还支持会话、锁和队列。
相关:状态缓存(Drupal 10.3+,Drupal 11 中默认启用)。详情请参阅另一篇文章:使用 $settings['state_cache']
加速 Drupal 后端。
专业提示:在多服务器设置中,将引导保留在 APCu 中以获得超低延迟,并将其余部分移至共享后端。
settings.php 快速配置示例
粘贴,然后调整。
Redis
Drupal 集成
$settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml';
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['redis.connection']['port'] = 6379;
$settings['cache']['default'] = 'cache.backend.redis';
$settings['cache']['bins']['render'] = 'cache.backend.redis';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.redis';
$settings['cache']['bins']['page'] = 'cache.backend.redis';
性能调优
// 可选压缩
$settings['redis_compress_length'] = 100;
$settings['redis_compress_level'] = 1;
// 客户端超时(PhpRedis)
$settings['redis.connection']['timeout'] = 1.0;
$settings['redis.connection']['read_timeout'] = 1.0;
$settings['redis.connection']['retry_interval'] = 100;
$settings['redis.connection']['persistent'] = TRUE;
- container_yamls:注册 Redis 服务。
- interface:选择客户端。PhpRedis 是原生扩展。
- host/port:指定连接目标。在同一主机上优先使用 Unix 套接字。
- cache.default:为未映射的分区设置默认后端。
- bins:将特定分区映射到 Redis。
- compress_length/level:压缩大型值以节省内存。
- timeouts/persistent:设置连接/读取超时并重用连接。
Memcached
Drupal 集成
$settings['container_yamls'][] = 'modules/contrib/memcache/memcache.services.yml';
$settings['memcache']['servers']['127.0.0.1:11211'] = 'default';
$settings['memcache']['bins']['render'] = 'default';
$settings['memcache']['bins']['dynamic_page_cache'] = 'default';
$settings['memcache']['bins']['page'] = 'default';
$settings['cache']['default'] = 'cache.backend.memcache';
- container_yamls:注册 Memcache 服务。
- servers:定义服务器列表和池名称。
- bins:将分区映射到池。
- cache.default:为未映射的分区设置默认后端。
APCu 用于本地分区
// 需要 APCu 后端模块
$settings['cache']['bins']['bootstrap'] = 'cache.backend.apcu';
- bootstrap:将热引导数据保留在进程中以获得最低延迟。
运行时/服务器设置(settings.php 之外)
PHP 设置(php.ini)
OPcache
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=192
opcache.max_accelerated_files=16229
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1
opcache.enable
:为 FPM 或 Apache 打开 OPcache。opcache.enable_cli
:为 CLI 关闭 OPcache。opcache.memory_consumption
:为编译后的脚本分配内存池。opcache.max_accelerated_files
:设置哈希表大小。opcache.validate_timestamps
:检查文件时间戳是否更改。对于一次性部署,设置为 0。opcache.revalidate_freq
:当validate_timestamps
= 1 时,设置时间戳检查之间的秒数。opcache.interned_strings_buffer
:为共享字符串分配内存。opcache.fast_shutdown
:启用更快的请求关闭。
APCu
apc.enabled=1
apc.enable_cli=0
apc.shm_size=128M
apc.ttl=0
apc.gc_ttl=3600
apc.enabled
:为 FPM 打开 APCu。apc.enable_cli
:为 CLI 关闭 APCu。apc.shm_size
:设置总共享内存。apc.ttl
:设置条目的默认 TTL。apc.gc_ttl
:设置保留孤立条目的时间。
Redis 服务器(redis.conf)
maxmemory 2gb
maxmemory-policy allkeys-lru
timeout 1
tcp-keepalive 60
maxmemory
:设置内存上限。maxmemory-policy
:设置内存满时的驱逐行为。timeout
:设置空闲客户端超时(秒)。tcp-keepalive
:设置保活探测的间隔。
Memcached 服务器(标志)
memcached -m 2048 -I 4m -f 1.25 -o slab_reassign,slab_automove
-m
:设置总内存(MB)。-I
:设置最大条目大小。-f
:设置 slab 类的增长因子。-o slab_reassign,slab_automove
:启用 slab 再平衡。
容量快速规则
缓存 | 关键设置 | 快速规则(MB) |
---|---|---|
OPcache | opcache.memory_consumption | MB = (代码库 MB × 3) + 32 |
OPcache | opcache.max_accelerated_files | ≈ 1.5 × PHP 文件数(使用 10000、16229、32531) |
APCu | apc.shm_size | MB ≈ (键数 × (平均条目字节数 + 100) × 1.2) ÷ 1,000,000 |
Redis | maxmemory | MB ≈ (条目数 × (平均条目字节数 + 50) × 1.3) ÷ 1,000,000 |
Memcached | -m | MB ≈ (条目数 × 平均条目字节数 × 1.3) ÷ 1,000,000 |
Memcached | -I | 从 4 MB 开始;如有需要则增加 |
常见误区
- 误区:OPcache 缓存 HTML — 真相:它缓存编译后的 PHP 代码。
- 误区:APCu 可跨服务器工作 — 真相:它仅限于单个服务器进程。
- 误区:Redis 总是优于 Memcached — 真相:根据需求选择。
- 误区:缓存未命中意味着有问题 — 真相:缓存未命中是正常现象,会在流量增加时预热。
快速设置清单
- OPcache:
- 在 PHP 中启用扩展。
- 为生产环境调整内存大小和重新验证设置。
- 确保有足够的
opcache.memory_consumption
来容纳您的代码库。
- APCu:
- 安装 PHP 扩展。
- 如果您同时运行 CLI 和 FPM,请确认相关设置。
- 为
apc.shm_size
设置足够大的空间以避免驱逐。
- Redis:
- 安装服务器和 PHP 扩展。
- 添加 Drupal Redis 模块并映射正确的缓存分区。
- 设置客户端超时,并考虑会话、锁和队列。
- Memcached:
- 安装服务器和 PHP 扩展。
- 添加 Drupal Memcache 模块并映射您想要的分区。
- 为最大条目大小设置
-I
;确保应用程序能容忍缓存丢失。
避免这些陷阱
- 避免为同一分区混合使用 Redis 和 Memcached。
- 避免缓存容量不足。监控驱逐和命中率。
- 避免过度缓存。专注于昂贵、可重用的数据。
- 避免破坏失效机制。尊重缓存标签和上下文。
如何衡量成功
- 响应时间趋势:预热后,首次字节时间(TTFB)应有所下降。
- 数据库负载:每个请求的查询次数减少,数据库 CPU 使用率降低。
- 命中率:跟踪缓存命中率。如果命中率保持较低,请检查分区映射和 TTL。
- 错误日志:关注来自 Redis 或 Memcached 的连接错误或超时。
最后的想法
从 OPcache 开始,添加 APCu,然后为共享分区添加 Redis 或 Memcached。保持简单,衡量结果,并进行调整。