返回博客

如何通过正确的缓存加速 Drupal:OPcache、APCu 和共享后端(Redis 或 Memcached)

2025-08-1310 min read

如果您的 Drupal 网站感觉缓慢,缓存通常是解决方案。但不是单一的解决方案。不同的层级解决不同的问题。这就是为什么 OPcache、APCu 和像 Redis 或 Memcached 这样的共享后端经常一起出现。它们各自加速了堆栈的特定部分。正确使用它们,Drupal 会变得敏捷。错误使用它们,它仍然会拖沓。

警告:为 Drupal 缓存分区选择一个共享后端。使用 RedisMemcached,不要为同一分区同时使用两者。

一览:必须做 vs 高级

  • 必须做:在 PHP 中启用 OPcache。为本地缓存打开 APCu。在多服务器设置中为分区选择一个共享后端。
  • 高级:映射特定分区,调整 Redis 客户端超时,调整 Memcached 条目大小,压缩大型 Redis 值,根据实际使用情况调整池大小。

快速决策指南

设置必须做共享后端最适合备注
单服务器OPcache + APCu可选单节点上的小型网站数据库缓存可能就足够了。如果流量增长,可以添加 Redis 或 Memcached。
多服务器OPcache + APCuRedis 或 Memcached负载均衡集群渲染动态页面缓存页面默认数据使用一个共享后端。
高变动性内容OPcacheRedis复杂的标签和失效结构和持久化选项有帮助。
精简简单OPcacheMemcached纯粹的缓存,开销最小非常快,本质上是短暂的。

每个缓存的作用

  • 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)
OPcacheopcache.memory_consumptionMB = (代码库 MB × 3) + 32
OPcacheopcache.max_accelerated_files≈ 1.5 × PHP 文件数(使用 10000、16229、32531)
APCuapc.shm_sizeMB ≈ (键数 × (平均条目字节数 + 100) × 1.2) ÷ 1,000,000
RedismaxmemoryMB ≈ (条目数 × (平均条目字节数 + 50) × 1.3) ÷ 1,000,000
Memcached-mMB ≈ (条目数 × 平均条目字节数 × 1.3) ÷ 1,000,000
Memcached-I从 4 MB 开始;如有需要则增加

常见误区

  1. 误区:OPcache 缓存 HTML真相:它缓存编译后的 PHP 代码。
  2. 误区:APCu 可跨服务器工作真相:它仅限于单个服务器进程。
  3. 误区:Redis 总是优于 Memcached真相:根据需求选择。
  4. 误区:缓存未命中意味着有问题真相:缓存未命中是正常现象,会在流量增加时预热。

快速设置清单

  • 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。保持简单,衡量结果,并进行调整。