7.7 KiB
生产环境移除 Redis 依赖设计文档
1. 背景
当前项目基于若依前后端分离架构,Redis 在系统中承担了多类运行时状态能力,包括:
- JWT 登录态缓存
- 验证码缓存
- 登录失败次数缓存
- 防重提交短期缓存
- 接口限流计数
- 系统配置缓存
- 数据字典缓存
- 在线用户查询与强退
- 缓存监控页面与缓存清理接口
现有生产环境没有 Redis,因此需要彻底移除 Redis 依赖,并保证修改后与修改前的业务功能保持一致。
2. 已确认约束
- 生产环境为单实例部署
- 应用重启后,登录态、验证码、限流计数、登录失败次数等临时状态允许丢失
- 不引入新的中间件
- 不额外设计数据库持久化方案
- 目标是最短路径实现,避免补丁式和过度设计方案
3. 目标
- 移除 Redis 运行依赖与相关配置
- 保留现有业务功能与主要接口行为
- 保留现有前端缓存监控入口与主要能力
- 保证项目在无 Redis 配置、无 Redis 服务的情况下可正常启动和运行
4. 方案对比
方案一:统一进程内缓存层替换 Redis
将当前基于 Redis 的缓存访问统一收口为进程内缓存实现,保持上层业务调用方式和缓存语义尽量不变。
优点:
- 改动集中,替换边界清晰
- 最容易保持原有业务行为不变
- 不需要引入新基础设施
- 适合单实例部署场景
缺点:
- 需要补足 TTL、前缀查询、统计信息等基础能力
- 限流逻辑需要从 Redis 脚本改为本地原子实现
方案二:按场景分别重写
登录态、验证码、配置缓存、字典缓存、限流、防重分别改造成各自独立的本地实现。
优点:
- 单点改造直观
缺点:
- 改动分散
- 行为一致性难保证
- 容易遗漏使用点
- 后续维护成本更高
方案三:部分状态改存数据库
将登录态、验证码、失败次数等状态迁移到 MySQL。
优点:
- 状态具备一定持久性
缺点:
- 偏离本次最短路径目标
- 需要新增表结构、清理逻辑和一致性处理
- 复杂度明显高于当前需求
5. 设计结论
采用方案一:以统一进程内缓存层替换 Redis。
实现原则:
- 保留当前主要业务调用入口,避免业务层大面积改写
- 将所有 Redis 依赖集中替换为本地线程安全缓存实现
- 保持 key 组织方式、TTL 语义、按前缀检索、删除和清理行为不变
- 对外接口路径尽量不变,优先保障现有前后端功能连续性
6. 总体设计
6.1 基础设施替换边界
本次改造不采用“逐处删除 Redis 调用”的方式,而是保留当前缓存入口职责,将底层从 Spring Data Redis 替换为进程内缓存服务。
范围包括:
- 移除
spring-boot-starter-data-redis依赖 - 移除
application-*.yml中的 Redis 配置 - 移除
RedisTemplate、RedisConnectionFactory、Lua 限流脚本等 Redis 专属配置 - 为现有缓存访问入口提供本地实现
6.2 本地缓存能力要求
本地缓存组件必须提供以下能力:
setgethasKeydelete- 批量删除
- 基于前缀的
keys(pattern*) - TTL 过期控制
- 过期数据清理
- 基础命中和访问统计
该缓存实现需要线程安全,以保证登录、限流、防重提交等高频路径在单实例下的正确性。
7. 业务行为兼容设计
7.1 登录态
TokenService 当前通过 JWT 保存 token 标识,并将 LoginUser 存入 Redis。改造后继续维持该模型:
- JWT 内容保持不变
token -> LoginUser存入本地缓存- TTL 仍由
token.expireTime控制 - 临近过期时继续自动续期
- 注销时删除对应登录态
这样可以保持登录、鉴权、刷新 token、在线用户列表、强退用户等行为不变。
7.2 验证码
验证码继续按 uuid -> code 存储在本地缓存中,并沿用当前过期时间配置。
- 生成验证码后写入缓存
- 校验时读取并删除
- 过期后自动失效
7.3 登录失败次数
登录失败次数继续按用户名缓存,保持:
- 连续失败次数累加
- 达到阈值后锁定
- 锁定时间到期后自动解除
- 登录成功后清理失败记录
7.4 防重提交
SameUrlDataInterceptor 继续按 url + submitKey 保存短时缓存,保留当前毫秒级过期控制和重复提交判断逻辑。
7.5 限流
原有限流逻辑依赖 Redis Lua 脚本做原子计数。由于当前部署为单实例,可以改为本地原子计数实现,保留现有注解参数语义:
- 限流 key 规则不变
- 时间窗口含义不变
- 阈值含义不变
- 超限返回逻辑不变
7.6 系统配置缓存
SysConfigServiceImpl 继续通过缓存保存系统配置,保持:
- 启动加载缓存
- 按 key 读取缓存
- 新增、修改、删除配置时同步刷新缓存
- 手动刷新缓存接口继续可用
7.7 数据字典缓存
DictUtils 与字典服务继续使用缓存保存字典数据,保持:
- 首次加载与重载逻辑不变
- 字典刷新接口不变
- 前端字典相关功能无感知
7.8 在线用户
在线用户列表和强退功能继续基于登录 token 前缀扫描实现,因此本地缓存必须支持按前缀查询 key。
7.9 缓存监控
不删除缓存监控功能。保留:
- 菜单入口
- 前端页面路由
- 后端接口路径
- 缓存清理能力
底层统计来源从 Redis 改为本地缓存统计视图。
8. 缓存监控设计
8.1 保留现有能力
CacheController 继续提供以下接口能力:
- 缓存概览
- 缓存名称列表
- 指定分类下的 key 列表
- 指定 key 的值查看
- 按分类清理
- 按 key 清理
- 全量清理
8.2 监控数据来源调整
由于 Redis 已移除,缓存监控页面中的信息调整为本地缓存统计信息,例如:
- 缓存类型:
IN_MEMORY - 运行模式:
single-instance - 当前缓存总数
- 读取次数
- 命中次数
- 过期清理次数
返回结构应尽量兼容当前前端页面,减少前端改动范围。
8.3 文案调整
对于前端页面中明显写死的 Redis 文案,需要调整为更准确的“缓存监控”或“本地缓存监控”,避免出现界面语义错误。
9. 配置与依赖调整
需要完成以下调整:
- 删除 Maven 中 Redis 相关依赖
- 删除后端配置中的 Redis 段
- 清理 Redis 专属配置类与序列化器引用
- 清理直接依赖
RedisTemplate的控制器和切面实现 - 将相关逻辑改为依赖统一的本地缓存服务
10. 测试与验收
验收以业务行为为准,至少覆盖:
- 登录成功后可访问受保护接口
- token 临近过期时自动续期正常
- 在线用户列表可查询
- 在线用户强退可用
- 验证码生成与校验正常
- 登录失败次数限制正常
- 防重提交正常
- 限流正常
- 配置缓存刷新正常
- 字典缓存刷新正常
- 缓存监控页面可打开、可查看、可清理
- 项目在无 Redis 配置、无 Redis 服务时可启动
11. 风险与边界
- 本方案仅适用于当前确认的单实例部署
- 由于缓存改为进程内存储,多实例部署时不会共享状态
- 重启后临时状态会丢失,此行为已被确认可接受
- 本次不增加跨实例一致性能力,不增加持久化方案
12. 实施范围说明
本设计文档仅定义 Redis 移除与本地缓存替换方案,不扩展到以下范围:
- 多实例一致性方案
- 引入数据库持久化缓存
- 引入新的第三方缓存组件
- 额外新增降级或兜底机制
13. 后续输出
在该设计确认后,下一步需要输出两份实施计划:
- 后端实施计划
- 前端实施计划
并在实际编码改动时同步维护对应实施记录文档。