Redis 缓存回收的7种策略volatile设置过期时间及allkeys所有数据范围内

  • Post author:
  • Post category:其他




1、基础说明

当redis设置内存使用限制后,当达到内存限制时,Redis将尝试删除key(控制节点的最大使用内存)

redis.conf中配置项

maxmemory <bytes>

或者控制台执行

CONFIG SET maxmemory 4gb

,设置内存

在这里插入图片描述

参数说明:

  • maxmemory的默认值是0,也就是不限制内存的使用。
  • 32bit系统如果使用默认配置或配置为maxmemory 0则最大使用3G内存。
  • maxmemory的值没有最小限制(但是如果低于1MB,会打一条WARNING日志)。
  • 如果设置了maxmemory选项(值 >= 1),redis在接收命令时总是会判断当前是否已经超出最大内存限制,如果超过限制会根据驱逐策略去释放内存(如果是同步释放且释放内存很大,则会阻塞其他命令的执行)。
  • 单位,默认字节B,支持,KB、MB、GB、K(1000B)、M(1000000B)、G(1000000000B)

推荐设置方案(需要结合

应用数据实际访问特征



成本开销

来综合考虑的。)

  • 根据“八二原理”,最常被访问的 20% 的数据来说,它们贡献的访问量,既有可能超过 80%,也有可能不到 80%。

    建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销。



2、淘汰策略

缓存被写满是不可避免的。一共有7种淘汰策略,1种拒绝策略:

  • 针对设置过期时间的键值对:即使缓存没有写满,这些数据如果过期了,也会被删除。

    除。当然,如果它的过期时间到了但未被策略选中,同样也会被删除。


    • volatile-random

      :从设置了过期时间的键值对中,进行

      随机删除

    • volatile-ttl

      :从设置了过期时间的键值对中,根据

      过期时间的先后进行删除,越早过期的越先被删除

    • volatile-lru

      :从设置了过期时间的键值对中,使用

      LRU

      算法筛选,

    • volatile-lfu

      :从设置了过期时间的键值对中,使用

      LFU

      算法筛选,在 LRU算法的基础上,同时考虑了

      数据的访问时效性和数据的访问次数
  • 所有键值对


    • allkeys-random

      :从所有键值对中,随机选择并删除数据;

    • allkeys-lru

      :从所有键值对中,使用

      LRU

      算法筛选,

    • allkeys-lfu

      :从所有键值对中,使用

      LFU

      算法筛选,

  • noevction

    :不进行数据淘汰。

    一旦缓存被写满了,再有写请求来时,Redis不再提供服务,而是直接返回错误

如果一个键值对被删除策略选中了,即使它的过期时间还没到,也需要被删。

设置过期key的方式EXPIRE、PEXPIRE、EXPIREAT、PEXPIREAT

  • 剩余时间

    • EXPIRE(秒级)、PEXPIRE(毫秒级)
  • 指定过期时间戳

    • EXPIREAT(设置秒级)、PEXPIREAT(设置毫秒级)



2.1、LRU算法:最近最少使用的原则

LRU 算法的全称是 Least Recently Used,按照

最近最少使用的原则

来筛选数据,最不常用的数据会被筛选出来,而最近频繁使用的数据会留在缓存中。维护一个链表,链表头是MRL(最常使用的数据),链表尾就是LRU(最不常使用的数据)。LRU需要用链表管理所有的缓存数据,这会带来额外的空间开

销,当有数据被访问时,需要在链表上把该数据移动到 MRU 端,如果有大量数据被访问,就会带来很多链表移动操作,会很耗时

Redis 中,LRU算法被做了简化,以减轻数据淘汰对缓存性能的影响。Redis 默认会记录每个数据的最近一次

访问的时间戳

(由键值对数据结构RedisObject 中的 lru 字段记录)。

  1. Redis在决定淘汰的数据时,第一次会

    随机选出N 个数据

    ,把它们作为一个候选集合。
  2. Redis 会比较这 N 个数据的 lru 字段,把lru 字段值最小的数据从缓存中淘汰出去。
  3. 当需要再次淘汰数据时,Redis 需要挑选数据进入第一次淘汰时创建的候选集合。挑选标准是:

    1. 能进入候选集合的数据的 lru 字段值

      必须小于候选集合中最小的 lru 值。
    2. 有新数据进入候选数据集后,如果候选数据集中的数据个数达到了 maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。

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

CONFIG SET maxmemory-samples 100



2.2、LFU算法

LFU 策略中会从两个维度来筛选并淘汰数据:

  • 一是,数据访问的时效性(访问时间离当前时间的远近);
  • 二是,数据的被访问次数。

LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了

一个计数器

,来统计这个数据的访问次数。当使用 LFU 策略筛选淘汰数据时:

  • 首先会根据数据的

    访问次数

    进行筛选,把访问次数最低的数据淘汰出缓存。
  • 如果两个数据的访问次数相同,LFU 策略再

    比较这两个数据的访问时效性

    ,把距离上一次访问时间更久的数据淘汰出缓存。
  • 如果一个key的计数器值特别大,但是长时间没有被访问,redis中LFU算法会有对应的衰减机制

    • lfu_log_factor衰减因子:控制计数器值增加的速度,避免 counter(8bit) 值很快就到 255 了。
    • lfu_decay_time默认1:如果数据在 N 分钟内没有被访问,那么它的访问次数就要减 N。

      在这里插入图片描述


      LRU 策略更加关注数据的时效性,而 LFU 策略更加关注数据的访问频次。



3、淘汰策略使用

  1. 优先使用 allkeys-lru 策略。可以充分利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。如果

    业务数据中有明显的冷热数据区分

    ,建议使用

    allkeys-lru

    策略。

  2. 如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分

    ,建议使用

    allkeys-random

    策略,随机选择淘汰的数据就行。
  3. 如果业务中

    有置顶的需求

    ,比如置顶新闻、置顶视频,那么,可以使用

    volatile-lru

    策略,同时不给这些置顶数据设置过期时间。这样一来,这些需要置顶的数据一直不会被删除,而其他数据会在过期时根据 LRU规则进行筛选。



4、缓存污染

在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染。

当缓存污染不严重时,只有少量数据占据缓存空间,此时,对缓存系统的影响不大。但是,缓存污染一旦变得严重后,就会有大量不再访问的数据滞留在缓存中。如果这时数据占满了缓存空间,我们再往缓存中写入新数据时,就需要先把这些数据逐步淘汰出缓存,这就会引入额外的操作时间开销,进而会影响应用的性能。

要解决缓存污染问题,最关键的技术点就是

能识别出这些只访问一次或是访问次数很少的数据

,在淘汰数据时,优先把它们筛选出来并淘汰掉。所以采用LFU策略

  • volatile-lfu
  • allkeys-lfu



版权声明:本文为Extraordinarylife原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。