thinkphp原生不支持真正的分布式缓存,其memcached/redis驱动仅支持多节点配置但无故障转移与自动降级;redis集群需手动初始化rediscluster实例;推荐apcu+redis两级缓存并自行封装降级逻辑。

ThinkPHP 原生不支持真正的分布式缓存,所谓“分布式”在官方驱动里只是多节点列表配置,实际仍由单个客户端(如 Memcached 或 Redis 扩展)做一致性哈希或轮询分发,框架层无路由、无故障转移、无自动降级。
Memcached 多节点配置 ≠ 分布式缓存能力
ThinkPHP 的 memcached 驱动允许配多个 server,但底层调用的是 PHP 的 Memcached::addServer(),它只负责把 key 映射到某个节点,不处理节点宕机后的重试或 fallback。一旦某个 127.0.0.1:11211 不可用,get() 可能直接返回 false 而非穿透查下一层。
- 必须手动检查扩展是否启用:
extension=memcached.so(Linux)或php_memcached.dll(Windows) - 配置中
servers是数组,每个元素必须是['host' => 'x.x.x.x', 'port' => 11211]格式,不能写成['x.x.x.x:11211'] - 不支持密码认证(
Memcached协议本身无 auth),若需鉴权,得换memcached代理或改用 Redis - key 过期后不会主动清理内存,仅在 get 时判断 —— 所以高写低读场景下,
apcu_cache_info('memory_usage')可能显示内存持续上涨
Redis 驱动默认是单实例,集群模式要绕过框架
ThinkPHP 的 redis 驱动(\think\Cache\Driver\Redis)只接受单 host + port,即使你配了 ['host' => 'redis-cluster'],它也不会自动识别 Redis Cluster 协议。想用集群,必须跳过 Cache::store('redis'),直接 new 一个 RedisCluster 实例。
- 先确认 PHP 安装了
redis扩展且版本 ≥ 5.3(支持RedisCluster类) - 连接字符串不是单个地址,而是节点数组:
['10.0.1.100:7000', '10.0.1.101:7000', '10.0.1.102:7000'] - 不能复用
stores.redis配置项,得单独初始化:$cluster = new \RedisCluster(null, $nodes); - 写入时若 key 涉及多个 slot(比如用
{user}:123和{user}:456),RedisCluster自动路由;但没做重试,节点临时失联会抛RedisClusterException
真正可用的分布式缓存方案:APCu + Redis 两级降级
这不是“分布”在多台机器,而是分布于「进程内」(APCu)和「网络侧」(Redis)两层,解决 Redis 故障时的雪崩问题。ThinkPHP 没内置该逻辑,必须自己封装函数。
- 键名必须隔离:
apcu_fetch('tp_apcu:user:123')和redis get 'user:123'不能共用同一 key,否则 APCu 未过期时 Redis 更新了,读出来就是旧值 - 写入顺序不能错:先
apcu_store(),再redis->set();反过来会导致短暂不一致(APCu 还没写完,Redis 已更新,新请求从 APCu 读到 null) - APCu TTL 不可靠:
apcu_store($key, $val, 60)的 60 秒是软限制,实际回收依赖共享内存压力,不能当精确过期用 - 不要在 CLI/Swoole 长生命周期里依赖 APCu:子进程 fork 后不共享 APCu 数据,
apcu_fetch()在 worker 间是隔离的
最易被忽略的一点:所有自定义缓存逻辑都绕过了 ThinkPHP 的 Cache::tag() 和事件钩子,比如 CacheWrite 事件不会触发。如果你依赖 tag 清除或监控埋点,这部分得自己补全。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











