一.为什么需要缓存淘汰机制

  • Redis缓存使用内存来保存数据,避免业务应用从后端数据库中读取数据,可以提升应用响应速度。
  • 为什么我们不把所有要访问的数据都放入到缓存中呢?性价比不高。
  • MYSQL中有1TB数据,如果我们使用Redis把这1TB数据缓存起来,1TB内存价格是3.5w元但是1TB磁盘的价格只有800人民币左右。另一方面,数据访问大多数时候遵循二八原则,百分之八十的请求只访问百分之20的数据。

缓存空间容量必然要小于后端数据库的数据总量。

二.缓存数据的淘汰机制

数据淘汰机制包含两步:

  1. 根据一定策略筛选出对应用访问来说并不重要的数据;
  2. 将这些数据从缓存中删除,为新来的数据腾出空间;

三.设置多大的缓存容量合适

       

Redis核心技术与实战-学习笔记(二十四):替换策略:缓存满了_学习

  • "长尾效应" --蓝线: 二八原理。百分之20的数据贡献了百分之80的访问。
  • "重尾效应"--红线:20% 的数据可能贡献不了 80% 的访问,而剩余的 80% 数据反而贡献了更多的访问量。

正因为20%的数据不一定贡献80%的访问量,我们不能简单的按照"总数量的20%来设置缓存最大空间容量"。需要结合数据实际访问特征成本开销来综合考虑。

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

四.Redis缓存有哪些淘汰策略?

  • 不进行数据淘汰策略,只有noeviction。
  • 设置了过期时间的数据淘汰策略: volatle-random,volatitle-ttl,volatitle-lru,volatitle-lfu。
  • 所有数据范围内淘汰:allkeys-lru,allkeys-random, allkeys-lfu。

Redis核心技术与实战-学习笔记(二十四):替换策略:缓存满了_redis_02

  • 默认情况下,Redis在使用内存空间超过maxmemory时,并不会被淘汰,也就是设定的noeviction 策略。
  • 一旦缓存被写满了,Redis不再提供服务,直接报错。
  • Redis用作缓存时候,实际数据集通常会大于缓存容量的,总会有新的数据写入缓存,因此noeviction策略不符合Redis使用规则。

volatitle-random.volatitle-ttl,volatitle-lru和volatitle-lru这四种淘汰策略:

  • 他们筛选的候选数据范围,被限制在已设置过期时间的键值对上。
  • 即使缓存没有写满,这些数据过期也会被删除。
  • volatitle-ttl在筛选时,会针对设置了过期时间的键值对,根据过期时间先后删除,越早过去的越先被删除。
  • volatitle-random,在设置了过期时间的键值对中,随机删除。
  • volatitle-lru会使用LRU算法帅选设置看过期时间的键值对。
  • volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对。

allkeys-lru、allkeys-random、allkeys-lfu 这三种淘汰策略:

  • allkeys-random 策略,从所有键值对中随机选择并删除数据
  • allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选
  • allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选

如果一个键值对被删除 策略选中了,即使他的过期时间还没到,也需要被删除。当然,如果他的过期时间到了但未被选中,同样会被删除。

五.LRU 算法

     Least Recently Used 最近最少使用原则来筛选数据,最不常用的数据会被筛选出来,最近频繁使用的数据会留在缓存中。

LRU算法实现

  • LRU会把所有的数据组成一个链表,链表 的头和尾分别表示MRU端和LRU端  ,分别代表最近最常使用的数据和最近最不常的数据。

                      

Redis核心技术与实战-学习笔记(二十四):替换策略:缓存满了_学习_03

LRU算法思想:

  • 刚刚被访问的数据肯定还会再次访问,所以我们把它放到MRU端;
  • 长久不访问的数据,肯定不会再被访问了,所以我们就让它后移到 LRU 端,并有限删除它。

Redis的LRU算法:

  • LRU算法被做简化,以减轻数据 淘汰对缓存性能;
  • Redis 默认会记录每个数据的最近一次访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)。
  • Redis在决定淘汰数据的时,第一次会随机选出N个数据,把他们作为一个候选集合。
  • Redis会比较这N个数据的lru字段,把lru字段值中最小的数据从缓存中淘汰出去。
CONFIG SET maxmemory-samples 100
  • Redis提供了一个配置参数maxmemory-samples,这个参数就是Redis选出数据个数N。
  • 我们执行这个命令,可以让Redis选出100个数据作为候选数据集。
  • 能进入候选集合的数据lru字段值必须小于候选集合中最小的lru值。
  • 当有新的数据进入候选数据集的时候,如果候选数据集中的数据个数达到了maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。

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

六.三个使用建议

  • 优先使用allkeys-lru策略。这样可以充分利用LRU这一经典缓存算法优势,将最近最长访问的数据留在缓存中,提升应用的访问性能。适用于业务数据中有明显的冷热数据区分。
  • 如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分,建议使用allkeys-random策略,随机选择淘汰的数据就行。
  • 如果业务有置顶需求,比如置顶新闻,置顶视频,使用volatitle-lru策略,同时不给置顶数据设置过期时间。置顶数据一直不会被 删除,其他数据会在过期时候根据LRU规则进行筛选。