卡飞资源网

专业编程技术资源共享平台

从理论到实践,深入解析Redis过期删除策略与内存淘汰机制

我们知道,Redis是一款高性能的KV型分布式内存数据库。但是,由于内存资源始终是有限的,因此它必须遵循约定地过期Key删除策略与内存淘汰机制来保障内存资源的合理分配,从而使系统能够高效稳定地运行。


1. 过期删除策略

在Redis中,它使用了“定期删除策略+惰性删除策略”来实现过期删除策略,定期删除策略是集中处理,而惰性删除策略是零散处理。

Redis 内部维护了一个独立的过期字典用于存储所有过期的 Key,Redis 会将每个设置了过期时间的 Key 放入到这个独立的过期字典中。

Redis 会定期地遍历过期字典,并删除其中过期的 Key。为了减少删除操作对 Redis 性能的影响,Redis 采用了分步删除(lazy delete)的方式:每次只删除少量的过期 Key,直到全部删除完毕。

除了定期地遍历过期字典删除过期Key之外,Redis还会使用惰性删除策略来删除过期的 Key,即Redis 接收到一个读写操作请求时,会首先检查该 Key 是否过期,如果过期了就立即删除。

1.1 定期删除策略

定期删除策略指定期每隔一段时间执行一次过期键删除操作,并通过限制删除操作执行时长和频率来减少删除操作对CPU时间的影响。

它可以通过redis.conf配置文件中的hz来进行配置,如图1所示:

如图1所示,Redis 默认每 1 秒执行10次过期扫描,也就是每 100 ms 执行一次。每次执行过期扫描并不会遍历过期字典中的所有Key,而是采用了一种简单的贪心策略,如图2所示:

如图2所示,定期删除策略的执行流程为:

  • 1)根据redis.conf中的hz配置的执行频率值,定时serverCron方法去执行清理;
  • 2)从过期字典中随机选择20个已经过期的Key;
  • 3)删除已经选择的这20个已经过期的 Key;
  • 4)删除完成之后,继续检查过期的Key的比率是否超过25%,如果超过,继续重复执行“2)与3)”,否则结束。

在redis.conf配置文件中,hz参数的取值范围是1~500。在设置hz参数时需要注意的是,如果删除操作执行次数过多、执行时间太长,就会导致占用大量CPU资源去进行删除操作;如果删除操作次数太少、执行时间短,就会导致内存资源被持续占用,得不到释放。通常情况下,不建议超过100,只有在请求延时非常低的情况下可以将值提升到100。

1.2 惰性删除策略

对于惰性删除策略,它相对比较简单,当Redis客户端进行读写操作请求时,先检查一下Key是否过期,如果过期则立即删除,并且不再提供值返回给客户端。相对于定期删除策略,惰性删除策略不会在特定的时间点去主动删除过期Key,而是等到客户端尝试访问它的时候再判断Key是否过期。

由此可见,惰性删除策略对CPU比较友好,但也可能会导致过多过期键长时间得不到清理并被积压,从而增加了内存开销,使占用的内存得不到及时的释放。因此,只有当Key失效而又没有被占用太长的时间时,才能体现出它的优越性。

最后,在Redis主从架构中还需要小心主从不同步带来的过期Key删除问题:即一个Slave节点因网络等问题而未与Master进行及时同步,此时如果Master上执行了过期Key删除操作并未及时同步给Slave节点。这时,这些Master删除的过期Key因未同步删除操作的原因仍会存在于Slave节点上,从而带来了一系列安全隐患,因此要注意处理这种情况。


2. 内存淘汰机制

2.1 内存淘汰策略概述

当 Redis 达到最大内存限制时,它会根据配置好的内存淘汰策略决定哪些Key被删除。Redis 提供的内存淘汰策略有如下8种:

1)noeviction

它是Redis系统默认的内存淘汰策略,该策略表示当内存不足以容纳新写入数据时,新的写操作会被拒绝,Redis会返回错误。这样,我们就可以保证已有数据的安全,同时系统开发者或运维人员也会得到明确的信号去增加Redis的内存,或者寻找其他的解决方案。

因此,在任何对数据的完整性和可靠性有严格要求,不能接受任何形式数据丢失的场景中,应该选择noeviction作为Redis的内存淘汰策略。

2)allkeys-lru

LRU 算法即为最近最少使用算法,该策略会根据LRU算法在内存不足以容纳新数据时,优先淘汰掉最长时间未被使用的缓存Key。

3)volatile-lru

该策略在过期的Key中使用LRU算法进行淘汰,即优先淘汰那些已经设定了过期时间且最近最少使用的Key,从而可以更好地利用有限的内存资源。

4)allkeys-random

该策略提供了一种简单有效,且执行效率都相对较高的方式来处理内存压力,它会在所有的Key中随机选择一个Key进行淘汰,它并不关心这个Key是否设置了过期时间,也不关心这个Key被访问的频率或者时间。因此,由于所有数据都有可能被随机淘汰,这就避免了某些数据因为访问频率低而被频繁淘汰的结果,从而在一定程度上保证了所有数据在Redis中的生存机会均等。

5)volatile-random

该策略同样并不考虑缓存Key被访问的频率或者时间,会从那些已设置过期时间的Key中随机选择一个进行删除,从而确保了那些重要的、永久的数据Key不会被删除。

6)volatile-ttl

该策略会在设置了过期时间的Key中,优先删除 TTL (Time To Live) 值最小的键,也就是最快过期的键。

7)allkeys-lfu

LFU 算法即为最不常用算法(根据使用频率进行计算),该策略根据LFU 算法将优先删除那些最不常用的Key。当内存达到上限时,Redis会计算每个Key的使用频率,并删除使用频率最低的Key。

8)volatile-lfu

该策略会从哪些设置了过期时间的Key中,优先淘汰使用频率最低的Key。如果存在一些Key没有设置过期时间,那么这些Key将永远不会被淘汰,即使内存已经达到了上限。因此,在使用该策略时,一定要确保所有的键都设置了合理的过期时间。


2.2 相关操作与设置

1)获取Redis能使用的最大内存大小

config get maxmemory

运行结果如下图所示:

2)获取Redis内存淘汰策略

config get maxmemory-policy

运行结果如下图所示:

3)在redis.conf配置文件中设置淘汰策略,如下图所示:

4)在redis.conf配置文件中设置内存限制,如下图所示:

5)通过命令方式设置内存淘汰策略与内存限制(这种方式仅限于临时生效,因此不推荐),如下所示:

# 设置内存淘汰策略 
config set maxmemory-policy allkeys-lru

#设置内存限制 
config set maxmemory 100mb
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言