php无内置读写分离缓存,实为开发者设计的两级缓存策略:apcu作本地读缓存、redis作中心写缓存,需同步清理多进程apcu并避免误用opcache。

PHP 本身没有内置的“读写分离缓存”机制,所谓“读写分离缓存”不是标准术语,而是开发者为缓解缓存雪崩、穿透或主存储压力,人为将 read 和 write 操作路由到不同缓存层(比如本地内存 + 分布式 Redis)的一种策略。它不等于数据库读写分离,也不依赖 PHP 语言特性,关键在逻辑设计和缓存选型。
什么时候该考虑两级缓存架构(本地 + 远程)
单靠 Redis 或 Memcached 在高并发读场景下容易成为网络瓶颈;而全用 apcu 或 opcache 又无法跨进程共享,更新不一致。两级缓存本质是用本地缓存扛读、远程缓存保一致:
- 适合读多写少、数据变更不频繁但对读响应要求极高的场景(如商品基础信息、配置项)
- 不适合实时性极强的数据(如秒杀库存),因为本地缓存会延迟失效
- 必须配合合理的失效策略(主动删除远端 + 清空本地,或设置短 TTL + 后台异步刷新)
apcu 作本地读缓存 + redis 作中心写缓存怎么配
典型组合:用 apcu 存高频只读副本,所有写操作先落 redis,再清除本机 apcu 对应 key;读时优先查 apcu,未命中再查 redis 并回填。
注意点:
Difeye是一款超轻量级PHP框架,主要特点有: Difeye是一款超轻量级PHP框架,主要特点有: ◆数据库连接做自动主从读写分离配置,适合单机和分布式站点部署; ◆支持Smarty模板机制,可灵活配置第三方缓存组件; ◆完全分离页面和动作,仿C#页面加载自动执行Page_Load入口函数; ◆支持mysql,mongodb等第三方数据库模块,支持读写分离,分布式部署; ◆增加后台管理开发示例
立即学习“PHP免费学习笔记(深入)”;
-
apcu是 per-process 的,FPM 下每个 worker 有独立内存空间,apcu_clear_cache()只清当前进程,不能广播清理 - 写操作后不能只删
rediskey,必须同步触发本机apcu_delete($key)(否则其他请求仍可能读到旧值) - 推荐用
apcu_entry()带回调的方式读取,避免重复查redis和重复写apcu - 示例片段:
function get_user_info($uid) {
$key = "user:{$uid}";
return apcu_entry($key, function() use ($key, $uid) {
// 回调里查 redis,失败则返回 null,apcu 不缓存
$data = redis()->get($key);
if ($data === false) {
$data = fetch_from_db($uid); // 回源
if ($data) {
redis()->setex($key, 3600, json_encode($data));
}
}
return $data ? json_decode($data, true) : null;
}, 600); // apcu 缓存 10 分钟
}
为什么不要用 opcache 当缓存容器
opcache 是为加速 PHP 脚本编译而设的,不是通用键值缓存。它不支持按 key 删除、不提供 TTL、无法序列化复杂结构,且启用 opcache.file_cache_only=1 时甚至不支持运行时写入。
- 误用
opcache_get_status()['cache_full']判断缓存容量?那是 opcode 缓存区满载状态,和业务数据无关 - 试图用
opcache_compile_file()缓存 JSON?会直接报错或静默失败 - 真正需要的是
apcu(共享内存)或memcached(分布式),不是opcache
缓存失效时最容易漏掉的一步
多数人记得删 Redis,却忘了通知所有 PHP-FPM worker 清除本地 apcu。没有跨进程通信机制的话,只能靠“懒清除”——让下次读请求发现过期后自动回源更新,但这会造成短暂不一致。
- 可行解法之一:用 Redis 的
PUB/SUB通道广播失效事件,各 worker 订阅后执行apcu_delete() - 更轻量做法:写操作后,在 Redis 写一个带时间戳的
version:user:123key,读时先比对版本号再决定是否跳过apcu - 绝对别用
sleep(1)等几毫秒再删本地缓存——既不可靠又拖慢响应
真正的难点不在代码怎么写,而在判断哪些数据值得两级缓存、TTL 设多长、失效广播要不要加、以及能否接受几秒内的脏读。这些没法套模板,得看监控里的缓存命中率、Redis 延迟、APCU 内存占用三个指标来回调。










