Redis过期策略:一篇让小白彻底搞懂的文章
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。
一、面试经典问题:到期立刻删除吗?
面试官问:“Redis设置了过期时间的key,到期会立刻删除吗?”
小白常见回答:“会的,过期就自动删了。”
正确答案:“不会立刻删除! Redis用的是‘拖延症’策略——能不删就不删,等到必要时候才删。”
就像你妈让你整理房间,你不会马上整理,而是:
- 等要用房间时再整理(惰性删除)
- 每隔一段时间被迫整理一点(定期删除)
二、Redis的两种“拖延”删除策略
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。
策略1:惰性删除(用的时候才检查)
就像:找东西时才整理抽屉
当你访问一个key时:
1. Redis先问:“这个key过期了吗?”
2. 如果过期了 → 当场扔掉,告诉你“没有这个key”
3. 如果没过期 → 正常给你数据
特点:
✓ 省力:不用一直检查
✗ 可能积灰:如果key永远没人访问,就永远占着内存
举个例子:
- 你去年双11的购物车缓存,设置了30天过期
- 如果之后没人再看购物车,这个key会在内存里躺一年
- 直到某天你想看购物车,Redis才说:“哦,这个过期一年了,删掉吧”
策略2:定期删除(定时抽查)
就像:每周日抽查整理房间
Redis每100毫秒(0.1秒)做一次:
1. 随机抽20个设置了过期时间的key
2. 检查它们过期了没
3. 删除过期的
如果抽查发现:
- 过期的key多(>25%)→ 继续抽查下一批
- 过期的key少 → 结束本轮抽查
特点:
✓ 主动清理:定期扫除垃圾
✗ 抽查可能漏掉:可能有些过期key没被抽到
实际流程:
时间轴:0秒 → 0.1秒 → 0.2秒 → ...
0秒:内存里有10000个key,其中2000个已过期但还在
0.1秒:随机抽20个,发现8个过期 → 删除8个 → 还有1992个过期key
0.2秒:再抽20个,发现5个过期 → 删除5个 → 还有1987个过期key
...
核心要记住:过期key不会立刻消失!它们可能还在内存里待一段时间。
三、内存满了怎么办?8种淘汰策略
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。
当Redis内存用完时,就像衣柜满了要扔衣服,有8种“扔法”:
8种策略简单比喻
| 策略 | 怎么扔 | 适合场景 |
|---|---|---|
| noeviction | 不扔,新衣服不让放 | 贵重物品(绝对不能丢) |
| allkeys-lru | 把最久没穿的衣服扔掉 | 最常用!适合缓存 |
| volatile-lru | 只扔设置了保质期且最久没穿的 | 区分永久和临时物品 |
| allkeys-random | 随机扔一件衣服 | 所有衣服价值差不多时 |
| volatile-random | 从有保质期的衣服里随机扔 | 临时物品随机淘汰 |
| volatile-ttl | 扔最快过期的衣服 | 优先清理快过期的 |
| allkeys-lfu | 扔最不常穿的衣服(Redis 4.0+) | 保护常穿的,扔不常穿的 |
| volatile-lfu | 从有保质期的衣服里扔最不常穿的 | 临时物品按使用频率淘汰 |
怎么选?一张图搞定
问:数据能丢吗?
├── 不能丢 → 选 noeviction(但要确保内存足够!)
└── 能丢(缓存场景) →
问:所有数据都能淘汰吗?
├── 都能 → 选 allkeys-lru(或allkeys-lfu if Redis 4.0+)
└── 只能淘汰临时数据 → 选 volatile-lru 或 volatile-ttl
生产环境推荐
# 95%的场景用这个:
maxmemory 16gb # 设置内存上限(物理内存的75%)
maxmemory-policy allkeys-lru # 淘汰最久没用的
四、必须知道的面试坑
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。
坑1:大量key同时过期(缓存雪崩)
错误做法:
# 双11零点,所有商品缓存同时设置1小时过期
SETEX product:1001 3600 "商品信息"
SETEX product:1002 3600 "商品信息"
# ... 一万个商品都在1小时后同时过期
会发生什么:
- 1小时后:所有缓存同时失效
- 用户访问:发现缓存没了,全都去查数据库
- 数据库:瞬间被打爆,可能挂掉
- 系统:崩溃
解决方案:加随机时间
# 正确做法:过期时间 = 基础时间 + 随机时间
基础过期时间 = 3600 # 1小时
随机时间 = 随机数(0到300) # 0-5分钟随机
实际过期时间 = 3600 + 随机时间
# 结果:有的1小时过期,有的1小时5分过期,分散开
坑2:永不过期的key太多
有些同学喜欢设置永久缓存:
SET user:1001 "用户数据" # 没设置过期时间!
结果内存慢慢被占满,又没设置淘汰策略,最后Redis写不进去了。
正确做法:
# 1. 一定要设置maxmemory
# 2. 选择合理的淘汰策略
# 3. 即使“永久”缓存,也要设置很长过期时间(如30天)
SETEX user:1001 2592000 "用户数据" # 30天过期
五、实战配置指南(抄作业版)
场景1:普通Web应用缓存
# redis.conf 配置
maxmemory 8gb # 8G内存上限
maxmemory-policy allkeys-lru # 淘汰最近最少用的
maxmemory-samples 10 # 抽查10个key(默认)
场景2:用户登录Session
maxmemory 4gb
maxmemory-policy volatile-ttl # 优先淘汰快过期的Session
场景3:重要数据不能丢
maxmemory 16gb
maxmemory-policy noeviction # 不淘汰,但必须监控内存!
# 必须配合:监控告警 + 及时扩容
通用最佳实践
- 一定要设置maxmemory:防止Redis吃光服务器内存
- 默认用allkeys-lru:适合大多数缓存场景
- 避免同时过期:过期时间加随机数
- 监控内存使用:设置80%报警,90%紧急报警
六、面试满分回答模板
面试官:“说说Redis的过期策略?”
你可以这样回答:
Redis的过期策略分两层:
第一层:过期删除(拖延策略)
1. 惰性删除:访问key时才检查是否过期,过期就删
2. 定期删除:每100ms随机抽查一批key,删除过期的
所以,过期key不会立刻删除,可能还在内存里待一会。
第二层:内存淘汰(内存满了怎么办)
有8种策略,最常用的是allkeys-lru:淘汰最近最少使用的key。
生产环境要注意:
1. 避免大量key同时过期(加随机时间防雪崩)
2. 必须设置maxmemory和淘汰策略
3. 根据业务选择策略:缓存用allkeys-lru,Session用volatile-ttl
七、小白常见问题解答
Q1:我怎么知道有多少过期key?
# 查看统计信息
redis-cli info keyspace
# 看到:db0:keys=1000,expires=300
# 意思:总共1000个key,其中300个设置了过期时间
Q2:为什么我的Redis内存一直涨?
可能原因:
- 很多key永不过期
- 过期key还没被删除(在等惰性或定期删除)
- 内存淘汰策略没生效(没设置maxmemory)
Q3:设置多大的maxmemory合适?
服务器有16G内存:
推荐:maxmemory 12gb # 留4G给系统和其他应用
服务器有8G内存:
推荐:maxmemory 6gb # 留2G给系统
Q4:线上Redis内存满了怎么办?
紧急步骤:
- 临时扩容:增加maxmemory值
- 清理数据:手动删除不重要的key
- 分析原因:用
redis-cli --bigkeys找大key - 长期方案:优化过期策略,分片集群
八、记住这5条就够用
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。
- 过期不立即删:Redis有惰性和定期两种删除
- 内存满了要淘汰:8种策略里,缓存用
allkeys-lru - 防雪崩加随机:过期时间加随机数,避免同时失效
- 一定要设上限:必须设置maxmemory,默认无上限很危险
- 监控不能少:监控内存使用率,设置报警
最后给小白的话: Redis过期就像你家的冰箱:
- 食物有保质期(key有过期时间)
- 你不会每天检查所有食物(惰性删除)
- 周末会清理一下冰箱(定期删除)
- 冰箱满了要扔掉一些食物(内存淘汰)
理解这个比喻,你就懂了Redis过期策略的精髓!