redis内存淘汰策略和过期键删除

数据库键的过期时间都保存在过期字典中

过期键删除(主动删除和被动删除):

redis 的过期键的过期时间都保存在过期字典中,过期键的删除策略有3种

  • 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即删除对键的删除操作。
  • 惰性删除:放任键过期不管,但每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键。如果没有过期,就返回该键。
  • 定期删除:每隔一段时间,程序对数据库进行一次检查,删除里面的过期键。至于删除多少过期键,以及检查多少数据库,有算法决定。

1 定时删除特点

优点:对内存友好,通过定时器可以保证过期键过期键会尽可能快的删除,并释放过期键占用的空间。

缺点:1)cpu不友好,在过期键比较多的情况下,删除过期键可能会占用相当一部分cpu时间;在内存不紧张cpu紧张的情况下,将cpu时间用在删除和当前任务无关的过期键上,无疑会对服务器响应时间和吞吐量造成影响。2)创建定时器需要Redis服务器中的时间事件,而现在时间事件的实现方式是无序链表,查找一个事件的时间复杂度为O(N),并不能高效的处理大量时间事件。

2 惰性删除特点

优点:1)对cpu友好,程序只在取出键时才对建进行过期检查,删除的目标仅限于当前处理的键。

缺点:1)对内存不友好,当数据库中有大量的过期键,而这些键又没有被访问到,那么他们也许会永远不会被删除。

3 定期删除:是前两种删除策略的一种折中。会每隔一段时间执行一次删除过期键操作,并通过限制操作执行的时长和频率来减少删除操作对cpu时间的影响。

难点:确定删除策略的时长和频率

1)如果删除操作太过频繁,或者执行时间太长,定期删除策略就会退化成定时删除策略。

2)如果删除执行得太少,或者执行时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存现象。

内存淘汰

最大内存的设置是通过设置maxmemory来完成的,格式为maxmemory bytes ,maxmemory为0的时候表示对Redis的内存使用没有限制。当目前使用的内存超过了设置的最大内存,就要进行内存释放了, 当需要进行内存释放的时候,需要用某种策略对保存的的对象进行删除。Redis有六种策略(默认的策略是no-enviction)。

redis中当内存超过限制时,按照配置的策略,淘汰掉相应的key-value,使得内存可以继续留有足够的空间保存新的数据。redis 确定驱逐某个键值对后,会删除这个数据并,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。

  1. volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的key ;
  2. allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰;
  3. volatile-random:随机淘汰数据,只淘汰设定了有效期的key;
  4. allkeys-random:随机淘汰数据,所有的key都可以被淘汰;
  5. volatile-ttl:淘汰剩余有效期最短的key;
  6. no-enviction:不删除任意数据(但redis还会根据引用计数器进行释放),这时如果内存不够时,会直接返回错误 。
  7. 以上总结就是:lru淘汰-最少使用,ttl淘汰-将要过期,随机淘汰-随机
选择:
  • 在Redis中,数据有一部分访问频率较高,其余部分访问频率较低,或者无法预测数据的使用频率时,设置allkeys-lru是比较合适的。
  • 如果所有数据访问概率大致相等时,可以选择allkeys-random。
  • 如果研发者需要通过设置不同的ttl来判断数据过期的先后顺序,此时可以选择volatile-ttl策略。
  • 如果希望一些数据能长期被保存,而一些数据可以被淘汰掉时,选择volatile-lru或volatile-random都是比较不错的。
  • 由于设置expire会消耗额外的内存,如果计划避免Redis内存在此项上的浪费,可以选用allkeys-lru 策略,这样就可以不再设置过期时间,高效利用内存了。