Redis 作为当下最热门的 Key-Value 存储系统,在大大小小的系统中都扮演着重要的角色,不管是 session 存储还是热点数据的缓存,亦或是其他场景,我们都会使用到 Redis。在生产环境我们偶尔会遇到 Redis 服务器内存不够的情况,那对于这种情况 Redis 的内存是如何回收处理的呢?另外对于带有过期时间的 Key Redis 又是如何处理的呢?
我们都知道如果我们要设置 Redis 的最大内存大小只需要在配置文件redis.conf 中配置一行 maxmemory xxx 即可,或者我们通过 config set 命令在运行时动态配置 Redis 的内存大小。
那么当 Redis 内存不够的时候,我们要知道 Redis 是根据什么策略来淘汰数据的,在配置文件中我们使用 maxmemory-policy 来配置策略,如下图

可以看到策略的值由如下几种:
客户端运行命令,添加数据申请内存; Redis 会检查内存的使用情况,如果已经超过的最大限制,就是根据配置的内存淘汰策略去淘汰相应的 key,从而保证新数据正常添加; 继续执行命令。
Redis 中的 LRU 算法不是精确的 LRU 算法,而是一种经过采样的LRU,我们可以通过在配置文件中设置 maxmemory-samples 5 来设置采样的大小,默认值为 5,我们可以自行调整。官方提供的采用对比如下,我们可以看到当采用数设置为 10 的时候已经很接近真实的 LRU 算法了。

在 Redis 3.x 以上的版本的中做过优化,目前的近似 LRU 算法以及提升了很大的效率,Redis 之所以不采样实际的 LRU 算法,是因为会耗费很多的内存
前面介绍了 Redis 的内存回收策略,下面我们看看 Key 的过期策略,提到 Key 的过期策略,我们说的当然是带有 expire 时间的 key,如下

 通过 redis> set name ziyouu ex 100 命令我们在 Redis 中设置一个 key 为 name,值为 ziyouu 的数据,从上面的截图中我们可以看到右下角有个 TTL,并且每次刷新都是在减少的,说明我们设置带有过期时间的 key 成功了。
对于如何清除过期的 key 通常我们很自然的可以想到就是我们可以给每个 key 加一个定时器,这样当时间到达过期时间的时候就自动删除 key,这种策略我们叫定时策略。这种方式对内存是友好的,因为可以及时清理过期的可以,但是由于每个带有过期时间的 key 都需要一个定时器,所以这种方式对 CPU 是不友好的,会占用很多的 CPU,另外这种方式是一种主动的行为。
有主动也有被动,我们可以不用定时器,而是在每次访问一个 key 的时候再去判断这个 key 是否到达过期时间了,过期了就删除掉。这种方式我们叫做惰性策略,这种方式对 CPU 是友好的,但是对应的也有一个问题,就是如果这些过期的 key 我们再也不会访问,那么永远就不会删除了。
Redis 服务器在真正实现的时候上面的两种方式都会用到,这样就可以得到一种折中的方式。另外在定时策略中,从官网我们可以看到如下说明
Specifically this is what Redis does 10 times per second: Test 20 random keys from the set of keys with an associated expire. Delete all the keys found expired. If more than 25% of keys were expired, start again from step 1.
意思是说 Redis 会在有过期时间的 Key 集合中随机 20 个出来,删掉已经过期的 Key,如果比例超过 25%,再重新执行操作。每秒中会执行 10 个这样的操作。
发表时间:2019-11-25
本站文章除注明转载/出处外,皆为作者原创,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。