Redis过期删除策略和内存淘汰策略

过期删除策略

定时删除:在设置 key 的过期时间时,同时创建一个定时事件,当时间到达时,由事件处理器自动执行 key 的删除操作。

  • 优点:可以保证过期的key可以被快速删除,释放内存空间
  • 缺点:在过期键比较多的情况下,会占用大量的CPU时间

惰性删除: 不主动删除过期键,每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。

  • 优点:对CPU时间友好
  • 缺点:过期键占用的内存不会及时释放,造成了一定的内存浪费

定期删除:每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。

优点:通过限制删除的时长和频率,减少因为删除对cpu的占用,同时也能删除一部分过期键释放内存

缺点:

  • 内存清理没有定时删除好,同时没有惰性删除使用的资源少
  • 难以确定删除操作执行的时长和频率,如果执行的太频繁,和定时删除一样;如果执行的太少,又和惰性删除一样,占用的key不能及时释放

如何判断key已经过期

typedef struct redisDb { 
    dict *dict; /* 数据库键空间,存放着所有的键值对 */ 
    dict *expires; /* 键的过期时间 */ .... 
} redisDb;

过期字典数据结构结构如下:

过期字典的 key 是一个指针,指向某个键对象;

过期字典的 value 是一个 long long 类型的整数,这个整数保存了 key 的过期时间;

 

判断策略 

字典实际上是哈希表,哈希表的最大好处就是让我们可以用 O(1) 的时间复杂度来快速查找。

当我们查询一个 key 时,Redis 首先检查该 key 是否存在于过期字典中:

如果不在,则正常读取键值;

如果存在,则会获取该 key 的过期时间,然后与当前系统时间进行比对,如果比系统时间大,那就没有过期,否则判定该 key 已过期。 

Redis过期键删除策略是什么 

 Redis采用的是 惰性删除+定期删除 这两种策略配合使用

详细说说 Redis 的定期删除的流程:

  1. 从过期字典中随机抽取 20 个 key;
  2. 检查这 20 个 key 是否过期,并删除已过期的 key;
  3. 如果本轮检查的已过期 key 的数量,超过 5 个(20/4),也就是「已过期 key 的数量」占比「随机抽取 key 的数量」大于 25%,则继续重复步骤 1;如果已过期的 key 比例小于 25%,则停止继续删除过期 key,然后等待下一轮再检查。

 内存淘汰策略

noevction:不淘汰任何数据,如果运行内存超过了最大设置内存,会不允许写入

volatile:针对过期键

lru:淘汰最久未访问到的数据

lfu:淘汰使用频率最少的数据

random:随机淘汰

ttl:淘汰最久的过期键

allkeys:针对所有键

lru:淘汰最久未访问到的数据

lfu:淘汰使用频率最少的数据

random:随机淘汰

Redis的LRU算法

最近最久未使用算法:记录了每个key的最近访问时间,每次淘汰最久没有访问到的key,但是redis的lru不是标准的,做了优化

优化:

  • 标准lru需要维护双链表,开销很大,所以redis采用的是近似LRU算法
  • 具体的是每次随机采样n个key,默认值是5,然后按照时间戳淘汰最久的那个。如果淘汰后内存还是不足继续随机采样淘汰。在3。0之后,redis LRU还维护了淘汰池,池中的数据按照访问时间进行排序。第一次随机选取的key都会放入池中,每次淘汰池中最久访问的key。
  • 随后每次选取的key只有空闲时间(指的是没有访问到的时候)大于池中空间时间最小的key,才能放入其中。当池子装满了,需要新的key放入的时候,就将池子中最大的key淘汰

Redis的LFU算法

LRU 算法有一个问题,无法解决缓存污染问题,比如应用一次读取了大量的数据,而这些数据只会被读取这一次,那么这些数据会留存在 Redis 缓存中很长一段时间,造成缓存污染。

所以, LFU 算法会记录每个数据的访问次数。当一个数据被再次访问时,就会增加该数据的访问次数。这样就解决了偶尔被访问一次之后,数据留存在缓存中很长一段时间的问题,相比于 LRU 算法也更合理一些。 

LFU 算法相比于 LRU 算法的实现,多记录了「数据的访问频次」的信息。Redis 对象的结构如下:

typedef struct redisObject { 
    ... // 24 bits,
    用于记录对象的访问信息 unsigned lru:24; 
    ... 
} 
robj;

Redis 对象头中的 lru 字段,在 LRU 算法下和 LFU 算法下使用方式并不相同。

  • 在 LRU 算法中,Redis 对象头的 24 bits 的 lru 字段是用来记录 key 的访问时间戳,因此在 LRU 模式下,Redis可以根据对象头中的 lru 字段记录的值,来比较最后一次 key 的访问时间长,从而淘汰最久未被使用的 key。
  • 在 LFU 算法中,Redis对象头的 24 bits 的 lru 字段被分成两段来存储,高 16bit 存储 ldt(Last Decrement Time),低 8bit 存储 logc(Logistic Counter)。

 

  • ldt 是用来记录 key 的访问时间戳;
  • logc 是用来记录 key 的访问频次,它的值越小表示使用频率越低,越容易淘汰,每个新加入的 key 的logc 初始值为 5。

注意,logc 并不是单纯的访问次数,而是访问频次(访问频率),因为 logc 会随时间推移而衰减的。

在每次 key 被访问时,会先对 logc 做一个衰减操作,衰减的值跟前后访问时间的差距有关系,如果上一次访问的时间与这一次访问的时间差距很大,那么衰减的值就越大,这样实现的 LFU 算法是根据访问频率来淘汰数据的,而不只是访问次数。访问频率需要考虑 key 的访问是多长时间段内发生的。key 的先前访问距离当前时间越长,那么这个 key 的访问频率相应地也就会降低,这样被淘汰的概率也会更大。

对 logc 做完衰减操作后,就开始对 logc 进行增加操作,增加操作并不是单纯的 + 1,而是根据概率增加,如果 logc 越大的 key,它的 logc 就越难再增加。 

所以,Redis 在访问 key 时,对于 logc 是这样变化的: 先按照上次访问距离当前的时长,来对 logc 进行衰减; 然后,再按照一定概率增加 logc 的值 

<think>好的,我现在需要详细思考如何回答用户关于Redis删除策略内存淘汰机制的问题。用户希望了解它们的工作原理及配置方法,还可能需要配置示例。根据提供的引用内容,我需要先理清这两个概念的区别联系。 首先,根据引用[1][2],Redis过期策略包括惰性删除定期删除,而内存淘汰机制是在内存达到maxmemory时触发的策略。这两部分需要分开解释,但也要说明它们的关联。 接下来,我需要明确每个部分的具体内容。惰性删除是在访问键时检查过期时间,如果过期删除。定期删除则是每隔一段时间随机抽取一些键检查并删除过期的。这部分需要详细说明两种策略的优缺点,比如惰性删除节省CPU但可能导致内存浪费,定期删除则是一种折中。 然后是内存淘汰机制,引用[3][4]提到当内存达到上限时,Redis会根据配置的策略淘汰数据。常见的策略有volatile-lru、allkeys-lru、volatile-ttl等。需要逐一解释这些策略的区别,比如针对带过期时间的键还是所有键,使用LRU还是TTL等。 配置方法方面,用户可能需要知道如何设置maxmemory选择淘汰策略。例如,在redis.conf中设置maxmemory参数,并通过maxmemory-policy指定策略。配置示例部分可以举几个例子,比如设置最大内存为1GB,使用volatile-lru策略。 还要注意引用文献的正确标注,在回答中适当的位置添加引用标识,比如在提到惰性删除定期删除时引用[1][2],在内存淘汰策略部分引用[3][4]。 另外,用户可能需要实际操作的指导,比如如何查看当前配置,如何通过CONFIG SET命令动态调整策略。Java代码示例部分可以参考引用[4],展示使用Jedis库连接Redis并配置策略的例子,但需要确保代码正确且符合用户需求。 最后,生成的相关问题需要与主题紧密相关,帮助用户进一步探索。例如,如何选择合适的内存淘汰策略,不同策略的优缺点比较,或者如何监控Redis内存使用情况。 总结回答结构:先分开讲解删除策略内存淘汰机制,再说明配置方法,最后给出示例注意事项。确保每个部分清晰,并且引用正确。</think>### Redis删除策略内存淘汰机制详解 #### 一、Redis删除策略过期键处理) Redis通过**惰性删除****定期删除**两种策略管理过期键,确保内存资源高效利用。 1. **惰性删除** 当客户端访问某个键时,Redis会检查其过期时间。若已过期则直接删除,否则正常返回数据。 - **优点**:对CPU友好,仅在访问时触发检查。 - **缺点**:可能导致内存浪费(未访问的过期键长期驻留)[^1]。 2. **定期删除** Redis每隔一段时间(默认100ms)随机抽取部分键检查过期状态,删除其中已过期的键。 - **抽样数量**:由配置文件中的`hz`参数控制,默认10次/秒。 - **优点**:减少内存泄漏风险。 - **缺点**:需平衡CPU与内存效率[^2]。 #### 二、内存淘汰机制(Eviction Policy) 当内存使用达到`maxmemory`阈值时,Redis根据配置的淘汰策略释放空间。以下是常见策略: | 策略 | 描述 | |---------------------|--------------------------------------------------------------------| | `volatile-lru` | 从**设置过期时间的键**中,淘汰最近最少使用的键(LRU算法)[^3]。 | | `allkeys-lru` | 从**所有键**中淘汰最近最少使用的键。 | | `volatile-ttl` | 从**设置过期时间的键**中,淘汰剩余存活时间最短的键(TTL优先)[^3]。 | | `volatile-random` | 随机淘汰**设置过期时间的键**。 | | `allkeys-random` | 随机淘汰**任意键**。 | | `noeviction`(默认) | 禁止写入新数据,仅返回错误(需手动干预释放内存)[^3]。 | #### 三、配置方法及示例 1. **设置最大内存淘汰策略** 修改`redis.conf`文件或通过命令行动态配置: ```bash # 设置最大内存为1GB config set maxmemory 1gb # 使用volatile-lru策略 config set maxmemory-policy volatile-lru ``` 2. **Java示例(Jedis库)** ```java Jedis jedis = new Jedis("localhost"); // 设置最大内存并选择策略 jedis.configSet("maxmemory", "1gb"); jedis.configSet("maxmemory-policy", "allkeys-lru"); ``` 此配置适用于缓存场景,优先保留高频访问数据[^4]。 3. **查看当前配置** ```bash redis-cli config get maxmemory redis-cli config get maxmemory-policy ``` #### 四、注意事项 - **策略选择**:若数据均有过期时间,优先用`volatile-*`策略;若需全量数据管理,选择`allkeys-*`。 - **监控指标**:通过`INFO memory`命令关注`used_memory``evicted_keys`,评估淘汰效率[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值