最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
ThinkPHP 5.1 利用 APCu 缓存热点数据降低 DB 压力扩展
时间:2026-07-27 08:05:47 编辑:袖梨 来源:一聚教程网
APCu是ThinkPHP 5.1单机部署下缓存用户配置、地区字典等低频数据的最优方案,需安装扩展、配置store、封装两级读取逻辑,并同步清理两级缓存以保证一致性。
ThinkPHP 5.1 应用中频繁读取用户配置、站点开关、地区字典等不变或低频变更数据时,每次请求都查数据库会迅速拖慢响应、耗尽 MySQL 连接数;APCu 作为进程内内存缓存,能直接拦截这些重复读取,0 网络开销、微秒级返回,是单机部署下最轻量高效的热点数据缓存方案。
启用 APCu 扩展并验证加载状态
执行 sudo apt install php-apcu(Ubuntu/Debian)或 sudo yum install php-apcu(CentOS),安装后重启 PHP-FPM 服务: sudo systemctl restart php-fpm。
运行 php -m | grep apcu,若输出 apcu 则说明扩展已启用;若无输出,检查 /etc/php/*/mods-available/apcu.ini 是否存在且未被注释,确认其中包含 extension=apcu.so。
【必须关闭 apcu.enable_cli=0】 否则命令行环境(如 artisan 命令、crontab 脚本)会误用 APCu 导致缓存不可见,而 Web 请求正常——这种不一致极易引发调试困惑。
立即学习“PHP免费学习笔记(深入)”;
在 cache.php 中配置 APCu 驱动
打开 config/cache.php,在 'stores' 数组内新增 'apcu' 配置项:
'apcu' => [ 'type' => 'apcu', 'prefix' => 'tp5_apcu_', 'expire' => 3600,],
注意:不要修改 'default' 键值,保留其为 'file' 或 'redis';APCu 仅作为辅助驱动按需调用,避免全局切换导致标签等功能失效。
配置中的 prefix 必须显式指定,否则不同模块缓存键可能冲突——例如 get('status') 在用户模块和系统模块中会被写入同一 key。
封装两级缓存读取逻辑
第一步:定义统一读取函数,优先查 APCu,未命中再查 Redis,最后 fallback 至数据库:
function getHotConfig($key, $ttl = 3600) { $value = thinkCache::store('apcu')->get($key); if ($value !== false) return $value; $value = thinkCache::store('redis')->get($key); if ($value !== false) { thinkCache::store('apcu')->set($key, $value, $ttl); return $value; } $value = db('sys_config')->where('k', $key)->value('v'); if ($value !== null) { thinkCache::store('redis')->set($key, $value, $ttl); thinkCache::store('apcu')->set($key, $value, $ttl); } return $value;}
第二步:在控制器中调用 getHotConfig('site_open') 即可,无需关心底层哪一层命中。
第三步:对更新操作,必须同步清理两级缓存——先 thinkCache::store('apcu')->rm('site_open'),再 thinkCache::store('redis')->set('site_open', $newVal, 3600)。只清 Redis 不清 APCu,下次请求仍会从本地内存返回旧值。
规避 APCu 缓存穿透与空值陷阱
方法一:对数据库查无结果的 key,不存 null,改存占位符字符串 '__APCU_EMPTY__' 并设短 TTL(如 60 秒):
if ($dbResult === null) { thinkCache::store('apcu')->set($key, '__APCU_EMPTY__', 60); return false;}
方法二:读取时显式判断 if ($val === '__APCU_EMPTY__') return false;,避免业务层把字符串当有效数据处理。
APCu 不支持缓存标签(tag),Cache::tag('config')->clear() 对 APCu 驱动完全无效——该操作只会清空 file 或 redis 驱动下的对应标签,APCu 层仍残留旧数据,务必手动逐 key 清理或全量 apcu_clear_cache()(慎用,影响全站)。