签入版本
This commit is contained in:
@@ -1,90 +1,67 @@
|
||||
# 4.8 缓存架构设计
|
||||
# 4.9 缓存架构设计
|
||||
|
||||
:::tip 概述
|
||||
项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(file/Redis),大幅减少数据库查询。
|
||||
缓存层以 Redis 为主、进程内内存为降级:启动时探测 Redis,不可用自动切内存模式并告警,业务代码无感知。缓存键统一由 `consts` 函数生成,禁止裸字符串拼键。
|
||||
:::
|
||||
|
||||
## 两级缓存架构
|
||||
## 双模式结构
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 第一级:请求级缓存(static 变量) │
|
||||
│ │
|
||||
│ 生命周期:单次 HTTP 请求 │
|
||||
│ 存储位置:PHP 内存(static $cache) │
|
||||
│ 速度:极快(纳秒级) │
|
||||
│ │
|
||||
│ 同一请求内多次查询同一数据,只查一次库或缓存 │
|
||||
└──────────────────────────┬──────────────────────────────┘
|
||||
│ 未命中
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 第二级:持久缓存(cache() 门面) │
|
||||
│ │
|
||||
│ 生命周期:跨请求复用 │
|
||||
│ 存储位置:file 或 Redis │
|
||||
│ 速度:快(毫秒级) │
|
||||
│ 有效期:1 小时(3600 秒) │
|
||||
│ │
|
||||
│ 跨请求复用,减少数据库压力 │
|
||||
└──────────────────────────┬──────────────────────────────┘
|
||||
│ 未命中
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 数据库查询 │
|
||||
│ │
|
||||
│ 查询后同时写入两级缓存 │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
utility/cache 对外 API(Set/Get/Del/Exists/SetNX/Incr/ZSet...)
|
||||
│
|
||||
├── Redis 模式(默认):go-redis/v9 连接池
|
||||
│
|
||||
└── 内存降级模式(探测失败自动切换,InMemory() 可查当前模式)
|
||||
```
|
||||
|
||||
## 使用两级缓存的服务
|
||||
`cache.Init(ctx)` 在启动序列早期执行;`cache.Close()` 在优雅关闭末段调用。
|
||||
|
||||
| 服务 | 缓存键格式 | 说明 |
|
||||
|------|-----------|------|
|
||||
| `DictService` | `dict_{code}` | 字典项映射 |
|
||||
| `DictService` | `dict_full_{code}` | 字典项完整数据 |
|
||||
| `ParamService` | `param_{code}` | 系统参数值 |
|
||||
## 对外 API
|
||||
|
||||
## 缓存驱动配置
|
||||
| API | 说明 |
|
||||
|---|---|
|
||||
| Set / Get / Del / Exists | 基础读写(带 TTL) |
|
||||
| SetNX | 不存在才写入(任务锁、并发防护) |
|
||||
| Incr | 计数器(限流窗口) |
|
||||
| ZAdd / ZRem / ZRangeByScore / ZCard / ZRemRangeByScore | 有序集合(在线令牌按过期时间排序) |
|
||||
| PING / Info / DBSize | Redis 原始操作(缓存监控页用) |
|
||||
|
||||
`.env` 配置:
|
||||
## 缓存键规范
|
||||
|
||||
```ini
|
||||
; 文件缓存(默认)
|
||||
[CACHE]
|
||||
DRIVER = file
|
||||
键名唯一定义在 `internal/consts/cache_key.go`,统一前缀 `easygoadmin:`:
|
||||
|
||||
; Redis 缓存(推荐生产环境)
|
||||
[CACHE]
|
||||
DRIVER = redis
|
||||
REDIS_HOST = 127.0.0.1
|
||||
REDIS_PORT = 6379
|
||||
REDIS_PASSWORD =
|
||||
REDIS_DB = 0
|
||||
```
|
||||
| 键函数 | 用途 |
|
||||
|---|---|
|
||||
| CacheKeyTokenBlacklist(jti) | Token 黑名单(TTL = token 剩余有效期) |
|
||||
| CacheKeyOnlineJtiSet / CacheKeyOnlineInfo | 在线令牌集合与明细 |
|
||||
| CacheKeyCaptcha(uuid) | 图形验证码答案 |
|
||||
| CacheKeyDictItem(code) | 字典项集合(变更时删除对应键) |
|
||||
|
||||
:::warning 生产环境建议使用 Redis
|
||||
文件缓存在多进程/多服务器环境下无法共享,生产环境建议配置 Redis 缓存驱动。使用 Redis 前需安装 `php redis` 扩展。
|
||||
:::
|
||||
业务代码**禁止**裸字符串拼键——改键名时遗漏引用会脏数据滞留。
|
||||
|
||||
## 缓存清除
|
||||
## 缓存了什么
|
||||
|
||||
```php
|
||||
// 清除指定字典缓存
|
||||
DictService::clearCache('gender');
|
||||
| 场景 | 键模式 | 失效策略 |
|
||||
|---|---|---|
|
||||
| 验证码 | captcha:{uuid} | TTL 到期(captcha.expire) |
|
||||
| 字典项 | dict:{code} | 字典变更时主动 Del |
|
||||
| Token 黑名单 | token:blacklist:{jti} | TTL 自然过期 |
|
||||
| 在线用户 | online:jti:set + online:info:{jti} | 登出撤销 / 过期清理 |
|
||||
| 身份/租户 | —— | auth 模块按需缓存 |
|
||||
| 限流窗口 | 计数键 | 窗口过期 |
|
||||
|
||||
// 清除所有字典缓存
|
||||
DictService::clearAllCache();
|
||||
## 降级语义
|
||||
|
||||
// 清除指定参数缓存
|
||||
ParamService::clearCache('DEFAULT_PASSWORD');
|
||||
Redis 不可用时:
|
||||
|
||||
// 清除所有参数缓存
|
||||
ParamService::clearAllCache();
|
||||
```
|
||||
- Init 探测失败 → 切内存模式 → 打 Warn 告警(含后果说明)
|
||||
- 内存模式单进程有效:重启即空、多实例不共享
|
||||
- 依赖缓存正确性的功能(黑名单、在线列表)在内存降级下**退化为单机语义**——生产环境应保证 Redis 可用
|
||||
|
||||
对应接口:
|
||||
## 监控
|
||||
|
||||
```text
|
||||
GET /api/dict/refreshCache 刷新字典缓存
|
||||
```
|
||||
缓存监控页经 PING/Info/DBSize 展示 Redis 运行状态与键空间分布(见 [6.19 缓存监控](/zh/modules/cache-monitor.html))。内存降级时监控页反映内存实现的对应视图。
|
||||
|
||||
## 下一步
|
||||
|
||||
→ [4.10 数据库设计](/zh/architecture/database-design.html)
|
||||
|
||||
Reference in New Issue
Block a user