zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    Can't use Subversion command line client: svn
    SpringMVC配置easyui-datagrid
    找不到提交和更新按钮,subversion不见了,无法更新和上传代码
    静态资源[org.springframework.web.servlet.PageNotFound]
    Field 'id' doesn't have a default value
    MySql 插入数据中文乱码
    Junit 测试 Spring
    mybatis动态SQL
    Mybatis 3.3.0 Log4j配置
    MappingJacksonHttpMessageConverter过期
  • 原文地址:https://www.cnblogs.com/hld123/p/15371820.html
Copyright © 2011-2022 走看看