Redis的数据清理机制

Redis的数据清理机制

Redis数据清理机制主要分为两大核心体系:

  • 过期键删除策略:针对设置了过期时间的Key,负责在Key过期后进行自动清理,属于"到时间清垃圾"的被动与主动结合型清理;
  • 内存淘汰策略:在Redis占用内存达到预设上限时,通过主动淘汰部分Key腾出内存空间,属于"内存不够强制腾位置"的应急型清理;

二者既相互独立又协同互补,共同保障Redis在内存资源有限的情况下高效运行,既避免了过期数据长期占用内存导致的资源浪费,也防止了内存溢出引发的服务异常。

Redis过期键删除策略

什么是Redis的过期数据

Redis作为一种内存级数据库,其所有数据均存放在内存中,对于内存中的数据,我们可以通过TTL指令获取其存活状态,而TTL指令返回的值主要分为三种情况,分别对应数据的不同存活状态。

第一种情况是返回正数,该数值代表该数据在内存中还能存活的时间,也就是数据的剩余过期时间;

第二种情况是返回-1,代表该数据是永久有效的,未设置任何过期时间;

第三种情况是返回-2,代表该数据是已经过期的数据、或被手动删除的数据、或未定义的不存在的数据。

针对设置了EXPIRE/TTL过期时间的Key,Redis提供了三种明确的删除策略,每种策略对应不同的删除时机,也各有优劣。

定时删除策略

定时删除策略的删除时机核心是"Key的过期时间一到达,立即执行删除"。

具体而言,当给Key设置过期时间后,Redis会立即为该Key创建一个定时器,一旦过期时间节点到来,定时器就会触发,立即执行对该Key的删除操作。

优点是能够最大限度节约内存资源,只要Key过期就会被及时删除,快速释放不必要的内存占用,不会出现过期数据滞留内存的情况;

缺点是会给CPU带来较大压力,因为无论当前CPU是否繁忙,只要Key到达过期时间,就必须执行删除操作,这种强制触发的删除会占用CPU资源,进而影响Redis服务器的响应时间和整体性能。

综上,定时删除策略本质上是用处理器性能换取存储空间,也就是典型的"时间换空间"策略,由于其对CPU的过高消耗,在实际生产中基本不被采用。

惰性删除策略

惰性删除策略的删除时机核心是"过期不主动删除,访问时再判断删除"。

具体而言,即使Key已经到达预设的过期时间,Redis也不会主动对其进行任何处理,该Key会一直存在于内存中,直到下次客户端访问该Key(执行get指令)时,才会对其过期状态进行判断:如果Key未过期,则正常返回数据;如果Key已过期,则立即删除该Key,并返回数据不存在的响应。

需要特别注意的是,在执行get指令时,Redis会隐性地先执行expireIfNeeded()方法,以此判断数据是否已经过期。

优点是能最大限度节约CPU性能,无需后台线程持续监控所有过期Key,也不会在Key过期时强制执行删除操作,仅在有实际访问请求时才进行判断和删除,避免了无效的CPU消耗;

缺点是会给内存带来较大压力,若某个过期Key长时间不被访问,就会一直占用内存资源,导致内存利用率下降,甚至引发内存泄露问题。

综上,惰性删除策略本质上是用存储空间换取处理器性能,也就是"空间换时间"策略,能够有效降低CPU负担,但需配合其他策略缓解内存压力。

定期删除策略

定期删除策略的删除时机核心是"按固定周期,周期性地抽样检查并删除过期Key",是一种兼顾CPU和内存的折中策略。

具体实现逻辑如下:Redis启动服务器并完成初始化时,会读取配置文件中的hz参数(该参数用于控制定期删除的频率),其默认值为10,意味着Redis每秒会执行10次activeExpireCycle()方法,对每个Redis库(Redis默认有16个库,编号0-15)逐一进行检测,每次执行该方法的耗时被严格控制在250ms/10,即每次执行不超过25ms,避免阻塞主线程。在对某个Redis库进行检测时,会随机挑选w个Key进行过期检查(w的取值为ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP属性的默认值),检查规则为:如果被检测的Key已经超时,则立即删除该Key;如果一轮检测中,删除的Key数量超过了本次检测Key总数的25%,则继续对该Redis库循环执行抽样检测;如果一轮检测中,删除的Key数量≤本次检测Key总数的25%,则停止对该Redis库的检测,转而检查下一个Redis库,按0-15的顺序循环进行。

总结来看,定期删除策略的核心是周期轮询Redis库中的时效性数据,采用随机抽取的策略,同时利用"过期数据占比"的方式动态控制删除频度------当某个库中过期数据较多时(删除占比超过25%),会加大该库的检测力度,确保尽快清理部分过期数据;当过期数据较少时,则切换到下一个库,避免占用过多CPU资源。这种策略很好地平衡了内存和CPU的压力,既不会像惰性删除那样导致内存压力过大,也不会像定时删除那样给CPU带来过重负担,同时其检测频度可通过调整hz参数自定义设置,能够根据实际业务场景和服务器性能灵活适配。

综合三种过期键删除策略的优劣,Redis最终选择"惰性删除+定期删除"的组合方案:日常依靠惰性删除节省CPU资源,避免无效的后台扫描;后台通过定期删除按固定周期抽样清理过期Key,缓解惰性删除带来的内存浪费和内存泄露风险,实现了CPU与内存资源的动态平衡,既保证了Redis服务器的响应性能,又能有效控制内存占用。

Redis内存淘汰策略

当Redis占用的内存达到预设的maxmemory最大内存限制时,再执行写入类命令(如set、hset等)就会触发内存淘汰机制,Redis会按照预设的淘汰策略,删除一部分Key以腾出足够的内存空间,确保新数据能够正常写入;若未配置maxmemory参数,Redis会无限制占用服务器的物理内存,不会触发任何内存淘汰操作,严重时可能导致服务器内存耗尽,引发系统异常。除了maxmemory参数外,与内存淘汰相关的核心配置还有maxmemory-policy,该参数用于指定内存满时的具体淘汰策略,目前Redis共提供了六大淘汰策略,可分为三大类,分别适用于不同的业务场景。

放弃数据驱逐

第一类是放弃数据驱逐策略,即noeviction策略。这也是Redis的默认淘汰策略,其核心逻辑是当内存达到上限后,拒绝所有写入命令,此时写入操作会报错,但读命令(如get、hget等)可以正常执行;这种策略适用于数据绝对不能丢失的业务场景,如金融交易、订单存储等,这类业务不允许通过删除任何数据来腾出内存,宁愿拒绝新数据写入,也不能牺牲已存储的数据安全性。

检测全库数据

第二类是检测全库数据,从所有Key中淘汰。这类策略不区分Key是否设置了过期时间,所有Key均参与淘汰,也是缓存场景中最常用的一类策略,具体包括两种:allkeys-lru策略和allkeys-lfu策略。其中allkeys-lru策略是最常用的淘汰策略,其核心是淘汰最近最少使用的Key,通过判断Key的访问时间,优先删除长时间未被访问的冷数据;allkeys-lfu策略是Redis4.0版本新增的策略,核心是淘汰最不经常使用的Key,通过统计Key的访问频次,优先删除访问次数最少的Key,相比LRU策略,LFU更能避免"偶尔访问的冷数据常驻内存"的问题,适用范围更广泛。

检测易失数据

第三类是检测易失数据,只从带过期时间的Key中淘汰。这类策略仅在设置了TTL过期时间的Key中选择淘汰对象,永久Key(未设置过期时间的Key)永远不会被删除,具体包括四种策略:volatile-lru策略、volatile-lfu策略、volatile-random策略和volatile-ttl策略。其中volatile-lru策略是在所有带过期时间的Key中,淘汰最近最少使用的Key;volatile-lfu策略是在所有带过期时间的Key中,淘汰最不经常使用的Key;volatile-random策略则是随机删除带过期时间的Key,逻辑简单粗暴,不考虑Key的冷热程度;volatile-ttl策略则是优先删除剩余过期时间最短的Key,适用于希望优先清理即将过期的临时数据的业务场景。

综上,Redis的数据删除与内存淘汰策略是一个系统性的设计,通过"惰性删除+定期删除"的组合实现过期数据的高效清理,明确了不同策略的删除时机,平衡了CPU与内存资源;通过六大内存淘汰策略应对内存不足的场景,兼顾了CPU资源、内存利用率和服务性能。在实际应用中,需结合业务场景合理配置过期时间和内存淘汰策略,熟练掌握相关配置命令和注意事项,才能充分发挥Redis的高性能优势,保障服务的稳定运行。

相关推荐
oradh1 小时前
Oracle数据库服务器端编程介绍
数据库·oracle·oracle基础·oracle数据库基础
2401_846339562 小时前
Vue 3 中集成 Three.js 场景的完整实现指南
jvm·数据库·python
日取其半万世不竭2 小时前
Excalidraw 自建部署指南:白板协作工具完全私有化
服务器·网络·数据库
这个DBA有点耶2 小时前
联合索引的顺序:写错等于白建(最左前缀+范围条件+覆盖索引详解)
数据库·代码规范
2301_775639892 小时前
Golang怎么写TODO待办应用_Golang TODO应用教程【深入】
jvm·数据库·python
胖头鱼的鱼缸(尹海文)2 小时前
数据库管理-第423期 Oracle AI DB 23.26.2新特性一览(20260504)
数据库·人工智能·oracle
iuvtsrt2 小时前
WordPress 分页失效的常见原因与正确实现方案
jvm·数据库·python
木井巳2 小时前
【MySQL数据库】数据库操作及数据类型
数据库·mysql·adb
阿维的博客日记2 小时前
Redis 和 Caffeine 构建的多级缓存,如何保持数据一致性?
数据库·redis·缓存