Memcached 扩展未安装或配置错误是 PHP 调用失败的主因;需确认 php-memcached 已启用、igbinary 序列化兼容、键名安全哈希、过期时间设为≤2592000秒,并通过 getVersion() 等方式主动检测连接。

Memcached 扩展没装好,new Memcached() 直接报错
PHP 调用 Memcached 前必须确认扩展已启用。常见错误是只装了服务端 memcached(Linux 下 systemctl start memcached),却漏掉 PHP 的 memcached 扩展(非 memcache!两者不兼容)。运行 php -m | grep memcached,无输出就说明没装。Debian/Ubuntu 下执行:sudo apt install php-memcached,然后重启 Web 服务(如 sudo systemctl restart apache2 或 php-fpm)。Windows 用户需检查 php.ini 是否启用了 extension=php_memcached.dll,且 DLL 文件在 ext/ 目录下。
$mc->set() 返回 false,但没报错?查连接和序列化
Memcached 默认使用 igbinary 序列化(比原生 serialize 快且紧凑),但若未安装 igbinary 扩展,set() 可能静默失败。先运行 php -i | grep igbinary 确认;若无,要么装 igbinary,要么显式禁用:$mc->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP)。另外,set() 失败大概率是连接问题:检查 $mc->addServer('127.0.0.1', 11211) 后是否调用 $mc->isConnected()(注意:该方法仅 PHP 8.0+ 支持),更稳妥的是执行一次 $mc->getVersion() 并捕获返回值是否为数组。
缓存键设计不当,导致击穿或冲突
直接用用户 ID 当键名(如 'user_123')看似简单,但实际容易出问题:
- 不同环境(测试/生产)共用同一 Memcached 实例时,键名冲突会导致脏数据
- 未加前缀的键无法批量清理(Memcached 不支持通配符删除)
- 动态参数拼接不加转义,如
'post_'.$id.'_'.$lang,当$id含空格或控制字符时写入失败
'prod:post:'.$id.':'.$lang),或用 sprintf('v1:post:%d:%s', $id, urlencode($lang)) 保证安全。关键数据建议加版本号前缀(如 v2:user_profile:123),升级结构时只需改前缀即可自然失效旧缓存。
过期时间设成 0 就永不过期?其实有陷阱
$mc->set('key', 'val', 0) 看似“永久”,但 Memcached 内部会将 0 解释为「服务器当前时间 + 0 秒」,即立即过期。真正想长期缓存,得设一个大值,比如 30*24*3600(30 天)。更麻烦的是,Memcached 对超过 30 天的过期时间会自动转为 UNIX 时间戳处理——如果传入 2592001(30 天+1秒),它会当成绝对时间戳(1970 年起算),结果变成已过期。所以安全上限是 2592000(30 天整)。另外,别依赖过期机制做业务逻辑(如“缓存到期即触发更新”),因为 Memcached 不保证准时删除,只是惰性淘汰+LRU 清理。
立即学习“PHP免费学习笔记(深入)”;
真正卡住性能的往往不是“要不要用”,而是键怎么命、连怎么保、错怎么判。Memcached 很快,但一连串 get 后跟 set 的条件判断写法,很容易掩盖连接抖动或序列化失败——这些细节不打日志,线上就只能靠猜。










