签入版本
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 4.8 缓存架构设计
|
||||
|
||||
:::tip 概述
|
||||
项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(file/Redis),大幅减少数据库查询。
|
||||
项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(Cache 门面,默认 Redis),大幅减少数据库查询;数据变更时由 Observer 自动失效对应缓存,保证一致性。
|
||||
:::
|
||||
|
||||
## 两级缓存架构
|
||||
@@ -19,10 +19,10 @@
|
||||
│ 未命中
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 第二级:持久缓存(cache() 门面) │
|
||||
│ 第二级:持久缓存(cache() 门面 / Redis) │
|
||||
│ │
|
||||
│ 生命周期:跨请求复用 │
|
||||
│ 存储位置:file 或 Redis │
|
||||
│ 存储位置:Redis(CACHE_STORE=redis,必需组件) │
|
||||
│ 速度:快(毫秒级) │
|
||||
│ 有效期:1 小时(3600 秒) │
|
||||
│ │
|
||||
@@ -41,50 +41,79 @@
|
||||
|
||||
| 服务 | 缓存键格式 | 说明 |
|
||||
|------|-----------|------|
|
||||
| `DictService` | `dict_{code}` | 字典项映射 |
|
||||
| `DictService` | `dict_full_{code}` | 字典项完整数据 |
|
||||
| `ParamService` | `param_{code}` | 系统参数值 |
|
||||
| `DictCacheService` | `dict_{code}`(前缀 `dict_`) | 字典项映射(`CACHE_PREFIX = 'dict_'`,TTL 见 `CACHE_TTL`) |
|
||||
| `MenuService` 等 | 权限/菜单缓存 | 角色权限列表(配合 Observer 失效) |
|
||||
|
||||
## 缓存一致性:Observer 自动失效
|
||||
|
||||
数据变更时由 Eloquent Observer 精确失效相关缓存(注册于 `AppServiceProvider`):
|
||||
|
||||
| Observer | 监听模型 | 触发动作 |
|
||||
|----------|----------|----------|
|
||||
| `DictItemObserver` | 字典项 | 清除所属字典缓存(`dict_{code}`) |
|
||||
| `MenuObserver` | 菜单 | 清除菜单/权限相关缓存 |
|
||||
| `RoleMenuObserver` | 角色-菜单关系 | 清除角色权限缓存 |
|
||||
|
||||
```text
|
||||
字典项变更 → DictItemObserver → DictCacheService::clearCache(code) → 下次读取回源重建
|
||||
菜单变更 → MenuObserver → 权限缓存失效 → 前端刷新菜单后生效
|
||||
```
|
||||
|
||||
:::tip 设计要点
|
||||
缓存写入发生在"读取回源"时,失效只做 `forget` 不做主动重建——**删除缓存比更新缓存更安全**,避免并发下旧数据回写。
|
||||
:::
|
||||
|
||||
## 缓存驱动配置
|
||||
|
||||
`.env` 配置:
|
||||
|
||||
```ini
|
||||
; 文件缓存(默认)
|
||||
[CACHE]
|
||||
DRIVER = file
|
||||
|
||||
; Redis 缓存(推荐生产环境)
|
||||
[CACHE]
|
||||
DRIVER = redis
|
||||
REDIS_HOST = 127.0.0.1
|
||||
REDIS_PORT = 6379
|
||||
REDIS_PASSWORD =
|
||||
REDIS_DB = 0
|
||||
# Redis 缓存(项目默认,必需)
|
||||
CACHE_STORE=redis
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=null # 设置了 requirepass 时必须同步
|
||||
```
|
||||
|
||||
:::warning 生产环境建议使用 Redis
|
||||
文件缓存在多进程/多服务器环境下无法共享,生产环境建议配置 Redis 缓存驱动。使用 Redis 前需安装 `php redis` 扩展。
|
||||
:::warning 不要改回 database/file 驱动
|
||||
- `CACHE_STORE=database`:数据库脚本**不含** Laravel `cache` 表,会直接报表不存在;
|
||||
- `file` 驱动:多进程/多服务器环境下无法共享,且本项目 JWT 会话、权限缓存均依赖 Redis;
|
||||
- 会话 / 缓存 / 队列三者统一使用 Redis(`SESSION_DRIVER` / `CACHE_STORE` / `QUEUE_CONNECTION`)。
|
||||
:::
|
||||
|
||||
## 缓存清除
|
||||
|
||||
```php
|
||||
// 清除指定字典缓存
|
||||
DictService::clearCache('gender');
|
||||
// 清除指定字典缓存(Observer 已自动调用,此处为手动兜底)
|
||||
DictCacheService::clearCache('gender');
|
||||
|
||||
// 清除所有字典缓存
|
||||
DictService::clearAllCache();
|
||||
|
||||
// 清除指定参数缓存
|
||||
ParamService::clearCache('DEFAULT_PASSWORD');
|
||||
|
||||
// 清除所有参数缓存
|
||||
ParamService::clearAllCache();
|
||||
DictCacheService::clearAllCache();
|
||||
```
|
||||
|
||||
对应接口:
|
||||
对应接口与命令:
|
||||
|
||||
```text
|
||||
GET /api/dict/refreshCache 刷新字典缓存
|
||||
```
|
||||
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` |
|
||||
|
||||
连接验证:
|
||||
|
||||
```bash
|
||||
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 即连接正常
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user