Redis教程

Redis缓存淘汰策略

本文主要是介绍Redis缓存淘汰策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Redis缓存淘汰策略

    前言

    长期将Redis作为缓存使用,难免会遇到内存空间存储瓶颈,当Redis内存超出物理内存限制时,内存数据就会与磁盘产生频繁交换,使Redis性能急剧下降。此时如何淘汰无用数据释放空间,存储新数据就变得尤为重要了。解决这个问题就涉及到缓存系统的一个重要机制,即缓存数据的淘汰机制。

    一、淘汰机制实现步骤

    简单来说,数据淘汰机制包括两步

    1、根据一定的策略,筛选出对应用访问来说“不重要”的数据;

    2、将这些数据从缓存中删除,为新来的数据腾出空间,

    Redis3.0版本支持的淘汰策略有6种,自Redis 4.0版本开始新增volatile-lfu和allkeys-lfu这两种策略。

    二、淘汰机制分类

    1、按照是否会进行数据淘汰分类

    1)不进行数据淘汰的策略,只有 noeviction 这一种。

    2)会进行淘汰的 7 种其他策略。

    2、根据淘汰候选数据集的范围分类

    1)在设置了过期时间的数据中进行淘汰,包括 volatile-random、volatile-ttl、volatile-lru、volatile-lfu(Redis 4.0 后新增)四种。

    2)在所有数据范围内进行淘汰,包括 allkeys-lru、allkeys-random、allkeys-lfu三种。

    三、淘汰策略详情

    

     默认情况下,Redis 在使用的内存空间超过 maxmemory 值时,并不会淘汰数据,也就是设定的 noeviction 策略。对应到 Redis 缓存,也就是指,一旦缓存被写满了,再有写请求来时,Redis 不再提供服务,而是直接返回错误。

     1、noevction:一旦缓存被写满了,再有写请求来时,Redis 不再提供服务,而是直接返回错误。Redis 用作缓存时,实际的数据集通常都是大于缓存容量的,总会有新的数据要写入缓存,这个策略本身不淘汰数据,也就不会腾出新的缓存空间,我们不把它用在 Redis 缓存中。

     2、volatile-ttl 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。

     3、volatile-random 就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。

     4、volatile-lru 会使用 LRU 算法(下文具体介绍)筛选设置了过期时间的键值对。

     5、volatile-lfu 会使用 LFU 算法(下文具体介绍)选择设置了过期时间的键值对。

     6、allkeys-random 策略,从所有键值对中随机选择并删除数据。

     7、allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选。

     8、allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选。

     四、淘汰算法

     1、LRU算法

     LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

     在 Redis 中,LRU 算法被做了简化,以减轻数据淘汰对缓存性能的影响。具体来说,Redis 默认会记录每个数据的最近一次访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)。然后,Redis 在决 定淘汰的数据时,第一次会随机选出 N 个数据,把它们作为一个候选集合。接下来,Redis 会比较这 N 个数据的 lru 字段,把 lru 字段值最小的数据从缓存中淘汰出去。

     Redis 提供了一个配置参数 maxmemory-samples,这个参数就是 Redis 选出的数据个数 N。例如,我们执行如下命令,可以让 Redis 选出 100 个数据作为候选数据集:

     CONFIG SET maxmemory-samples 100

     当需要再次淘汰数据时,Redis 需要挑选数据进入第一次淘汰时创建的候选集合。这儿的挑选标准是:能进入候选集合的数据的 lru 字段值必须小于候选集合中最小的 lru 值。当有新数据进入候选数据集后,如果候选数据集中的数据个数达到了 maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。

    这样一来,Redis 缓存不用为所有的数据维护一个大链表,也不用在每次数据访问时都移动链表项,提升了缓存的性能。

    LRU算法有一个问题就是,当应用对大量的数据进行一次全体读取,每个数据都会被读取,而且只会被读取一次。此时,因为这些被查询的数据刚刚被访问过,所以 lru 字段值都很大。而其他的热点数据就会被淘汰掉。

     2、LFU算法

     Redis 从 4.0 版本开始增加了 LFU 淘汰策略。与 LRU 策略相比,LFU 策略中会从两个维度来筛选并淘汰数据:

     1、数据访问的时效性(访问时间离当前时间的远近)

     2、数据的被访问次数。

     LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 LFU 策略筛选淘汰数据时,首先会根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出缓存。如果两个数据的访问次数相同,LFU 策略再比较这两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰出缓存。

    应用对大量的数据进行一次全体读取,因为这些数据不会被再次访问,所以它们的访问次数不会再增加。因此,LFU 策略会优先把这些访问次数低的数据淘汰出缓存。就解决了上面提到的LRU存在的问题。

    3、TTL算法

    Redis 数据集数据结构中保存了键值对过期时间的表,即 redisDb.expires。与 LRU 数据淘汰机制类似,TTL 数据淘汰机制中会先从过期时间的表中随机挑选几个键值对,取出其中 ttl 比较小的键值对淘汰。同样,TTL淘汰策略并不是面向所有过期时间的表中最快过期的键值对,而只是随机挑选的几个键值对。

    4、随机算法

    在随机淘汰的场景下获取待删除的键值对,随机找hash桶再次hash指定位置的dictEntry即可。

    五、Redis.conf中配置淘汰策略

1 #设置Redis 内存大小的限制,我们可以设置maxmemory ,当数据达到限定大小后,会选择配置的策略淘汰数据
2 
3 maxmemory 300mb
4 
5  
6 
7 #设置Redis的淘汰策略。
8 
9 maxmemory-policy volatile-lru

     Redis中的淘汰机制都是几近于算法实现的,主要从性能和可靠性上做平衡,所以并不是完全可靠,所以开发者们在充分了解Redis淘汰策略之后还应在平时多主动设置或更新key的expire时间,主动删除没有价值的数据,提升Redis整体性能和空间。

 

   参考链接:

    https://www.jianshu.com/p/3981610b645a

 

这篇关于Redis缓存淘汰策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!