redis 淘汰策略及具体使用场景
当 Redis 内存达到 maxmemory 限制时,需要通过淘汰策略来决定如何释放空间。Redis 提供了 8 种淘汰策略,分为三大类:
┌─────────────────────────────────────────────────────────┐
│ Redis 淘汰策略 │
├─────────────────┬───────────────────────────────────────┤
│ 不淘汰类 │ noeviction │
├─────────────────┼───────────────────────────────────────┤
│ 全体 Key 淘汰 │ allkeys-lru / allkeys-lfu / │
│ (All Keys) │ allkeys-random │
├─────────────────┼───────────────────────────────────────┤
│ 过期 Key 淘汰 │ volatile-lru / volatile-lfu / │
│ (Volatile) │ volatile-random / volatile-ttl │
└─────────────────┴───────────────────────────────────────┘
一、不淘汰策略
1. noeviction(不淘汰)
| 属性 | 说明 |
|---|---|
| 行为 | 内存满时,新写入操作直接返回错误,不删除任何数据 |
| 读操作 | 正常执行 |
| 写操作 | 拒绝并返回 (error) OOM command not allowed |
使用场景:
| 场景 | 说明 |
|---|---|
| 金融交易数据 | 每一笔交易记录都不能丢失,内存满时必须扩容而非删除 |
| 核心配置存储 | 系统关键配置,如支付渠道配置、风控规则 |
| 分布式锁服务 | 锁信息绝对不能被意外删除,需独立 Redis 实例 |
| 数据持久化优先 | 宁愿服务不可用,也不能丢失数据 |
示例:
# 配置
maxmemory-policy noeviction
# 应用场景 - 支付订单缓存
SET order:202403010001 '{"amount": 100, "status": "paid"}'
# 当内存满时,新的 SET 会失败,应用层需要处理错误并触发扩容告警
二、全体 Key 淘汰策略(All Keys)
这类策略对所有 Key 生效,无论是否设置过期时间。
2. allkeys-lru(最近最少使用)
| 属性 | 说明 |
|---|---|
| 算法 | LRU(Least Recently Used)近似算法 |
| 淘汰对象 | 最长时间未被访问的 Key |
| 采样数 | 默认随机采样 5 个,淘汰其中最久未使用的 |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 通用缓存 | 最常见的缓存场景,如用户会话、商品详情 |
| 热点数据缓存 | 保留最近被访问的数据,淘汰冷门数据 |
| 社交网络 | 用户最近查看的帖子、好友动态 |
| API 响应缓存 | 接口返回结果的缓存 |
示例:
# 配置
maxmemory-policy allkeys-lru
maxmemory-samples 5 # 采样数量,越大越精确但越慢
# 场景:电商商品详情缓存
# 用户频繁访问 iPhone 15 详情页,该 Key 被保留
# 一个月没人看的 iPhone 12 详情页被淘汰
GET product:iphone15 # 访问时间更新,不会被淘汰
GET product:iphone12 # 很久没访问,优先被淘汰
3. allkeys-lfu(最不经常使用)
| 属性 | 说明 |
|---|---|
| 算法 | LFU(Least Frequently Used) |
| 淘汰对象 | 访问频率最低的 Key |
| 计数器 | 每个 Key 有 8 位计数器(0-255),随时间衰减 |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 热点识别场景 | 需要区分"突发访问"和"持续热点" |
| 新闻/内容推荐 | 真正热门的新闻持续被访问,突发流量但后续无访问的被淘汰 |
| 商品排行榜 | 长期畅销品保留,昙花一现的促销品淘汰 |
| 广告系统 | 高频展示的广告保留,低频的淘汰 |
LRU vs LFU 对比:
场景:某商品被秒杀,1 分钟内访问 10 万次,之后无人问津
LRU 策略:该商品最近被访问过,会一直保留,占用内存
LFU 策略:虽然访问次数多,但后续频率为 0,计数器衰减后被淘汰 ✓
场景:某商品每天稳定被访问 1000 次,持续一个月
LRU 策略:只要定期有访问,就能保留
LFU 策略:频率计数器高,优先保留 ✓
示例:
# 配置
maxmemory-policy allkeys-lfu
# 场景:视频平台推荐系统
# 视频 A:突然爆火(1小时100万播放),但之后没人看 → LFU 淘汰
# 视频 B:每天稳定 10 万播放,持续一个月 → LFU 保留
4. allkeys-random(随机淘汰)
| 属性 | 说明 |
|---|---|
| 算法 | 随机选择 Key 进行淘汰 |
| 特点 | 实现简单,开销最小 |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 数据访问完全随机 | 没有明显的热点模式 |
| 临时数据池 | 如验证码、临时 Token |
| 测试环境 | 不关心具体淘汰哪个 Key |
| 性能敏感 | LRU/LFU 的采样有 CPU 开销,Random 最低 |
示例:
# 配置
maxmemory-policy allkeys-random
# 场景:短信验证码缓存
# 每个验证码 5 分钟有效期,访问完全是随机的
# 使用 Random 策略,避免 LRU/LFU 的维护开销
SETEX sms:code:13800138000 300 "123456"
三、过期 Key 淘汰策略(Volatile)
这类策略只对设置了过期时间(TTL)的 Key 生效,未设置过期时间的 Key 不会被淘汰。
5. volatile-lru(过期 Key 中最近最少使用)
| 属性 | 说明 |
|---|---|
| 范围 | 仅在设置了 TTL 的 Key 中选择 |
| 算法 | LRU |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 混合存储 | 部分数据永久保留(如配置),部分可淘汰(如缓存) |
| 会话管理 | 用户会话有过期时间,但用户基础信息永久保留 |
| 多级缓存 | 热点数据不设过期,普通缓存设过期并 LRU 淘汰 |
示例:
# 配置
maxmemory-policy volatile-lru
# 场景:用户系统混合存储
# 永久数据(不设置过期)- 不会被任何 volatile 策略淘汰
SET user:1000:profile '{"name": "张三", "level": "VIP"}'
# 缓存数据(设置过期)- 可被 LRU 淘汰
SETEX user:1000:session 3600 "session_data"
SETEX user:1000:feed 1800 "feed_data"
# 内存满时,优先淘汰 feed(假设更久没被访问)
6. volatile-lfu(过期 Key 中最不经常使用)
| 属性 | 说明 |
|---|---|
| 范围 | 仅在设置了 TTL 的 Key 中选择 |
| 算法 | LFU |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 限时活动 | 需要识别真正热门的活动数据 |
| 短期推荐 | 24 小时内的热门内容推荐 |
| 临时排行榜 | 小时级更新的排行榜 |
示例:
# 配置
maxmemory-policy volatile-lfu
# 场景:双 11 活动页面缓存
# 所有活动数据设置 24 小时过期
SETEX activity:page:1 86400 "page_data" # 高频访问,保留
SETEX activity:page:2 86400 "page_data" # 低频访问,淘汰
7. volatile-random(过期 Key 中随机淘汰)
| 属性 | 说明 |
|---|---|
| 范围 | 仅在设置了 TTL 的 Key 中选择 |
| 算法 | Random |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 定时任务队列 | 延迟队列中的任务,执行顺序不依赖访问模式 |
| 临时令牌池 | 随机淘汰不影响业务 |
8. volatile-ttl(即将过期的 Key 优先淘汰)
| 属性 | 说明 |
|---|---|
| 范围 | 仅在设置了 TTL 的 Key 中选择 |
| 算法 | 优先淘汰 TTL 最小的(最快过期的) |
使用场景:
| 场景 | 详细说明 |
|---|---|
| 延迟队列 | 优先清理快到期的任务,避免内存浪费 |
| 限时优惠 | 快过期的优惠券优先清理 |
| 实时数据 | 实时性要求高的数据,旧数据快速清理 |
| 日志/轨迹 | 近期日志保留,旧日志快速淘汰 |
示例:
# 配置
maxmemory-policy volatile-ttl
# 场景:订单超时处理队列
# 订单 30 分钟未支付自动关闭
SETEX order:timeout:001 1800 "pending" # 还剩 30 分钟
SETEX order:timeout:002 60 "pending" # 还剩 1 分钟,优先被淘汰(已处理或即将处理)
# 内存满时,优先淘汰 order:timeout:002(TTL 更小)
四、策略选择决策树
开始
│
▼
数据是否绝对不能丢失? ──是──► noeviction
│ (配合监控告警和扩容)
否
│
▼
是否所有数据都设置了过期时间? ──是──► 访问是否有明显热点?
│ │
否 ├─是(突发热点)► volatile-lfu
│ │
▼ └─否(常规访问)► volatile-lru
数据是否有部分需要永久保留? ──是──► volatile-lru
│ (保护永久数据)
否
│
▼
访问是否有明显热点模式? ──是──► allkeys-lfu
│ (区分持续热点和突发流量)
否
│
▼
allkeys-lru (默认推荐,通用场景)
五、关键配置参数
# redis.conf 核心配置
# 1. 最大内存限制(必须设置)
maxmemory 4gb
# 2. 淘汰策略(根据场景选择)
maxmemory-policy allkeys-lru
# 3. 采样数量(LRU/LFU 的精度控制)
# 默认 5,范围 1-10,越大越精确但 CPU 消耗越高
maxmemory-samples 5
# 4. LFU 计数器衰减时间(分钟)
# 默认 1,LFU 计数器随时间衰减的速度
lfu-decay-time 1
# 5. LFU 计数器初始值
# 新 Key 的初始计数器值,避免新 Key 立即被淘汰
lfu-log-factor 10
# 6. 从节点是否忽略内存限制
# 默认 yes,从节点不执行淘汰,保持与主节点一致
replica-ignore-maxmemory yes
六、实际业务场景配置建议
| 业务场景 | 推荐策略 | 理由 |
|---|---|---|
| 电商商品缓存 | allkeys-lru | 保留热门商品,冷门自动淘汰 |
| 社交网络 Feed | allkeys-lfu | 区分持续热度和突发热度 |
| 金融支付系统 | noeviction | 数据绝对安全,配合扩容 |
| 游戏排行榜 | volatile-ttl | 快速清理过期榜单数据 |
| 分布式锁服务 | noeviction | 独立实例,锁不能丢失 |
| 临时验证码 | allkeys-random | 完全随机访问,最小开销 |
| 用户会话 + 配置 | volatile-lru | 配置永久保留,会话可淘汰 |
| 实时日志系统 | volatile-ttl | 旧日志快速清理 |
七、注意事项
-
LRU/LFU 是近似算法:为了性能,Redis 使用采样而非精确统计
-
淘汰是同步阻塞的:大量淘汰会短暂影响性能,建议设置告警提前扩容
-
主从复制差异:默认从节点不执行淘汰,避免主从不一致
-
集群模式:每个节点独立执行淘汰,需保证数据分布均匀
本文来自博客园,作者:Carvers,转载请注明原文链接:https://www.cnblogs.com/carver/articles/19656687

浙公网安备 33010602011771号