Redis 缓存机制与实战避坑指南
一、 核心概念:Redis 是什么?
Redis 是一个基于内存的高性能键值对(Key-Value)数据库。
- 优势:读写速度极快(微秒级),适合做缓存。
- 劣势:内存断电即失,数据易丢失。
- 定位:在 Java 项目中,通常作为 MySQL 的“前置缓存”,减轻数据库压力。
二、 核心机制:缓存读写流程(Cache-Aside Pattern)
当程序需要读取配置或数据时,遵循以下标准流程(以若依框架的 selectConfigByKey 为例):
- 先查缓存:程序先去 Redis 里找对应的 Key。
- 命中缓存:如果 Redis 里有,直接返回,绝对不看数据库。
- 未命中缓存:如果 Redis 里没有(Key 不存在或已过期),程序会去 MySQL 数据库查。
- 回写缓存:从 MySQL 查到数据后,程序会顺手把数据写回 Redis,方便下次查询。
实战启示:当你修改了数据库,但没更新 Redis,程序永远读的是 Redis 里的旧值。这就是“改库不生效”的根本原因。
三、 缓存更新策略:为什么页面修改能生效,改库不生效?
| 操作方式 | 底层逻辑 | 是否生效 |
|---|---|---|
| 通过系统页面修改 | 执行 updateConfig 方法,同时更新 MySQL 和 Redis。 | ✅ 立即生效 |
| 直接修改 MySQL 数据库 | 只更新了 MySQL,Redis 里的旧值依然存在。 | ❌ 不生效 |
| 重启 Redis | 如果开启了持久化,Redis 会把硬盘上的旧数据重新加载回内存。 | ❌ 通常不生效 |
| 重启 Java 后端 | 会触发 resetConfigCache 逻辑,清空并重新加载所有配置到 Redis。 | ✅ 生效 |
| 手动 DEL 缓存 Key | 精准删除 Redis 里的脏数据,下次请求会自动去 MySQL 查最新值并回写。 | ✅ 立即生效 |
四、 持久化机制:为什么重启 Redis 没用?
Redis 为了防止数据丢失,默认开启了持久化(RDB),它会把内存里的数据保存到硬盘上。
dump.rdb文件:Redis 的“存档文件”。- 关闭 Redis 时:Redis 会把内存里的数据(包括错误的旧值)存入
dump.rdb。 - 启动 Redis 时:Redis 会读取
dump.rdb,把旧数据原封不动地恢复到内存里。
- 关闭 Redis 时:Redis 会把内存里的数据(包括错误的旧值)存入
- 结果:你重启了 Redis,但缓存里的旧值又回来了,问题依旧。
- 如何彻底清空:在 Redis 关闭状态下,去
D:\Redis\目录删掉dump.rdb文件,再启动 Redis,它就会以空内存运行。
注意:生产环境不能随便删
dump.rdb,会导致用户掉线、缓存雪崩。
五、 实战避坑:如何正确修改 Redis 里的配置?
错误姿势:
- 直接改 MySQL 数据库,指望 Redis 自动同步。
- 直接重启 Redis,指望清空缓存。
- 直接删除
dump.rdb(生产环境禁止)。
正确姿势(推荐按顺序):
- 改数据库:确保改的值格式正确(如全小写
true)。 - 精准清缓存:打开 Redis 客户端,执行
DEL sys_config:sys.account.captchaEnabled。 - 刷新页面:重新发起请求,程序会自动去 MySQL 查最新值并写入 Redis。
六、 高级技巧:关闭持久化(仅限开发环境)
如果你在本地开发,每次改完库都要手动删缓存太麻烦,可以直接关闭 Redis 持久化,让 Redis 变成纯内存缓存。
命令行启动方式:
redis-server.exe --save "" --appendonly no
--save "":禁用 RDB 快照。--appendonly no:禁用 AOF 日志。
修改配置文件:
在 redis.windows.conf 中修改:
save ""
appendonly no
启动时带上配置文件:redis-server.exe redis.windows.conf
关闭持久化后:Redis 一关,数据全没,重启就是空内存,下次请求会自动去 MySQL 查最新数据。
警告:生产环境绝对不能关闭持久化,否则 Redis 一挂,所有用户掉线,请求会瞬间击垮 MySQL。
七、 常见问题排查清单(FAQ)
Q1:改了数据库,接口返回旧值,怎么办?
- 检查 Redis:去 Redis 查对应的 Key 是否存在,值是否正确。
- 手动清除:执行
DEL 对应的key。 - 再次测试:刷新页面,看是否生效。
Q2:Redis 里的值为什么带双引号(如 "false")?
- 这通常是序列化问题(如 Jackson 序列化把字符串转为 JSON 格式)。
- 如果代码比较逻辑是
"true".equals(value),那么"false"带引号会导致判断失败,需要修改序列化配置或代码逻辑。
Q3:为什么重启 Redis 不生效,重启 Java 后端就生效?
- 重启 Redis:如果开了持久化,旧数据会恢复;如果没开,数据会清空,但程序启动时可能会重新写入旧值(取决于代码逻辑)。
- 重启 Java:会触发启动初始化逻辑(如
@PostConstruct),强制从 MySQL 重新加载所有配置到 Redis。
八、 总结:记住这三句话
- 页面改配置:走的是
updateConfig,会同步更新 Redis。 - 直接改数据库:只改了 MySQL,Redis 不知道,所以不生效。
- 清缓存的正确方式:精准
DEL对应的 Key,不要盲目重启 Redis。
这份文档涵盖了你在实际开发中遇到的 Redis 缓存核心问题,建议保存下来,以后遇到类似问题直接翻看,能帮你省下大量排查时间。