PHP缓存命中率需按后端分层监控:APCu用apcu_cache_info()取num_hits/num_misses;Redis用INFO stats的keyspace_hits/misses差分计算;OpCache的hits仅反映文件加载,与业务数据缓存无关。

PHP 本身不提供内置的缓存命中率监控机制,必须依赖具体缓存后端(如 Redis、APCu、Memcached)暴露的指标,再通过代码主动采集和计算。直接读 opcache_get_status() 或调用 Redis::info() 是最可行的起点。
查 APCu 缓存命中率:用 apcu_cache_info() 看实时计数
APCu 的命中/未命中数据藏在 apcu_cache_info('user') 或 apcu_cache_info('system') 返回数组的 num_hits 和 num_misses 字段里,不是所有版本都默认开启统计——需确认 apc.enable_cli=1(CLI 下)且 apc.stat=1(Web 下),否则 num_hits 恒为 0。
实操建议:
- 每次采样先调用
apcu_clear_cache('user')清空前状态(仅开发/测试环境),避免旧数据干扰趋势判断 - 命中率 =
num_hits / (num_hits + num_misses),分母为 0 时需单独处理,避免除零警告 - 不要在高并发请求中频繁调用
apcu_cache_info(),它会锁住共享内存段,可能拖慢响应
Redis 缓存命中率:解析 INFO commandstats 和 INFO stats
Redis 的 keyspace_hits / keyspace_misses 只反映 GET/SET 类命令,而 commandstats 能看到每个命令的调用次数与耗时,更适合定位「哪些操作拖累命中率」。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 用
$redis->info('stats')['keyspace_hits']和['keyspace_misses']计算全局命中率,但注意该值是自 Redis 启动以来的累计值,需定时差分才能得周期命中率 -
commandstats中关注cmdstat_get.calls和cmdstat_get.failed_calls,后者非零说明存在 key 类型错误等异常,不是单纯缓存未命中 - 如果用 Pipeline 或 Lua 脚本批量读写,
keyspace_hits不会准确反映实际业务命中情况——脚本内逻辑绕过常规 key 查询路径
OpCache 命中率监控:别只看 opcache_get_status()['opcache_statistics']
opcache_get_status() 返回的 opcache_statistics 包含 hits、misses、blacklist_misses,但这些仅统计 PHP 文件加载阶段,和业务层「数据缓存」无关。误当成 APCu 命中率会导致完全错误的结论。
实操建议:
- 检查
opcache.revalidate_freq设置:若为 0,文件修改后不会重载,misses几乎为 0,此时命中率数字失去参考价值 -
blacklist_misses高说明大量文件被 opcache 主动排除(如路径匹配了opcache.blacklist_filename),需检查排除规则是否过宽 - OpCache 命中率稳定在 95%+ 是常态;低于 80% 才值得排查,优先看
memory_usage.used_memory是否接近memory_usage.total_memory,内存不足会强制淘汰
真正难的不是取数,而是把「缓存命中率」和业务请求链路对齐:一次 HTTP 请求可能触发多个缓存层(OpCache → APCu → Redis),每层的「命中」定义不同,混在一起统计毫无意义。盯紧你正在优化的那一层,其他层关掉或打标隔离。











