Yii框架不支持Memcached集群模式,其多服务器配置仅为客户端轮询/权重分发,各节点独立无故障转移、无槽管理、不共享状态,非真正集群。

Yii 框架不支持 Memcached 集群模式——它底层调用的是 PHP 的 Memcached 类,但仅支持单实例或一致性哈希多服务器(非 Redis 那种自动分片集群),所谓“Memcached 集群”在 Yii 中实际是伪集群,靠客户端轮询/权重分发,没有故障转移、无槽管理、不共享状态。
Yii 中配置 Memcached 多服务器 ≠ 集群
很多人看到 servers 写成数组就以为启用了集群,其实只是客户端负载均衡。Yii 的 yii\caching\MemCache(注意是 MemCache,不是 Memcached)只做连接池式分发,各节点完全独立:
- 写入时按 key 哈希选一个 server,不跨节点同步
- 某个 server 宕机,该 server 上所有缓存立即不可读,且不会自动 failover 到其他节点
- 没有节点发现机制,增删节点需重启应用或手动刷新连接
- 不支持
getMulti跨节点批量获取(PHPMemcached::getMulti()本身也不保证跨节点)
如果你真需要集群能力(自动重试、节点剔除、请求重路由),得换 Redis 或自己封装代理层(如 Twemproxy / Mcrouter),Yii 原生不提供。
Memcached 多服务器配置必须用数组嵌套结构
servers 看似简单,但错一格就静默失效——Yii 不报错,set() 返回 true,get() 却永远 null:
- ✅ 正确写法:
'servers' => [['host' => '127.0.0.1', 'port' => 11211], ['host' => '192.168.1.10', 'port' => 11211]] - ❌ 错误写法:
'servers' => ['127.0.0.1:11211', '192.168.1.10:11211'](字符串数组,被忽略) - ❌ 错误写法:
'servers' => ['host' => '127.0.0.1', 'port' => 11211](单层数组,key 冲突覆盖) - 可选加
'weight'控制流量比例,但不解决高可用问题
测试是否生效:在控制器里执行 Yii::$app->cache->set('test_' . time(), 'ok', 5),然后立刻 get();再停掉其中一个 server,观察是否部分 key 开始 miss —— 这才是真实行为。
和原生 Memcached 扩展协作时 key 不兼容
Yii 的 MemCache 默认对 key 做 md5() + keyPrefix,value 默认 serialize(),而原生 Memcached::get('mykey') 拿不到 Yii 存的值:
- 关闭自动处理:
'keyPrefix' => '', 'hashKey' => false, 'serializer' => null - 但这样会丧失 Yii 缓存组件的统一前缀隔离能力,多个应用共用同一 Memcached 实例时极易 key 冲突
- 更安全的做法是:约定所有非 Yii 端也加相同前缀,并用
unserialize()解 value - 如果要用
increment()/decrement(),必须通过$cache->getMemCache()拿到原生实例,且确保上述序列化配置一致
别把 Memcached 当 Redis 用
有人试图用 Memcached 存 session、计数器、分布式锁,结果频繁失效——这不是配置问题,是选型错位:
- Memcached 没有持久化,内存满时 LRU 清理不可控,
set(..., 3600)不保证真活 1 小时 - 没有原子计数(
increment是有的,但不支持初始值设置和边界检查) - 没有发布订阅、没有 list/set/zset 等数据结构,锁实现只能靠
add()+ TTL,竞态窗口比 Redis 的SETNX大得多 - Session 场景下,若没设
keyPrefix,多个 Yii 应用共用同一 Memcached 会导致PHPSESSID_*相互覆盖,用户随机掉登录
真正需要集群、强一致、带原子操作的场景,直接切 Redis;Memcached 只适合做纯临时、可丢失、高吞吐的热点数据缓存,它的“分布式”本质是水平伸缩,不是容错集群。


















