直接执行redis-cli -a pwd memory usage key,若返回值超100000(100kb)即需警惕,超1000000(1mb)可判定为生产级大key;注意thinkphp默认带prefix,查时需补全实际key名。

ThinkPHP 项目里 Redis 出现大 Key,不是框架的问题,而是业务写入没约束导致的——直接查 MEMORY USAGE 定位,别信“自动扫描”或“监控告警等它爆”。
怎么快速确认是不是大 Key 在拖慢 ThinkPHP 请求?
ThinkPHP 本身不感知 Redis Key 大小,但你能在日志或监控里看到两类典型现象:
- 接口响应时间突然从 20ms 涨到 800ms+,且集中在某个缓存读写操作(比如
Cache::get('user:profile:'.$uid)) - Redis
used_memory持续爬升,evicted_keys开始非零,但业务没批量写入动作
这时别猜,立刻连上 Redis 实例执行:
redis-cli -a yourpassword MEMORY USAGE user:profile:12345
返回值若 > 100000(约 100KB),就该警惕;> 1000000(1MB)基本可判定为生产级大 Key。注意:ThinkPHP 的 Cache 类默认用 prefix,实际 Key 名可能是 thinkphp:user:profile:12345,查的时候要带前缀。
ThinkPHP 场景下哪些写法最容易造出大 Key?
不是所有大 Key 都来自手动 set,ThinkPHP 的缓存封装和 ORM 行为会悄悄埋雷:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
Db::name('product')->select()+Cache::set('all_products', $list, 3600):一次缓存全表,列表超 5000 条就踩线 -
Cache::remember('user_orders:'.$uid, 7200, function() use ($uid) { return Db::name('order')->where('uid',$uid)->select(); }):用户订单多时,单个 Key 存几千条记录 - 用
Hash缓存用户完整资料:$redis->hMset('user:detail:'.$uid, $data),其中$data['avatar_url']是 Base64 图片字符串(动辄几百 KB) - 日志类缓存未分页:
Cache::set('oplog:'.$uid, $full_log_array),数组含时间戳、IP、参数 JSON 字符串
这些写法在本地测不出问题,一上生产、用户量上来,HGETALL 或 GET 就卡住主线程。
拆分方案必须匹配 ThinkPHP 的调用习惯
不能只改 Redis,还要让 ThinkPHP 代码不报错、不漏数据:
- 把
user:profile:12345拆成user:profile:basic:12345、user:profile:ext:12345,然后用Cache::get(['user:profile:basic:'.$uid, 'user:profile:ext:'.$uid])批量取(ThinkPHP 6.1+ 支持数组 Key) - 对列表类缓存,强制分页:
Cache::get('user_orders:'.$uid.':page_1'),用Cache::remember套一层,避免业务层改逻辑 - 图片/文件类字段,绝不进 Redis:改用
Cache::set('user:avatar_hash:'.$uid, md5($url), 86400),真实图片走 CDN 或对象存储 - 删大 Key 时禁用
DEL:改用SCAN+UNLINK脚本,ThinkPHP 可封装成Cache::safeDelete($key)方法
最关键一点:ThinkPHP 的 Cache 默认不支持 UNLINK,得自己扩展驱动或直接调 think\cache\driver\Redis 底层连接执行命令。
上线前必须堵死的三个漏洞
很多团队修复了当前大 Key,两周后又出现新的——因为没卡住源头:
- 在
app/common.php或中间件里加全局钩子,拦截所有Cache::set调用,对 value 长度做硬限制(如strlen(json_encode($value)) > 102400就抛异常) - Redis 配置里设
maxmemory-policy allkeys-lru不够,还得配notify-keyspace-events Ex,配合监控抓过期事件,反向定位谁在写长期不更新的大 Key - ThinkPHP 日志里搜
Cache::set出现频率最高的 10 个 Key pattern,人工 review 是否合理——比如cache:report:*这种通配,大概率是定时任务 dump 全量数据
大 Key 的本质不是技术问题,是缓存边界没定义清楚。ThinkPHP 让开发太快,反而容易跳过“这个数据到底该不该进 Redis”这一步。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










