@Cacheable的value必须含占位符(如_{id})才能动态生成键,否则所有调用共用同一缓存;ttl生效优先级为注解>配置文件>Redis驱动默认值;prefix不可含冒号,需与value配合拼出正确Redis键;参数类型不一致会导致缓存未命中且不执行方法体。

Cacheable 注解的 value 和 ttl 不是“填了就生效”,而是受 prefix 拼接规则、Redis 驱动配置、方法参数类型三重约束;乱设 value 可能导致缓存键重复或完全不命中。
Cacheable 的 value 参数必须带占位符才能动态生成键
value 不是自由字符串,它会被拼在 prefix 后面,且必须包含 {paramName} 或 _{params.paramName} 这类占位符,否则所有调用共用同一个缓存键。比如:
-
#[Cacheable(prefix: 'user', value: '_{id}')]→ 键为user:_123(正确) -
#[Cacheable(prefix: 'user', value: '_123')]→ 键恒为user:_123(错误,所有调用覆盖同一缓存) - 若方法签名是
public function info(int $uid, string $type),则value: '_{uid}_{type}'才能区分不同组合
ttl 设置优先级:注解 > cache.php 配置 > RedisDriver 默认值
ttl 单位是秒,但实际生效值取决于三层叠加逻辑:
- 注解中显式写了
ttl: 1800→ 直接采用 - 注解没写 ttl,但
config/autoload/cache.php中 default 驱动设置了'ttl' => 3600→ 采用该值 - 两者都没配,则 fallback 到
Hyperf\Cache\Driver\RedisDriver的默认 3600 秒 - 注意:model-cache 组件的
empty_model_ttl不影响 Cacheable,那是查不到数据时的兜底策略
prefix 带冒号会影响 Redis CLI 查看,但代码里不能加
很多人想在 Redis 里看到类似 user:123 的键,于是把 prefix 写成 'user:',这是错的:
- Cacheable 内部会自动拼接
prefix . value,若 prefix 已含:,value 再带_123就变成user:_123,不是预期的user:123 - 正确做法是
prefix: 'user'+value: ':{id}'→ 拼出user:123 - Redis CLI 中
KEYS user:*能匹配,但生产环境禁用 KEYS,应改用 SCAN
缓存未命中却没走方法体?检查参数类型与反射是否一致
常见现象:传了 $id = '123'(字符串),但方法定义是 int $id,结果缓存键生成为 user:_123,而实际执行时因类型转换失败,AOP 切面可能跳过缓存逻辑直接抛异常。
- 确保方法参数类型声明与实际传入值严格一致,尤其注意 int/float/string 边界
- 开启
Hyperf\Di\Aop\ProxyManager的 debug 日志,观察CacheableAspect是否触发 - 若用数组参数如
array $params,value 必须写成_{params.id},不能写_{id}
最易被忽略的是 value 占位符和参数名的大小写及嵌套层级——_{params.userId} 和 _{params.userid} 是两个键,且一旦写错,缓存就彻底失效,但不会报错,只能靠日志或 Redis 监控发现。


















