Loading

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 旧日志快速清理

七、注意事项

  1. LRU/LFU 是近似算法:为了性能,Redis 使用采样而非精确统计

  2. 淘汰是同步阻塞的大量淘汰会短暂影响性能,建议设置告警提前扩容

  3. 主从复制差异:默认从节点不执行淘汰,避免主从不一致

  4. 集群模式:每个节点独立执行淘汰,需保证数据分布均匀

posted @ 2026-03-01 20:11  Carvers  阅读(1)  评论(0)    收藏  举报