2.0 KiB
Redis Cache — 实现细节
主流程见 SKILL.md,本文档为连接、Cache-Aside、CachedRepository、TTL、分布式锁、穿透/击穿防护的完整代码。
连接配置
// config/autoload/redis.php
return [
'default' => ['host' => env('REDIS_HOST'), 'auth' => env('REDIS_AUTH'), 'port' => (int) env('REDIS_PORT', 6379), 'db' => (int) env('REDIS_DB', 0), 'pool' => ['min_connections' => 5, 'max_connections' => 30, ...]],
'cache' => ['db' => (int) env('REDIS_CACHE_DB', 1), 'pool' => [...]] // 独立连接池
];
Cache-Aside 模式
CacheService:withCache($key, $ttl, $fetcher) — get 命中则返回,否则 fetcher() 后 setex,TTL 加 jitter 防 stampede。invalidate($keys)、invalidatePattern($pattern) 用 scan 分批 del。
CachedRepository 装饰器
实现 RepositoryInterface,包装 baseRepo。getById/getPageList 用 withCache,key 格式 {entity}:{id} 和 {entity}:list:{params_hash}。invalidateDetail/invalidateList/invalidateAll。DI 注册时用 closure 返回 new CachedRepository(baseRepo, cacheService, 'order', detailTtl, listTtl)。Service 写操作后判断 $repository instanceof CachedRepository 则 invalidateAll。
TTL 规范
Profile 30m、列表 5m、配置 1h、JWT 2h、Session 24h、限流与窗口对齐、验证码 5m、锁 任务时长+30s。
Key 命名
<namespace>:<entity>:<id>:<field>,如 user:profile:123、orders:list:page:1、rate:limit:ip:api、session:user:456、lock:order:789、ws:connection:fd:100。
分布式锁
RedisLockService:withLock($lockKey, $ttlMs, $fn)。SET NX PX。释放用 Lua 脚本原子校验 value 后 DEL。
缓存穿透/击穿
穿透:不存在 key 缓存 NULL_PLACEHOLDER(TTL 30s)。击穿:热点 key 用 withLock 互斥,double-check 后 fetcher 再 setex。
装饰器 vs 直接缓存 决策
读写比 > 10:1 → CachedRepository。读写比 < 10:1 → Service 内 CacheService。热点数据(排行榜)→ Redis 原生 ZSET/INCR。