无尘阁日记

无尘阁日记

PHP 文件缓存机制全解析:Stat Cache 与 Realpath Cache 的本质区别
2026-03-02

问:

1)stat cache

缓存 file_exists、filesize、filemtime 等结果


2)realpath cache

缓存路径解析结果(比如 ../a/../b 这种路径转换)


这俩啥区别?

答:

这个问题问得非常到位。
很多人知道有缓存,但不知道这两层缓存“缓存的根本不是同一种东西”。

我给你用工程视角讲清楚。

一、核心区别一句话版

stat cache 缓存的是:
“这个文件现在是什么状态?”

realpath cache 缓存的是:
“这个路径最终指向哪里?”

一个缓存“文件属性”
一个缓存“路径解析结果”

完全不同层级。

二、我们从文件访问的完整流程讲

当你写:

file_exists('../a/../b/test.txt');

PHP 内部其实分两步:

第一步:路径解析
把 ../a/../b/test.txt
转换成真正的绝对路径,比如:

/var/www/project/b/test.txt

这一步用到 realpath cache。

第二步:文件状态查询
去问系统:

这个文件存在吗?
大小多少?
修改时间多少?

这一步用到 stat cache。

所以完整链路是:

你的代码

realpath 解析

stat 查询

操作系统

磁盘

三、realpath cache 具体干什么?

它缓存的是:

路径字符串 → 绝对路径

例如:

"../a/../b/test.txt"
→ "/var/www/project/b/test.txt"

以及符号链接解析结果。

它不关心文件大小
不关心是否存在
不关心修改时间

它只管:

“这条路径最后指向哪里?”

存在于:

realpath_cache_size
realpath_cache_ttl

这是 php.ini 可配置的。

四、stat cache 具体干什么?

它缓存的是:

某个路径的文件元数据

比如:

file_exists
filesize
filemtime
is_dir
is_file

这些函数的结果。

它缓存的是“文件状态结果”。

而且是当前请求生命周期内缓存。

五、举个清晰对比案例

场景一:文件被删除

unlink('a.txt');

如果之前调用过:

file_exists('a.txt');

那么 stat cache 里记着它存在。

你必须:

clearstatcache();

否则 file_exists 可能还返回 true。

这里和 realpath 没关系。

场景二:符号链接被修改

假设:

/data/link → /data/old

你把 link 改成指向:

/data/new

如果 realpath cache 还记着旧指向:

那么路径解析可能还是 old。

这时候你要:

clearstatcache(true);

注意 true
因为要清 realpath cache。

六、再从内存层级看区别

realpath cache
缓存的是“字符串映射关系”

stat cache
缓存的是“文件元数据结构”

一个更像:

路径映射字典

一个更像:

文件属性快照

七、性能层面差异

realpath cache
是为了减少路径解析开销
尤其是大量 include 文件时

stat cache
是为了减少频繁的文件系统调用

两者优化目标不同。

八、什么时候必须清哪个?

普通 rename、copy 后判断
清 stat cache 就够

如果涉及:

符号链接
动态目录挂载
chroot 切换
路径结构变化

才需要清 realpath cache

也就是:

clearstatcache(true);

九、工程级理解总结

realpath cache
解决“我是谁?”

stat cache
解决“我现在什么状态?”

一个是身份解析
一个是状态记忆

十、给你一个终极记忆口诀

路径变了 → 清 realpath
状态变了 → 清 stat
不确定 → true 一起清

如果你愿意,我可以再讲一个更深的:

为什么 realpath cache 是跨函数有效,而 stat cache 只在请求内有效。