开发者

Redis Key过期策略详解

目录
  • 概述
  • Redis Key过期策略
    • 定时删除
    • 惰性删除
    • 定期删除
      • 「惰性删除」 + 「定javascript期删除」策略
  • Redis采用的策略
    • 持久化对过期策略的处理
      • RDB对过期策略的处理
        • AOF对过期策略的处理
          • 复制场景下的特殊处理
            • 数据一致性风险
            • 总结对比表

              概述

              Redis的Key过期策略是其内存管理系统的核心组成部分,主要包括「被动过期」、「主动过期」和「内存淘汰」三个机制。

              本文将着重讲解Redis的Key过期策略,从实现原理、工作流程到最佳实践进行全面解析。

              Redis Key过期策略

              Redis采用多策略组合的方式管理Key过期,主要包括三种机制:定时删除惰性删除定期删除

              下面将分别对这三种key过期机制进行实现原理、优缺点、Redis采用的策略、以及RDB/AOF对不同过期策略的处理上的讲解。

              定时删除

              实现原理:  

              • 在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key过期时间来临时,对key进行删除。

              优点: 

              • 内存友好,可以及时清除过期的数据

              缺点:  

              • cpu不友好,会占用大量cpu资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。  
              • 定时器的创建耗时,若为每一个设置过期时间key创建一个定时器(将会产生大量的定时器),性能影响严重。  
              • Redis未采用此策略。

              惰性删除

              实现原理:  

              • 只有当访问key时,才会判断该key是否已经是过期(触发expireIfNeeded()检查),过期则清除。  

              优点:  

              • cpu友好,零额外开销  
              • 删除操作精准 

              缺点:  

              • 内存泄漏风险:不访问的过期Key永远存在。
              • 极端情况下可能会出现大量过期key没有再被访问,从而不会被删除,占用大量无效内存。

              定期删除

              实现原理:  

              每隔一定时间,扫描一定数量在数据库中expires字典(过期字典)中一定数量的key,并清除其中已过期的key。

              工作机制  

              • 周期性执行activeExpireCycle()  
              • 随机抽取部分过期字典中的Key检查  
              • 采用自适应算法控制CPU消耗

              核心算法

              def activeExpireCycle():
                 while True:
                  # 每次随机检vytYwNz查20个Key
                  for i in range(20):
                      key = random.choice(expires_dict)
                      if key.expire_time < now:
                          delete_key(key)
                  # 动态退出条件
                  if checked_keys < 20*25%:  # 过期率<25%则退出
                      break

              优点:  

              • 该策略是前两者的一个折中方案,通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得cpu和内存资源达到最优的平衡效果。  
              • 通过限制删除的时长和频率,来减少删除操作对cpu时间的占用 — 解vytYwNz决「定时删除」的缺点  
              • 定期删除过期key — 解决「惰性删除」的缺点

              缺点:  

              • 在内存友好方面,不如「定时删除」。  
              • 在cpu时间友好方面,不如「惰性删除」。

              难点:  

              • 合理设置操作的执行时长(每次删除执行多长时间)和执行频率(每隔多久时间做一次删除),这个需要各个业务场景根据实际情况进行动态调整。

              Redis采用的策略

              Redis采用**「惰性删除」** + **「定期删除」**的混合策略

              • 混合策略架构

              Redis Key过期策略详解

              「惰性删除」 + 「定期删除」策略

              惰性删除流程

              • 在进行get或setnx等操作时,先检查key是否过期。  
              • 若过期,则删除key,然后执行相应操作。  
              • 若没过期,则直接执行相应操作。

              定期删除流程

              1.遍历每个数据库(即redis.conf中配置的“database”数量,默认为16)。  

              2.检查当前库中指定个数key(默认是每个库检查20个key,相当于循环执行20次)。   

              • a. 如果当前库中没有一个key设置了过期时间,直接执行下一个库的遍历。   
              • b. 随机获取一个设置了过期时间的key,检查key是否过期,如过期,删除key。   
              • c. 判断定期删除操作是否已经达到指定时长,若达到,则退出定期删除。 

              注意事项

              • 定期删除,在程序中有一个全局变量current_db来记录下一个将要便利的库。
              • 假设有16个库,这一次定期删除遍历了10个,那此时的current_db就是11,下一次定期删除就从第 11库开始遍历。

              持久化对过期策略的处理

              RDB对过期策略的处理

              说明:过期key对RDB没有影响 

              原理:  

              1.从内存持久化数据到RDB文件

              主节点  

              • a. 生成RDB快照时会主动过滤已过期的Key。  
              • b. 仅持久化未过期的Key-value对。 

              从节点  

              • a. 即使接收到的RDB文件包含未实际过期的Key。  
              • b. 加载时仍会执行过期检查(双重保障)。

              关键源码

              // rdb.c 源码关键逻辑
              int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime) {
                  if (expiretime != -1 && expiretime < mstime()) {
                      return 0; // 跳过已过期的Key
                  }
                  // 保存未过期的Key...
              }

              2.从RDB文件恢复数据到内存 

              全量加载流http://www.devze.com程:  

              • a. 清空当前数据库  
              • b. 解析RDB文件内容  
              • c. 对每个Key执行expireIfNeeded()检查  
              • c. 仅加载未过期的Key

              AOF对过期策略的处理

              说明:过期key对AOF没有影响 

              原理: 

              1.从内存持久化数据到AOF文件

              正常AOF追加模式  

              • a. AOF会将对应Key的操作一并写入文件中
              操作类型AOF记录内容
              Key设置过期PEXPIREAT key timestamp
              Key自然过期DEL key(实际由propagateExpire()生成)
              手动删除直接记录DEL key

              AOF重写时  

              • a. 重写时,会先判断Key是否过期,已过期的Key不会重写到AOF文件

              与RDB的区别  

              • a. 仍会记录Key的过期时间(PEXPIREAT)  
              • b. 但实际数据只有未过期Key会被写入

              复制场景下的特殊处理

              主从复制流程

              节点角色过期Key处理方式
              主节点惰性删除+定期删除
              从节点仅依赖主节点的DEL同步

              关键机制:  

              • a. 主节点过期后会向从节点传播DEL命令  
              • b. 从节点不会主动删除Key(即使已过期)  
              • c. 3.2+版本引入replica-ignore-expire配置(默认关闭)

              数据一致性风险

              场景:  

              • Key在主节点过期但尚未同步到从节点  
              • 此时主节点宕机,从节点晋升后:&emjavascriptsp; 
              • RDB加载:会重新检查过期  
              • AOF回放:依赖记录的DEL命令

              总结对比表

              持久化方式生成时处理加载时处理复制传播
              RDB过滤过期Key二次检查全量同步
              AOF记录DEL命令按序重放增量同步
              混合模式RDB部分过滤组合加载混合同步

              以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

              0

              上一篇:

              下一篇:

              精彩评论

              暂无评论...
              验证码 换一张
              取 消

              最新数据库

              数据库排行榜