当前位置:首页 > 问答 > 正文

Redis里那些内存回收算法到底咋回事儿,优势又在哪儿讲讲吧

Redis作为一个内存数据库,所有数据都放在内存里,而内存是有限且宝贵的资源,当内存快要用完时,新的数据就写不进来了,这肯定不行,Redis需要一套机制,像家里的储物间一样,定期清理掉不常用的东西,腾出空间给新来的物品,这套机制就是内存回收。

Redis的内存回收,主要从两个层面来解决这个问题:一是如何判断哪些数据是“垃圾”,可以回收;二是具体在什么时机、以什么方式去回收。

Redis里那些内存回收算法到底咋回事儿,优势又在哪儿讲讲吧

第一,如何判定数据是“垃圾”?—— 回收策略

Redis提供了8种主要的策略(由maxmemory-policy配置项控制),让你根据自己应用的特性来选择,这些策略的核心思想就两点:要么淘汰过期了的数据,要么在没过期的数据里挑一些“不重要”的淘汰。

Redis里那些内存回收算法到底咋回事儿,优势又在哪儿讲讲吧

  1. 对付过期键的策略(主动清理):

    • volatile-lru:这是最常用的策略之一,它只针对那些设置了过期时间(TTL)的键,从中挑选出“最近最少使用”的淘汰,LRU算法的思想很简单:如果一个数据最近被访问过,那么它将来被访问的可能性也更大,反过来,很久没被碰过的数据,就更可能被淘汰,Redis采用了一种近似LRU的算法,并不是遍历所有键精确计算,而是通过随机采样来评估,这样在性能和效果上取得了很好的平衡。
    • volatile-lfu:这是Redis 4.0引入的更智能的策略,LFU是“最不经常使用”,它不只是看数据多久没被访问,而是统计一段时间内被访问的频率,一个键可能昨天被访问了100次,但今天一次还没访问,LRU可能会因为它“没被访问而淘汰它,但LFU会认为它是个热键而保留,这对于有“热点数据”的场景非常有效。
    • volatile-ttl:这个更直接,它只在设了过期时间的键里,优先淘汰剩余寿命最短的,反正它马上就要过期了,不如提前送它走,腾出空间。
    • volatile-random:很简单,在设了过期时间的键里,随机挑一个淘汰,这没啥智能可言,但好处是速度快,开销极小。
  2. 对付所有键的策略(迫不得已时的清理): 当上面四种策略都无法腾出足够空间时(比如所有键都没设置过期时间,或者过期键都删完了内存还是满),Redis就会动用下面这组策略,它们会在所有键(包括没设过期时间的) 中进行淘汰,这意味着你的永久数据也可能被删除,所以使用时要非常小心。

    Redis里那些内存回收算法到底咋回事儿,优势又在哪儿讲讲吧

    • allkeys-lru:和volatile-lru思路一样,但战场扩大到了全体键。
    • allkeys-lfu:同上,在全体键中运用LFU算法。
    • allkeys-random:在全体键中随机淘汰。
    • noeviction:这不算回收策略,而是“不淘汰”策略,这是默认策略,当内存不足时,所有会引起内存增长的命令(比如写命令)都会报错,读命令正常,这适用于你确信数据绝对不能丢的场景,但要求应用端能处理好写操作失败的情况。

第二,什么时候、以什么方式回收?—— 回收时机与过程

光有策略还不够,得有人去执行,Redis的回收触发方式主要有两种:

  1. 被动回收(惰性删除):当客户端尝试访问一个键时,Redis会先检查这个键是否已过期,如果过期了就立刻删除,然后返回空值,这种方式是“被动”的,好处是只在需要时才做检查,节省CPU,坏处是如果大量过期键一直不被访问,它们就会像僵尸一样长期占用内存,直到被偶然触发或主动清理。
  2. 主动回收(定期删除):Redis会定期(默认每秒10次)随机测试一批设置了过期时间的键,检查它们是否过期,过期的就删除,如果发现这批键中过期的比例很高,它会继续再抽一批,直到比例降下来,这种方式是为了弥补被动回收的不足,主动去清理“僵尸”键。
  3. 强制回收(内存达到上限时):当Redis执行一个命令,导致内存使用量超过maxmemory限制时,它会立即根据你配置的maxmemory-policy策略,淘汰掉一个或多个键,直到内存降回限制以下。

优势在哪儿?

Redis这套组合拳的优势非常明显:

  • 灵活可控:提供了8种策略,让你能根据业务数据的访问模式(是均匀访问还是有热点?)、数据重要性(哪些能丢哪些不能丢)来精细选择,比如缓存系统通常用allkeys-lru或allkeys-lfu,而会话存储可能用volatile-lru。
  • 性能与效果的平衡:没有追求绝对精确的LRU(那样CPU开销太大),而是用采样近似,在实践中被证明非常有效,保证了在高并发下的性能。
  • 多管齐下:结合了被动、主动、强制三种回收时机,既保证了日常的垃圾清理效率,又能在内存告急时果断出手,防止服务崩溃。
  • 与时俱进:引入了更智能的LFU算法,应对复杂的数据访问模式,比传统的LRU有更好的缓存命中率。

说白了,Redis的内存回收就像一个聪明的仓库管理员,他既会定期巡视清理过期商品(主动回收),也会在你要取货时发现过期就扔掉(被动回收),当仓库彻底爆满,新货进不来时,他会根据你定的规矩(回收策略),要么把最久没人买的货清掉(LRU),要么把销量最差的清掉(LFU),要么随便扔一个(Random),甚至拒绝新货入库(noeviction),这套机制确保了Redis这个“内存仓库”在有限的空间内,能够最高效地运转。