You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Memcached运行时新增主机致缓存全丢失:如何修复及排查?

我之前在维护PHP项目的时候正好碰到过一模一样的问题——运行时给Memcached集群加新节点,结果整个缓存好像全丢了,折腾了好一阵才搞明白根源。下面给你详细说排查思路和修复方案:

问题核心根源

PHP的Memcached扩展默认使用普通取模哈希(MODULA分布策略),这种策略的特点是:哈希槽的数量等于服务器节点数。当你运行时新增服务器,节点数变化,所有key的哈希映射会全部重新计算——原来存在旧节点的key,现在会被路由到新的节点组合里,导致旧节点的缓存找不到,看起来就像全部丢失了(但实际上旧节点的缓存数据还在,只是路由规则变了)。

排查步骤
  • 确认缓存是否真的丢失:调用$memcached->getStats()方法查看所有节点的缓存统计,重点看item_count字段。如果旧节点的item_count还是正常数值,说明只是路由问题;如果数值清零,那可能是误触发了flush()或者节点重启了。
  • 检查服务器添加的代码逻辑:区分是用addServer()(追加节点)还是setServers()(替换整个节点列表),两种方式都会改变节点数量,但setServers()更容易引发问题——如果不小心覆盖了旧节点列表,直接就会导致旧节点的缓存无法访问。
  • 验证哈希映射变化:写个简单的测试脚本,对比新增节点前后同一个key的路由节点:
$memcached = new Memcached();
// 先添加旧节点
$memcached->addServer('old-node-ip', 11211);
// 查看key对应的节点
echo "新增前test-key的路由节点:" . print_r($memcached->getServerByKey('test-key'), true) . PHP_EOL;
// 新增新节点
$memcached->addServer('new-node-ip', 11211);
// 再次查看key对应的节点
echo "新增后test-key的路由节点:" . print_r($memcached->getServerByKey('test-key'), true) . PHP_EOL;

如果前后输出的节点完全不同,就坐实了是哈希路由变化导致的“假丢失”。

  • 检查Memcached扩展的分布策略:执行echo ini_get('memcached.distribution');,默认输出是modula,也就是普通取模;如果是consistent,那可能是其他配置问题。
修复方案
  1. 启用一致性哈希(Ketama算法)
    这是最核心的修复手段,一致性哈希只会在新增/移除节点时影响部分key的路由,不会导致全量缓存无法访问。初始化Memcached实例时添加以下配置:
$memcached = new Memcached();
// 开启一致性哈希分布
$memcached->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
// 开启标准Ketama兼容模式,避免和其他语言客户端(比如Java、Python)的路由不一致
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
// 批量添加节点(支持权重设置,第三个参数是权重值)
$memcached->addServers([
    ['old-node-ip', 11211, 100],
    ['new-node-ip', 11211, 50]
]);
  1. 避免运行时动态修改节点列表
    尽量在应用启动阶段就加载完整的Memcached节点配置(比如从配置文件、配置中心读取),如果需要扩容,最好是重启应用加载新配置,而不是运行时动态添加节点——即使开启了一致性哈希,动态添加也会有部分缓存失效,重启加载能让路由规则提前生效,避免业务波动。
  2. 恢复已丢失的缓存(如果已发生)
    如果已经因为路由变化导致缓存不可用:
    • 如果业务允许,可以等待缓存自动重建(比如用户请求触发重新生成缓存);
    • 如果需要快速恢复,可以导出旧节点的缓存数据,然后按照新的一致性哈希规则重新写入集群;
    • 排查代码中是否误调用了$memcached->flush(),如果是,只能依赖缓存重建或者备份恢复。
额外注意事项
  • 确保集群中所有客户端(包括其他语言的客户端)都使用相同的一致性哈希算法,避免出现key路由不一致的问题;
  • 节点权重设置要合理,权重越高的节点会承担更多的key路由,避免节点负载不均。

内容的提问来源于stack exchange,提问作者Ehtasham Nasir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:40:24