Tavio's blog Tavio's blog
首页
  • JVM底层原理
  • 邪恶多线程
  • MyBatis底层原理
  • Spring底层原理
  • MySQL的优化之路
  • ClickHouse的高性能
  • Redis的快速查询
  • RabbitMQ的生产
  • Kafka的高吞吐量
  • ES的入门到入坑
  • MySQL自增ID主键空洞
  • 前端实现长整型排序
  • MySQL无感换表
  • Redis延时双删
  • 高并发秒杀优惠卷
  • AOP无侵入式告警
  • 长短链接跳转
  • 订单超时取消
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Tavio Zhang

努力学习的小码喽
首页
  • JVM底层原理
  • 邪恶多线程
  • MyBatis底层原理
  • Spring底层原理
  • MySQL的优化之路
  • ClickHouse的高性能
  • Redis的快速查询
  • RabbitMQ的生产
  • Kafka的高吞吐量
  • ES的入门到入坑
  • MySQL自增ID主键空洞
  • 前端实现长整型排序
  • MySQL无感换表
  • Redis延时双删
  • 高并发秒杀优惠卷
  • AOP无侵入式告警
  • 长短链接跳转
  • 订单超时取消
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Redis核心数据结构
  • Redis持久化机制
  • Redis高可用架构
  • Redis分布式锁
  • Redis缓存设计
  • Redis大Key与热Key
  • Redis限流
  • Redis IO多路复用
  • Redis过期删除策略
    • 一、先搞懂:Redis为什么不搞“精确过期删除”?
    • 二、三大核心策略拆解:惰性删除+定期删除+内存淘汰
      • 1. 惰性删除:“用的时候再检查”,最省CPU的被动策略
      • 核心原理
      • 优缺点分析
      • 适用场景
      • 2. 定期删除:“每隔一段时间扫一批”,平衡CPU和内存的主动策略
      • 核心原理
      • 关键配置参数
      • 优缺点分析
      • 3. 内存淘汰机制:“内存满了再清理”,最后的兜底策略
      • 核心原理
      • 7种核心淘汰策略(Redis 6.2+)
      • 优缺点分析
    • 三、协同工作流程:Redis是如何组合三种策略的?
    • 四、实战配置优化:不同业务场景的最优方案
      • 1. 通用缓存场景(如电商商品缓存、接口缓存)
      • 2. 核心数据缓存场景(如用户登录状态、订单信息)
      • 3. 临时数据场景(如验证码、临时会话)
      • 4. 不允许数据丢失场景(如金融交易记录缓存)
    • 五、常见坑点与避坑指南
      • 坑1:设置了expire,但key依然长期存在
      • 坑2:Redis突然响应变慢,CPU占用飙升
      • 坑3:核心未过期key被淘汰,导致业务异常
      • 坑4:认为“expire设置后,key一定会在到期时删除”
    • 六、总结:Redis过期删除的核心逻辑
  • Redis Bitmap
  • 《Redis》笔记
Tavio
2024-01-13
目录

Redis过期删除策略

在使用Redis的过程中,你是否遇到过这样的问题:明明给key设置了过期时间(expire),但到点后key却依然存在,导致内存占用居高不下?或者偶尔出现Redis响应变慢,排查后发现是大量过期key集中删除导致的?

这一切的根源,都在于Redis的过期删除策略。与传统数据库的“精确过期删除”不同,Redis作为内存数据库,需要在“内存占用”和“性能损耗”之间寻找平衡,因此设计了一套混合式的过期删除机制。

# 一、先搞懂:Redis为什么不搞“精确过期删除”?

首先要明确一个核心前提:Redis的过期删除,不是简单的“到点就删”。如果采用“精确过期删除”(即给每个过期key绑定一个定时器,到时间立即删除),虽然能保证过期key及时清理,但会带来两个致命问题:

  • 性能损耗过大:如果Redis中存在大量过期key,每个key都需要一个定时器,会占用大量CPU资源,尤其是在高并发场景下,CPU会被频繁的删除操作占用,导致Redis响应延迟;
  • 内存碎片风险:频繁的精确删除会产生大量内存碎片,降低内存利用率,长期运行可能导致内存溢出。

而Redis的核心优势是“高性能”和“高并发”,因此必须放弃“精确性”,选择“高效性”优先的设计思路。在此基础上,Redis设计了三种核心过期删除策略:惰性删除、定期删除、内存淘汰机制,三者协同工作,共同实现过期key的清理。

# 二、三大核心策略拆解:惰性删除+定期删除+内存淘汰

Redis的过期删除逻辑,是“被动清理”与“主动清理”结合的产物。下面逐一拆解三种策略的工作原理、优缺点,以及它们之间的协同逻辑。

# 1. 惰性删除:“用的时候再检查”,最省CPU的被动策略

# 核心原理

惰性删除的逻辑非常简单:不主动删除任何过期key,只有当客户端访问某个key时,才检查该key是否过期。如果过期,则立即删除并返回“nil”;如果未过期,则正常返回key的值。

形象地说,这就像“囤货党”——东西过期了不主动扔,只有当想起来要吃/用的时候,才看一眼是否过期,过期了再扔。

# 优缺点分析

优点 缺点
CPU效率极高,无需主动消耗CPU资源扫描和删除过期key 内存利用率低,大量过期key可能长期占用内存(“内存泄漏”风险)
删除操作仅在“访问时”触发,不会出现集中删除导致的性能波动 如果过期key长期不被访问,会一直占用内存,直到Redis内存不足

# 适用场景

适合过期key访问频率较低、内存资源相对充足的场景。但仅靠惰性删除无法解决“内存泄漏”问题,因此必须配合其他策略使用。

# 2. 定期删除:“每隔一段时间扫一批”,平衡CPU和内存的主动策略

# 核心原理

定期删除是Redis的“主动清理”策略:Redis会每隔一段时间(由配置参数决定),主动扫描一部分过期key并删除。但它并不是“全量扫描”,而是“抽样扫描”,具体逻辑如下:

  1. 从设置了过期时间的key的集合(expires字典)中,随机抽取N个key;
  2. 检查这N个key是否过期,过期的则删除;
  3. 如果本次扫描中,过期key的比例超过了M%,则继续重复步骤1-2;否则,本次扫描结束。

这里的N和M都是可配置的参数(默认N=20,M=25),通过这种“抽样+循环”的方式,既保证了一定的清理效率,又避免了全量扫描带来的CPU压力。

形象地说,这就像“定期大扫除”——不是每天把所有角落都扫一遍,而是每隔一段时间,随机挑几个角落扫,要是发现脏的地方多,就多扫一会儿;要是比较干净,就先停。

# 关键配置参数

定期删除的核心逻辑由以下两个配置参数控制(可在redis.conf中修改):

  • hz 10:Redis的“心跳频率”,即每秒执行定期任务的次数(默认10次)。hz值越高,定期删除的频率越高,过期key清理越及时,但CPU占用也越高;
  • maxmemory-samples 5:内存淘汰时的抽样数量(与定期删除的抽样逻辑类似),默认5个。

# 优缺点分析

优点 缺点
平衡了CPU和内存:既主动清理了部分过期key,减少内存占用,又通过抽样避免了全量扫描的CPU损耗 存在“漏删”风险:抽样扫描无法覆盖所有过期key,部分过期key可能依然长期存在
可通过配置hz参数调整清理频率,适配不同业务场景 如果hz设置过高,会占用过多CPU资源;设置过低,过期key清理不及时

# 3. 内存淘汰机制:“内存满了再清理”,最后的兜底策略

即使有了惰性删除和定期删除,依然可能存在大量过期key未被清理的情况。当Redis的内存使用达到上限(由maxmemory参数设置)时,就需要通过“内存淘汰机制”强制清理部分key,腾出内存空间,保证Redis正常运行。

# 核心原理

内存淘汰机制的触发条件是:Redis使用的内存达到maxmemory阈值,且新的写操作请求进来时。此时Redis会根据预设的淘汰策略,从内存中选择一部分key删除,然后执行新的写操作。

注意:内存淘汰机制不仅会删除过期key,在过期key不足时,也会删除未过期的key——这是它与前两种策略的核心区别(前两种仅删除过期key)。

# 7种核心淘汰策略(Redis 6.2+)

Redis支持多种内存淘汰策略,可通过maxmemory-policy参数配置,不同策略适配不同的业务场景:

策略名称 核心逻辑 适用场景
noeviction(默认) 不淘汰任何key,内存满时拒绝所有写操作(返回OOM错误) 不允许数据丢失的场景(如金融交易数据),需手动监控内存
allkeys-lru 从所有key中,淘汰“最近最少使用”(LRU)的key 通用场景,适合大多数业务(如缓存热点数据)
volatile-lru 仅从设置了过期时间的key中,淘汰“最近最少使用”的key 需要保留未过期key(如核心配置数据),仅清理过期缓存的场景
allkeys-random 从所有key中,随机淘汰一部分key key的访问频率均匀,无明显热点的场景(如随机生成的临时key)
volatile-random 仅从设置了过期时间的key中,随机淘汰一部分key 临时缓存场景,且无需区分访问频率
volatile-ttl 仅从设置了过期时间的key中,淘汰“剩余过期时间最短”(TTL最小)的key 需要优先清理即将过期的缓存数据的场景
volatile-lfu 仅从设置了过期时间的key中,淘汰“最近最少频率使用”(LFU)的key 缓存场景中,需要区分访问频率(如低频访问的缓存优先清理)
allkeys-lfu 从所有key中,淘汰“最近最少频率使用”(LFU)的key 通用场景,比LRU更精准(避免偶发访问导致的热点key被淘汰)

# 优缺点分析

优点 缺点
内存安全的最后保障:即使前两种策略失效,也能通过淘汰key保证Redis正常运行 可能删除未过期的核心key(如配置不当),导致业务异常
策略多样,可根据业务需求灵活选择 淘汰操作会占用CPU资源,可能导致写操作延迟

# 三、协同工作流程:Redis是如何组合三种策略的?

单独看每种策略都有缺陷,但组合起来后,就能实现“CPU高效+内存可控”的平衡。Redis的过期key清理完整流程如下:

  1. 日常清理:定期删除策略每隔hz秒执行一次抽样扫描,主动清理一部分过期key,减少内存占用;
  2. 访问触发清理:客户端访问某个key时,惰性删除策略触发,检查该key是否过期,过期则立即删除;
  3. 内存兜底清理:当Redis内存达到maxmemory阈值时,新写操作触发内存淘汰机制,根据预设策略淘汰key(优先淘汰过期key,不足时淘汰未过期key),腾出内存空间。

举个例子:一个设置了24小时过期的缓存key,可能在3种情况下被删除:

  • 24小时后,被定期删除的抽样扫描命中并删除;
  • 24小时后,客户端访问该key,被惰性删除检查并删除;
  • 24小时内,Redis内存满了,该key被内存淘汰机制选中并删除。

# 四、实战配置优化:不同业务场景的最优方案

了解了三种策略的逻辑后,核心是根据业务场景配置合适的参数,避免出现“内存泄漏”或“性能波动”问题。下面给出不同场景的配置建议:

# 1. 通用缓存场景(如电商商品缓存、接口缓存)

核心需求:兼顾性能和内存利用率,优先保留热点数据,避免核心缓存被淘汰。

推荐配置:


# 设置内存上限(根据服务器内存配置,如8GB服务器设置为6GB)
maxmemory 6gb
# 淘汰策略:从所有key中淘汰最近最少使用的key(精准保留热点)
maxmemory-policy allkeys-lfu
# 提高定期删除频率(每秒15次,平衡CPU和清理效率)
hz 15
# 内存淘汰抽样数量(增加抽样数,提升淘汰精准度)
maxmemory-samples 10
1
2
3
4
5
6
7
8
9

# 2. 核心数据缓存场景(如用户登录状态、订单信息)

核心需求:不允许核心未过期数据被淘汰,仅清理过期缓存。

推荐配置:


maxmemory 4gb
# 仅淘汰设置了过期时间的key中,最近最少使用的(保护未过期核心数据)
maxmemory-policy volatile-lfu
# 适当提高定期删除频率,及时清理过期缓存
hz 20
maxmemory-samples 10
1
2
3
4
5
6
7

# 3. 临时数据场景(如验证码、临时会话)

核心需求:临时数据过期后及时清理,内存满时可随机淘汰。

推荐配置:


maxmemory 2gb
# 仅从过期key中随机淘汰(临时数据无需区分访问频率)
maxmemory-policy volatile-random
# 定期删除频率适中
hz 10
maxmemory-samples 5
1
2
3
4
5
6
7

# 4. 不允许数据丢失场景(如金融交易记录缓存)

核心需求:禁止淘汰未过期数据,内存满时拒绝写操作,手动处理。

推荐配置:


maxmemory 8gb
# 不淘汰任何key,内存满时拒绝写操作
maxmemory-policy noeviction
# 提高定期删除频率,尽量及时清理过期key
hz 25
maxmemory-samples 10
1
2
3
4
5
6
7

# 五、常见坑点与避坑指南

在实际使用中,很多问题都是由于对过期删除策略理解不深导致的。下面总结4个常见坑点及避坑方法:

# 坑1:设置了expire,但key依然长期存在

原因:该key长期未被访问(惰性删除未触发),且未被定期删除的抽样扫描命中。

避坑方法:

  • 适当提高hz参数(如从10改为15),增加定期删除频率;
  • 对重要的过期key,可通过定时任务主动扫描并删除(如使用Redis的scan命令遍历过期key);
  • 避免设置过长的过期时间,尽量按业务需求精准设置TTL。

# 坑2:Redis突然响应变慢,CPU占用飙升

原因:hz参数设置过高(如50),导致定期删除任务占用过多CPU;或内存满后,大量淘汰操作触发CPU密集型计算。

避坑方法:

  • hz参数不宜超过25(默认10),需根据CPU性能调整;
  • 提前监控Redis内存使用,避免内存达到maxmemory阈值(可设置告警);
  • 选择合适的淘汰策略(如LFU比LRU更精准,减少频繁淘汰)。

# 坑3:核心未过期key被淘汰,导致业务异常

原因:使用了allkeys-*系列淘汰策略,且内存满时,核心key被判定为“低频使用”或“随机选中”。

避坑方法:

  • 核心数据key不设置过期时间,使用volatile-*系列淘汰策略(仅淘汰过期key);
  • 适当增大maxmemory阈值,避免频繁触发淘汰机制;
  • 对核心key,可通过“定期访问”的方式维持其“热点”状态(如定时执行get操作)。

# 坑4:认为“expire设置后,key一定会在到期时删除”

原因:对Redis过期删除的“非精确性”认知不足,误将Redis的expire当作“精确过期”。

避坑方法:

  • 明确Redis过期删除是“最终一致性”,而非“强一致性”;
  • 如果业务需要“精确过期”(如定时任务触发),建议使用专门的定时任务组件(如Quartz、XXL-Job),而非依赖Redis的expire;
  • 对过期时间敏感的业务,可在应用层增加“二次检查”(如获取key后,检查是否过期,过期则重新生成)。

# 六、总结:Redis过期删除的核心逻辑

Redis的过期删除策略,本质是“在性能和内存之间寻找平衡”的设计艺术。三种策略的核心价值可总结为:

  • 惰性删除:保证CPU高效,避免主动消耗;
  • 定期删除:主动清理部分过期key,减少内存泄漏风险;
  • 内存淘汰:内存安全的最后兜底,保证Redis不崩溃。
编辑 (opens new window)
#Redis过期删除策略
上次更新: 2026/01/21, 19:29:14
Redis IO多路复用
Redis Bitmap

← Redis IO多路复用 Redis Bitmap→

最近更新
01
订单超时取消
01-21
02
双 Token 登录
01-21
03
长短链接跳转
01-21
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式