5.8 KiB
5.8 KiB
4.8 缓存架构设计
:::tip 概述 项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(Cache 门面,默认 Redis),大幅减少数据库查询;数据变更时由 Observer 自动失效对应缓存,保证一致性。 :::
两级缓存架构
┌─────────────────────────────────────────────────────────┐
│ 第一级:请求级缓存(static 变量) │
│ │
│ 生命周期:单次 HTTP 请求 │
│ 存储位置:PHP 内存(static $cache) │
│ 速度:极快(纳秒级) │
│ │
│ 同一请求内多次查询同一数据,只查一次库或缓存 │
└──────────────────────────┬──────────────────────────────┘
│ 未命中
▼
┌─────────────────────────────────────────────────────────┐
│ 第二级:持久缓存(cache() 门面 / Redis) │
│ │
│ 生命周期:跨请求复用 │
│ 存储位置:Redis(CACHE_STORE=redis,必需组件) │
│ 速度:快(毫秒级) │
│ 有效期:1 小时(3600 秒) │
│ │
│ 跨请求复用,减少数据库压力 │
└──────────────────────────┬──────────────────────────────┘
│ 未命中
▼
┌─────────────────────────────────────────────────────────┐
│ 数据库查询 │
│ │
│ 查询后同时写入两级缓存 │
└─────────────────────────────────────────────────────────┘
使用两级缓存的服务
| 服务 | 缓存键格式 | 说明 |
|---|---|---|
DictCacheService |
dict_{code}(前缀 dict_) |
字典项映射(CACHE_PREFIX = 'dict_',TTL 见 CACHE_TTL) |
MenuService 等 |
权限/菜单缓存 | 角色权限列表(配合 Observer 失效) |
缓存一致性:Observer 自动失效
数据变更时由 Eloquent Observer 精确失效相关缓存(注册于 AppServiceProvider):
| Observer | 监听模型 | 触发动作 |
|---|---|---|
DictItemObserver |
字典项 | 清除所属字典缓存(dict_{code}) |
MenuObserver |
菜单 | 清除菜单/权限相关缓存 |
RoleMenuObserver |
角色-菜单关系 | 清除角色权限缓存 |
字典项变更 → DictItemObserver → DictCacheService::clearCache(code) → 下次读取回源重建
菜单变更 → MenuObserver → 权限缓存失效 → 前端刷新菜单后生效
:::tip 设计要点
缓存写入发生在"读取回源"时,失效只做 forget 不做主动重建——删除缓存比更新缓存更安全,避免并发下旧数据回写。
:::
缓存驱动配置
.env 配置:
# Redis 缓存(项目默认,必需)
CACHE_STORE=redis
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null # 设置了 requirepass 时必须同步
:::warning 不要改回 database/file 驱动
CACHE_STORE=database:数据库脚本不含 Laravelcache表,会直接报表不存在;file驱动:多进程/多服务器环境下无法共享,且本项目 JWT 会话、权限缓存均依赖 Redis;- 会话 / 缓存 / 队列三者统一使用 Redis(
SESSION_DRIVER/CACHE_STORE/QUEUE_CONNECTION)。 :::
缓存清除
// 清除指定字典缓存(Observer 已自动调用,此处为手动兜底)
DictCacheService::clearCache('gender');
// 清除所有字典缓存
DictCacheService::clearAllCache();
对应接口与命令:
GET /api/dict/refreshCache 刷新字典缓存(需认证)
php artisan dict:clear-cache 命令行清除字典缓存
php artisan config:clear 清除配置缓存(修改 .env 后)
php artisan cache:clear 清除全部应用缓存
Redis 使用全景
| 用途 | 使用方 | 说明 |
|---|---|---|
| JWT 双令牌会话 | JwtService |
refresh_token 存 Redis(支持踢下线、改密全端失效、一次性消费) |
| 字典缓存 | DictCacheService |
两级缓存第二级 |
| 权限/菜单缓存 | Authenticate 中间件 + Observer |
角色权限列表 |
| 验证码 | CaptchaService |
图形验证码存取 + IP 限流 |
| 会话/队列 | Laravel 驱动 | SESSION_DRIVER / QUEUE_CONNECTION |
连接验证:
php artisan tinker --execute="try { \Illuminate\Support\Facades\Redis::setex('test:key', 10, 'ok'); echo 'OK: '.\Illuminate\Support\Facades\Redis::get('test:key'); } catch (\Throwable \$e) { echo \$e->getMessage(); }"
# 输出 OK: ok 即连接正常