> 技术文档 > Redis过期数据清理大揭秘:双剑合璧的惰性与定期删除策略

Redis过期数据清理大揭秘:双剑合璧的惰性与定期删除策略


💡 一句话真相:Redis的过期清理就像\"超市临期商品管理\"🛒——惰性删除是顾客结账时检查保质期,定期删除是店员定时巡检货架!


🔧 一、为什么需要数据过期?内存管理的生死线

真实案例:某社交App因未设过期时间,3000万用户会话数据永久堆积,导致:

  • 内存爆满,服务崩溃 💥
  • 从Redis恢复数据耗时3小时 ⏳
  • 直接损失800万订单! 💸

Redis内存警告:

127.0.0.1:6379> info memory used_memory_human:6.0G # 内存使用量 maxmemory_human:8.0G # 内存上限 mem_fragmentation_ratio:1.8 # 碎片率过高! 

🛠️ 二、过期策略双核心:惰性删除 + 定期删除

策略 触发时机 优点 缺点 惰性删除 访问Key时检查 零额外CPU消耗 冷数据长期不释放 定期删除 定时随机扫描 主动释放内存 可能短时阻塞

#mermaid-svg-9aIFULiubc3EhGeM {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-9aIFULiubc3EhGeM .error-icon{fill:#552222;}#mermaid-svg-9aIFULiubc3EhGeM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9aIFULiubc3EhGeM .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-9aIFULiubc3EhGeM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9aIFULiubc3EhGeM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9aIFULiubc3EhGeM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9aIFULiubc3EhGeM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9aIFULiubc3EhGeM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9aIFULiubc3EhGeM .marker.cross{stroke:#333333;}#mermaid-svg-9aIFULiubc3EhGeM svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9aIFULiubc3EhGeM .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9aIFULiubc3EhGeM .cluster-label text{fill:#333;}#mermaid-svg-9aIFULiubc3EhGeM .cluster-label span{color:#333;}#mermaid-svg-9aIFULiubc3EhGeM .label text,#mermaid-svg-9aIFULiubc3EhGeM span{fill:#333;color:#333;}#mermaid-svg-9aIFULiubc3EhGeM .node rect,#mermaid-svg-9aIFULiubc3EhGeM .node circle,#mermaid-svg-9aIFULiubc3EhGeM .node ellipse,#mermaid-svg-9aIFULiubc3EhGeM .node polygon,#mermaid-svg-9aIFULiubc3EhGeM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9aIFULiubc3EhGeM .node .label{text-align:center;}#mermaid-svg-9aIFULiubc3EhGeM .node.clickable{cursor:pointer;}#mermaid-svg-9aIFULiubc3EhGeM .arrowheadPath{fill:#333333;}#mermaid-svg-9aIFULiubc3EhGeM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9aIFULiubc3EhGeM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9aIFULiubc3EhGeM .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-9aIFULiubc3EhGeM .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-9aIFULiubc3EhGeM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9aIFULiubc3EhGeM .cluster text{fill:#333;}#mermaid-svg-9aIFULiubc3EhGeM .cluster span{color:#333;}#mermaid-svg-9aIFULiubc3EhGeM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9aIFULiubc3EhGeM :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}写入数据设置过期时间加入过期字典永久存储惰性删除定期删除


🔍 三、惰性删除:精准狙击的\"特工\"

1. 执行流程

#mermaid-svg-gcCL7B6NuXIDqMIb {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb .error-icon{fill:#552222;}#mermaid-svg-gcCL7B6NuXIDqMIb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gcCL7B6NuXIDqMIb .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-gcCL7B6NuXIDqMIb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gcCL7B6NuXIDqMIb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gcCL7B6NuXIDqMIb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gcCL7B6NuXIDqMIb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gcCL7B6NuXIDqMIb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gcCL7B6NuXIDqMIb .marker.cross{stroke:#333333;}#mermaid-svg-gcCL7B6NuXIDqMIb svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gcCL7B6NuXIDqMIb .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gcCL7B6NuXIDqMIb text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-gcCL7B6NuXIDqMIb .actor-line{stroke:grey;}#mermaid-svg-gcCL7B6NuXIDqMIb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb .sequenceNumber{fill:white;}#mermaid-svg-gcCL7B6NuXIDqMIb #sequencenumber{fill:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb .messageText{fill:#333;stroke:#333;}#mermaid-svg-gcCL7B6NuXIDqMIb .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gcCL7B6NuXIDqMIb .labelText,#mermaid-svg-gcCL7B6NuXIDqMIb .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-gcCL7B6NuXIDqMIb .loopText,#mermaid-svg-gcCL7B6NuXIDqMIb .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-gcCL7B6NuXIDqMIb .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gcCL7B6NuXIDqMIb .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-gcCL7B6NuXIDqMIb .noteText,#mermaid-svg-gcCL7B6NuXIDqMIb .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-gcCL7B6NuXIDqMIb .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gcCL7B6NuXIDqMIb .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gcCL7B6NuXIDqMIb .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gcCL7B6NuXIDqMIb .actorPopupMenu{position:absolute;}#mermaid-svg-gcCL7B6NuXIDqMIb .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-gcCL7B6NuXIDqMIb .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gcCL7B6NuXIDqMIb .actor-man circle,#mermaid-svg-gcCL7B6NuXIDqMIb line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-gcCL7B6NuXIDqMIb :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}客户端Redis过期字典GET user:1001:session检查key是否过期?已过期(返回1)删除key(nil)客户端Redis过期字典

2. 源码实现(C语言伪代码)
int expireIfNeeded(redisDb *db, robj *key) { if (!keyIsExpired(db,key)) return 0; // 未过期  deleteKey(db,key);  // 执行删除  return 1; } robj *lookupKeyRead(redisDb *db, robj *key) { if (expireIfNeeded(db,key) == 1) { // 检查过期  return NULL; // 已删除返回空  } return lookupKey(db,key); } 
3. 实战风险:僵尸Key问题

场景:

# 大量已过期但永不访问的Key SET access_log:20230101 \"big_data\" EX 86400 

后果:内存被无形占用,可用空间持续减少!


⏰ 四、定期删除:主动出击的\"巡逻队\"

1. 三层渐进式扫描

Redis过期数据清理大揭秘:双剑合璧的惰性与定期删除策略

2. 核心算法参数
// redis.conf 配置 hz 10 // 每秒执行10次定期删除(默认) // 源码参数 #define ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP 20 // 每次扫描20个key #define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 // CPU占用≤25% 
3. 性能优化:自适应扫描
  • CPU空闲时:增加扫描频次(hz 100
  • 内存紧张时:每次扫描更多Key(可调参)

💥 五、内存耗尽时的最后防线:淘汰策略

当内存超maxmemory时触发:

策略 机制 适用场景 volatile-lru(默认) 淘汰最近最少使用的过期Key 缓存场景 allkeys-lru 淘汰所有Key中的LRU 内存不足时优先选择 volatile-ttl 淘汰剩余生存时间最短的Key 时效性敏感数据 noeviction 拒绝写入并报错 关键数据不允许丢失

配置方式:

# redis.conf maxmemory 8gb maxmemory-policy volatile-lru 

⚠️ 六、四大实战陷阱与解决方案

🚫 陷阱1:过期Key集中导致雪崩

场景:

# 同一秒设置大量Key过期 SET key1 value EX 3600 SET key2 value EX 3600 # 同时设置100万Key 

后果:3600秒后同时过期 → 定期删除压力暴增!

解决方案:

# 添加随机过期时间偏移 expire_time = 3600 + random.randint(0, 600) # 增加0-10分钟随机值 redis.setex(key, expire_time, value) 
🚫 陷阱2:大Key删除阻塞服务

案例:删除10MB的Hash Key耗时150ms → 阻塞其他请求!

优化方案:

# 异步删除(Redis 4.0+) UNLINK big_key # 非阻塞删除 # 分批次删除 HSCAN big_key 0 COUNT 100 # 分批遍历 HDEL big_key field1 field2 ... # 分批删除 
🚫 陷阱3:主从不一致

问题:主库删除过期Key后,从库可能未同步删除

解决方案:

# 开启从库主动检测(Redis 3.2+) replica-serve-stale-data no 
🚫 陷阱4:持久化导致过期复活

原理:RDB快照中的过期Key重启后重新加载

规避方法:

# 启用AOF重写时主动删除过期Key aof-rewrite-incremental-fsync yes 

💎 七、最佳配置指南

1. 生产环境推荐配置
# 内存上限(物理内存70%) maxmemory 16gb # 淘汰策略(缓存场景) maxmemory-policy volatile-lru # 定期删除频率 hz 10 # 开启异步删除 lazyfree-lazy-eviction yes 
2. 监控命令大全
# 查看过期Key数量 redis-cli info | grep expired_keys # 内存碎片率 redis-cli info | grep mem_fragmentation_ratio # 实时监控淘汰情况 redis-cli --stat 

🔧 八、总结:Redis过期数据清理三原则

  1. 双重保障:
    • 访问时检查(惰性删除)
    • 定时主动扫描(定期删除)
  2. 淘汰兜底:内存不足时按策略清理
  3. 避坑关键:
    • 分散过期时间
    • 大Key异步删除
    • 监控碎片率

Redis过期数据清理大揭秘:双剑合璧的惰性与定期删除策略

🔥 黄金口诀:

  • 冷门数据靠定期扫
  • 热点访问惰性删
  • 内存爆炸淘汰保

#Redis内核 #内存管理 #高并发架构