缓存高频但更新不敏感的动态内容(如头像、未读数)最有效;强一致性数据(如订单状态)不宜缓存;需合理选型方法、设计键名、防击穿雪崩、谨慎用模板缓存、优化Redis配置。

缓存什么内容才真正有效?
高频动态内容 ≠ 所有动态内容。比如用户头像、未读消息数、实时排行榜,这些变化频繁但更新不敏感——缓存 5–30 秒就足够;而订单状态、支付结果这类强一致性要求的,缓存反而会出错。Cache::tag() 和 Cache::remember() 都能用,但选错场景就白忙活。
- 用户侧接口返回的聚合数据(如首页卡片组)适合用
Cache::remember() 包裹查询逻辑
- 同一页面多个模块共用的数据(如导航菜单、权限列表)建议打上统一
tag,便于批量清除
- 缓存键必须含业务维度标识,比如
"user<em>profile</em>{$uid}",不能只写 "profile",否则全站用户共享同一份缓存
怎么避免缓存击穿和雪崩?
ThinkPHP 默认用文件或 Redis 做驱动,但没开箱即用的熔断或互斥锁机制。高并发下大量请求同时发现缓存失效,直接打穿到数据库,就是击穿;如果一批缓存 key 设了相同过期时间,集体失效引发流量洪峰,就是雪崩。
- 给过期时间加随机偏移:比如基础 60 秒,再加
rand(0, 30),避免整点失效
- 查无缓存时,用
Cache::lock() 加分布式锁(需 Redis 支持),只放行一个请求回源,其余等待重试
- 设置「空值缓存」:查不到数据也写入
null + 短期 TTL(如 2 秒),防恶意 ID 刷库
片段缓存怎么嵌进模板里不翻车?
ThinkPHP 的 {:cache()} 模板标签看着方便,但实际容易踩坑:它只缓存输出 HTML 字符串,不感知 PHP 变量变化;且默认不支持嵌套、不兼容某些 layout 结构。
- 不要在
{:cache()} 区块内写 <?php echo $user['name']; ?> 这类动态 PHP,改用 {$user.name} 模板语法,否则缓存后变量不更新
- 如果模板用了
{include file="xxx"},被 include 的文件不会被自动纳入缓存范围,得把整个区块包进去
- 开发环境务必关掉模板缓存(
'template_cache' => false),否则改了模板看不到效果,还以为是片段缓存没生效
Redis 驱动下哪些配置影响真实性能?
用 Redis 是为了快,但如果连接池、序列化、前缀配置不当,可能比文件缓存还慢。
-
host 和 port 必须直连 Redis 实例,别走中间代理(如 Twemproxy),多一层转发延迟明显
-
serialize 推荐用 igbinary(需扩展),比默认 php_serialize 小 30%+、快 2 倍;若没装扩展,至少关掉 json 序列化(它会强制转字符串,丢精度)
-
prefix 建议设为项目名缩写(如 "tp<em>shop</em>"),避免多项目混用 Redis 时 key 冲突,但别太长,key 越长 Redis 查找越慢
Cache::remember() 包裹查询逻辑 tag,便于批量清除 "user<em>profile</em>{$uid}",不能只写 "profile",否则全站用户共享同一份缓存 - 给过期时间加随机偏移:比如基础 60 秒,再加
rand(0, 30),避免整点失效 - 查无缓存时,用
Cache::lock()加分布式锁(需 Redis 支持),只放行一个请求回源,其余等待重试 - 设置「空值缓存」:查不到数据也写入
null+ 短期 TTL(如 2 秒),防恶意 ID 刷库
片段缓存怎么嵌进模板里不翻车?
ThinkPHP 的 {:cache()} 模板标签看着方便,但实际容易踩坑:它只缓存输出 HTML 字符串,不感知 PHP 变量变化;且默认不支持嵌套、不兼容某些 layout 结构。
- 不要在
{:cache()} 区块内写 <?php echo $user['name']; ?> 这类动态 PHP,改用 {$user.name} 模板语法,否则缓存后变量不更新
- 如果模板用了
{include file="xxx"},被 include 的文件不会被自动纳入缓存范围,得把整个区块包进去
- 开发环境务必关掉模板缓存(
'template_cache' => false),否则改了模板看不到效果,还以为是片段缓存没生效
Redis 驱动下哪些配置影响真实性能?
用 Redis 是为了快,但如果连接池、序列化、前缀配置不当,可能比文件缓存还慢。
-
host 和 port 必须直连 Redis 实例,别走中间代理(如 Twemproxy),多一层转发延迟明显
-
serialize 推荐用 igbinary(需扩展),比默认 php_serialize 小 30%+、快 2 倍;若没装扩展,至少关掉 json 序列化(它会强制转字符串,丢精度)
-
prefix 建议设为项目名缩写(如 "tp<em>shop</em>"),避免多项目混用 Redis 时 key 冲突,但别太长,key 越长 Redis 查找越慢
{:cache()} 区块内写 <?php echo $user['name']; ?> 这类动态 PHP,改用 {$user.name} 模板语法,否则缓存后变量不更新 {include file="xxx"},被 include 的文件不会被自动纳入缓存范围,得把整个区块包进去 'template_cache' => false),否则改了模板看不到效果,还以为是片段缓存没生效 -
host和port必须直连 Redis 实例,别走中间代理(如 Twemproxy),多一层转发延迟明显 -
serialize推荐用igbinary(需扩展),比默认php_serialize小 30%+、快 2 倍;若没装扩展,至少关掉json序列化(它会强制转字符串,丢精度) -
prefix建议设为项目名缩写(如"tp<em>shop</em>"),避免多项目混用 Redis 时 key 冲突,但别太长,key 越长 Redis 查找越慢
缓存不是加个 Cache::remember() 就完事,关键是判断「谁在读」「多久可 stale」「失效时谁扛压」——这三个问题没想清楚,缓存就只是给错误加了一层加速。



















