Files
EasyGoAdmin_GoFrame_EleVue/document/wiki/15_缓存键与失效策略.txt
T
2026-10-20 11:37:25 +08:00

107 lines
7.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
================================================================================
EasyGoAdmin 后端开发者文档 · 15 缓存键与失效策略
================================================================================
缓存实现:utility/cache 统一门面(Redis 优先,失败/运行期出错自动降级进程
内存 gcache,UsingMemory() 可查)。Redis 键统一前缀 easygoadmin:(consts/
cache_key.go)。降级影响:多实例不共享(限流计数、任务锁、在线用户、黑名单、
验证码、字典全部退化单机语义)。
--------------------------------------------------------------------------------
1. 缓存分层图
--------------------------------------------------------------------------------
请求 ──▶ ① 进程内缓存(sync.Map,无 Redis 交互,重启即清)
dictTextCache(300s) · reqFieldCache/textPlanCache(反射计划,永不过期)
maskReCache(正则,永不过期)
──▶ ② Redis(跨实例共享,TTL 自动回收)
黑名单/在线/验证码/字典/租户摘要/身份/限流/任务锁
──▶ ③ 数据库(唯一真相,dao.Ctx 全量过滤条件)
设计原则:② ③ 之间的一切缓存都必须有明确的失效点或短 TTL 兜底;
① 仅缓存“计算计划/只读文本”,不允许缓存业务状态。
--------------------------------------------------------------------------------
2. Redis 键全集(键模式 / TTL / 写入方 / 读取方 / 失效策略)
--------------------------------------------------------------------------------
键模式 TTL 写入 读取
------------------------------------ -------- ------------ --------------
easygoadmin:token:blacklist:{jti} 剩余有效期 Logout/Refresh JWT 中间件
+0(+60) 轮换/RemoveToken Exists 判定
ForceLogout
easygoadmin:online:jti:set (zset) 成员随info MarkOnline OnlineUser.Page
(score=过期 ts)MarkOffline (ZRangeByScore≥now)
easygoadmin:online:info:{jti} access剩余 MarkOnline OnlineUser.Page/
+60s MarkOffline Detail/ForceLogout
easygoadmin:captcha:{uuid} 300s Captcha 生成 Login/Verify(一次性)
easygoadmin:dict:item:{code} 3600s dict.setCache/ dict_item 快捷接口/
(Refresh RefreshCache AliasList 等
Cache 主动刷)
easygoadmin:tenant:info:{id} 60s Tenant中间件/ Tenant 中间件/
(自然过期) Login 路径 Login
easygoadmin:user:identity:{uid} 300s JWT 中间件 JWT 中间件
(回源Loader) (LoadIdentity 结果 JSON:
Roles/Perms/DataScope/DeptId;
旧缓存缺新字段时读侧回退安全值)
easygoadmin:user:perms:{uid} —(约定键,当前主路径用 identity 合并键,
保留扩展;变更时一并清理)
easygoadmin:user:roles:{uid} —(同上)
ratelimit:{ip}:{path}:{窗口起点} window+5s RateLimit incr RateLimit
job:lock:{jobId} 300s 兜底 jobTryLock(NX) jobTryLock
(执行完即 Del)
--------------------------------------------------------------------------------
3. 主动失效点清单(代码级)
--------------------------------------------------------------------------------
身份缓存 user:identity:{uid} 删除时机:
* role.SavePermission 保存角色权限 → clearRoleIdentityCache(roleId)
→ 查该角色全部 user → 逐个 Del
* role.Update 修改角色(含 data_scope 数据范围变更)→ AfterUpdate
钩子 roleClearCache → 同上链路逐个 Del
* user.AssignRoles 分配/调整角色 → clearIdentityCache(userId)
(user.Update / user.Add 均经 AssignRoles——改部门 dept_id 亦在此
路径清缓存,数据权限部门维度变更即时生效)
* user 修改密码 / 禁用等(部分路径主动清;其余靠 300s 过期兜底)
* 版本兼容:Identity 新增字段(DataScope/DeptId)反序列化缺省为 0,
读侧 GetDataScope 回退"全部"——升级无需强清存量缓存
租户摘要 tenant:info:{id} 删除时机:
* tenant 状态/过期时间变更(tenant 模块 AfterUpdate clearCache 钩子)
字典 Redis 缓存 dict:item:{code}:
* dict.RefreshCache 主动全量/单编码重建;dict_item 变更不主动清
(最长 1 小时延迟——关键场景调刷新接口)
黑名单:不主动删,靠 TTL=令牌剩余有效期自然过期(过期即令牌本身已失效)。
任务锁 job:lock:{id}:执行结束 defer Del;崩溃场景靠 300s TTL 兜底。
验证码:Verify 命中即删(一次性)。
--------------------------------------------------------------------------------
4. 进程内缓存明细
--------------------------------------------------------------------------------
dictTextCache(base.go)key={code}:{value} → 显示名,TTL 300s。
读多写少的 {field}Text 填充热路径。修改字典文案最迟 5 分钟生效;
RefreshCache 不清此层(各实例自然过期)。
reqFieldCache / textPlanCache / childrenIdxCache(module_spec.go)
反射索引与填充计划,按 reflect.Type 缓存,进程生命周期——只缓存“结构计划”
不缓存数据,类型不变即安全。
maskReCache(middleware/util.go)脱敏正则,按字段名缓存。
--------------------------------------------------------------------------------
5. TTL 设计原则(新增缓存时遵循)
--------------------------------------------------------------------------------
1) 状态判定类(黑名单/租户状态):TTL ≤ 业务有效期,且必须有主动失效点;
宁可短 TTL 多回源,不可长 TTL 陈旧放行。
2) 展示文本类(字典/归属地):TTL 300s~3600s + 刷新接口,接受分钟级延迟。
3) 高频读聚合类(identity):合并为单键 JSON(一次回源装多个集合),
TTL 300s,变更路径主动 Del。
4) 计数/锁类:键内嵌窗口起点或场景唯一 id,TTL 只做回收不参与语义
(限流窗口、执行锁均如此)。
5) 任何经 cache.Set 的值必须可 JSON 序列化为字符串;读侧 Unmarshal 失败
视为未命中回源。
--------------------------------------------------------------------------------
6. 排障
--------------------------------------------------------------------------------
键不存在/值陈旧:先查是否内存降级(redis-cli KEYS 'easygoadmin:*' 对比);
权限不生效:DEL easygoadmin:user:identity:{uid};
租户被禁仍可访问:等 60s 或 DEL easygoadmin:tenant:info:{id};
多实例行为不一致:确认 Redis 可用(/api/cache/info mode 应为 redis)。