使用 apcu_store() 缓存数组时需确保数据可序列化,避免含资源句柄或闭包;键名须规范化,过期时间0表示进程级永不过期而非持久存储。

PHP 用 apcu_store() 缓存数组数据时要注意什么
APCu 是 PHP 最轻量、最常用的用户级内存缓存扩展,但直接缓存含资源句柄(如 mysqli 对象、文件指针)或闭包的数组会静默失败,且不报错。缓存前必须确保数据可序列化。
-
apcu_store()只接受标量、数组、对象(需实现__serialize()或能被serialize()处理) - 缓存键名不能含空格或控制字符,建议用
md5($key)或str_replace([' ', '/'], '_', $key)规范化 - 过期时间设为
0表示永不过期,但 APCu 进程重启后即丢失——别把它当持久存储 - 示例:
$data = ['user_id' => 123, 'name' => 'Alice']; apcu_store('user_123', $data, 300); // 5 分钟后自动失效
Redis 缓存 JSON 数据时为什么 json_encode() 后还要加 JSON_UNESCAPED_UNICODE
中文字段在 Redis 中显示为 \u4f60\u597d 不是 bug,是默认 JSON 编码行为;但后续用 JavaScript 或其他语言读取时,若没正确解码 Unicode 转义,会导致乱码或解析失败。
- PHP 写入:用
json_encode($data, JSON_UNESCAPED_UNICODE)确保中文原样存储 - PHP 读取:
json_decode($redis->get('key'), true)即可还原数组,无需额外处理 - Redis 命令行查值时看到中文,说明编码正确;看到
\u...则说明写入时没加标志位 - 性能影响极小,但能避免跨语言协作时的隐性问题
文件缓存用 file_put_contents() 配合 flock() 的必要性
高并发下多个请求同时写同一个缓存文件,不加锁会导致内容截断、覆盖或 JSON 格式损坏——这不是概率问题,是必然发生的竞态。
- 必须用
fopen()+flock()+file_put_contents()组合,不能只靠file_put_contents($file, $content, LOCK_EX)(该 flag 仅对当前调用有效,不保证跨进程互斥) - 推荐写法:
$fp = fopen($cacheFile, 'c'); if (flock($fp, LOCK_EX)) { file_put_contents($cacheFile, json_encode($data), LOCK_EX); flock($fp, LOCK_UN); } fclose($fp); - 注意
'c'模式打开文件,避免清空后再写入的窗口期 - 缓存文件路径建议用
sys_get_temp_dir() . '/cache/',别放在 Web 可访问目录下
Memcached 存布尔值 true 为什么取出来变成 0
Memcached 协议本身不支持布尔类型,true 会被强制转成整数 1,而 false 转成空字符串 '';但 PHP 的 Memcached::get() 在遇到空字符串时会返回 false,导致真假混淆。
立即学习“PHP免费学习笔记(深入)”;
- 永远不要直接缓存
true/false,改用字符串'true'/'false'或整数1/0 - 更稳妥的做法是缓存数组:
['value' => $data, 'type' => 'bool'],读取后按 type 解析 - 如果用的是
memcache(非memcached)扩展,行为更不可靠,建议统一升级到memcached - 这个坑在调试时很难复现,往往上线后流量一上来才暴露











