apcu是php进程内用户数据缓存扩展,不跨进程、不持久、不支持集群;它是apc的精简版,仅保留用户缓存功能,移除字节码缓存(由opcache承担),php 7+需单独安装并启用,常因配置遗漏或进程隔离导致缓存不生效。

APCu 是 PHP 进程内缓存的轻量级首选,但它不跨进程、不持久、不支持集群——用对场景才能真正“轻量”。
APCu 和 APC、OPcache 到底什么关系?
APCu 是 APC 的“缓存模块精简版”:只保留 apcu_store() / apcu_fetch() 等用户数据缓存功能,移除了已由 OPcache 承担的字节码缓存部分。PHP 7+ 不再内置 APC,apcu 扩展需单独安装(如 apt install php-apcu),且必须启用 extension=apcu.so;OPcache 默认开启,但和 APCu 互不干扰。
常见错误现象:Call to undefined function apcu_fetch() —— 检查是否漏装扩展,或 CLI 和 FPM 的 php.ini 配置不一致(尤其 Docker 或多版本共存环境)。
怎么安全地写入和读取 APCu 缓存?
APCu 的 key 是字符串,值支持大多数 PHP 类型(含数组、对象),但序列化/反序列化由扩展自动处理,无需手动调用 serialize()。
立即学习“PHP免费学习笔记(深入)”;
-
apcu_store($key, $value, $ttl):$ttl 单位为秒,0 表示永不过期(但受内存限制,实际可能被 LRU 清理) -
apcu_fetch($key)返回false表示未命中(注意不是null),建议用!== false判断 - 并发写入无原子锁,若需“先读后写”,应改用
apcu_add()(仅当 key 不存在时写入)或加应用层锁
示例:
if (($data = apcu_fetch('user_123')) === false) {
$data = getUserFromDb(123); // 实际查询
apcu_store('user_123', $data, 300); // 缓存 5 分钟
}
为什么本地开发能用,上线后缓存总不生效?
核心原因:APCu 数据**不跨 PHP 进程**。FPM 下每个 worker 是独立进程,CLI 脚本也完全隔离。这意味着:
- Web 请求写入的缓存,另一个请求可能读不到(如果落在不同 worker)——这不是 bug,是设计如此
- CLI 命令(如 cron)无法共享 Web 请求的缓存,反之亦然
- 重启 PHP-FPM 或 Apache/Nginx 后,所有 APCu 数据清空
典型误用场景:用 APCu 存“全局开关”或“计数器”,结果各进程各自为政。这类需求应换 Redis 或数据库。
怎么调优 APCu 内存和清理行为?
默认 32MB(apc.shm_size=32M)通常够用,但需根据缓存对象大小和数量调整。关键配置项:
-
apc.enabled=1:必须开启(CLI 下默认关闭,需显式设为 1) -
apc.shm_size:建议按预估总量 × 1.5 设置,避免频繁 LRU 驱逐 -
apc.ttl和apc.user_ttl:控制默认过期时间,但建议代码中显式传$ttl更可控 -
apc.slam_defense=0:禁用“雪崩防御”(旧版有,新版默认关),避免高并发下批量失效
监控命令:apcu_cache_info() 查当前使用量、命中率;apcu_clear_cache('user') 仅清用户缓存(慎用,会清空全部)。
容易被忽略的一点:APCu 的 LRU 清理不保证及时性——内存满时才触发,且只清理过期项或最久未用项。如果缓存大量长 TTL 数据,又突然写入大批新数据,旧数据可能意外残留很久。











