redis面试:redis的内存管理

本文解析Redis内存控制的过期策略(惰性删除+定期过期)和淘汰策略(LRU、随机等),以及如何配置maxmemory和maxmemory-policy。了解如何在内存限制下保持高效缓存和性能平衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis主要通过控制内存上限和回收策略实现内存管理

控制内存上限

redis可以通过maxmemory 参数来控制可用内存。限制内存的目的主要有:

  • 用于缓存场景,当超出内存上限maxmemory时使用LRU等删除策略释放空间
  • 防止所用内存超过服务器物理内存。
    • 需要注意的是,maxmemory限制的是redis实际使用的内存量,也就是used_memory统计项对应的内存。
    • 由于内存碎片率的存在,实际消耗的内存可能会比maxmemory设置的更大,实际使用时需要小心这部分内存溢出

动态调整内存上限

redis的内存上限可以通过config set maxmemory进行动态修改,即修改最大可用内存,比如:

Redis-1>config set maxmemory 6GB

通过动态修改maxmemory,可以实现当前服务器下动态伸缩redis内存的目的。

注意:

  • redis默认无限使用服务器内存。为防止极端情况下导致内存耗尽,建议所有的redis进程都要配置Redis
  • 在保证物理内存可用的情况下,系统中所有redis实例可以通过调整maxmemory参数来达到自由伸缩内存的目的

内存回收策略

redis的内存回收机制主要体现在如下两个方面:

  • 删除到达过期时间的键对象
  • 内存使用达到maxmemory上限时触发内存溢出过期控制策略

关于:redis的过期策略和内存淘汰策略

一开始总会把这两个问题搞混淆了。一句话简单解释一下:
过期策略:已经过期的key删除方案。【定期删除和惰性过期】
淘汰策略:内存不够用的时候的处理方案。【就是常说的LRU算法】

Redis过期策略

我们都知道,Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。redis的过期策略就是指当redis中缓存的key过期了,redis如何处理

过期策略通常有三种:

  • 定时过期
  • 惰性过期
  • 定期过期

定时过期(redis没有使用这种方法)

  • redis所有的键都可以设置过期属性,内存保存在过期字典中。
  • 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。
  • 该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量
  • 由于进程内保存大量的键,维护每个键的精准过期删除机制会导致消耗大量的CPU,对于单线程的redis来说成本太大
  • 因此redis采用惰性删除和定时任务删除机制实现过期键的内存回收,没有采用这种方法

惰性过期

  • 只有当客户端访问一个key时,才会判断该key是否已经过期,过期则清除并返回空
  • 这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除,但是对内存非常不友好。
  • 极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存

因此,Redis还提供另一种定时任务删除机制作为惰性删除的补充。

定期过期

  • redis内部维护一个定时任务,默认每秒运行20次(通过配置hz控制)。
  • 每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已经过期的key
  • 该策略是前两者的一个折中方案。
  • 定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例,使用快慢这两种速率模式回收键。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。

redis默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的key,而是采用了一种简单的贪心策略

  • 从过期字典中随机20个key
  • 删除这30个key中已经过期的key
  • 如果过期的 key 比率超过 1/4,那就重复步骤 1;

redis默认是每隔 100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。

总结

  • Redis中同时使用了惰性过期和定期过期两种过期策略。
  • 定期删除是集中处理,惰性删除是零散处理。

Redis的内存淘汰策略

有了以上过期策略的说明后,就很容易理解为什么需要淘汰策略了。因为不管是定期采样删除还是惰性删除都不是一种完全精准的删除,还是会存在一个key没有被删除的场景,所以就需要内存淘汰策略进行补充

内存淘汰策略

当redis所用内存达到maxmemory上限时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制,Redis支持6种策略。

  • noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息
  • allkeys-lru: 加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键(不管数据有没有设置超时属性),直到腾出足够空间为止
  • volatile-lru:
    • 加入键的时候,如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键,直到腾出足够空间为止。
    • 如果没有可删除的键对象,回退到noeviction策略
  • allkeys-random:加入键的时候,如果过限,随机删除所有键,直到腾出足够空间为止。
  • volatile-random:加入键的时候如果过限,随机删除过期键,直到腾出足够空间为止。
  • volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
  • allkeys-lfu:从所有键中驱逐使用频率最少的键

内存溢出控制策略可以采用config set maxmemory-policy{policy}动态配置。Redis支持丰富的内存溢出应对策略,可以根据实际需求灵活定制

如何配置

我们通过配置redis.conf中的maxmemory这个值来开启内存淘汰功能。

# maxmemory

值得注意的是,maxmemory为0的时候表示我们对Redis的内存使用没有限制。

根据应用场景,选择淘汰策略

# maxmemory-policy noeviction

我们来了解下,内存淘汰的过程

  • 首先,客户端发起了需要申请更多内存的命令(如set)。
  • 然后,Redis检查内存使用情况,如果已使用的内存大于maxmemory则开始根据用户配置的不同淘汰策略来淘汰内存(key),从而换取一定的内存。
  • 最后,如果上面都没问题,则这个命令执行成功。

此外,redis支持动态改配置,无需重启。

config set maxmemory 100000
config set maxmemory-policy noeviction

总结

Redis的内存淘汰策略的选取并不会影响过期的key的处理。

  • 内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;
  • 过期策略用于处理过期的缓存数据。

https://www.cnblogs.com/alsf/p/9399009.html
https://www.jianshu.com/p/8aa619933ebb
https://redis.io/topics/lru-cache
https://zhuanlan.zhihu.com/p/105587132

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值