1

1.Redis过期删除

在使用redis存储数据时,我们一般会对数据设置过期时间,使得这些缓存在过期之后能被清除,释放珍贵的缓存资源。那过期清理是用什么策略来实现的呢?

redis主要通过以下两种方式

1.1 定期删除

1.redis每过100ms,从设置了过期时间的key中随机取出20个缓存key

2.清除其中的过期key

3.若过期key占比超过1/4,则重复步骤1

为什么定期删除采用的是随机策略,而不是对全部数据做清理呢?因为每100ms过滤所有缓存数据,对CPU压力较大。

虽然定期删除解决了一部分过期数据的问题,但是还有不少数据并没有被清除出缓存,所以此时就有了惰性删除

1.2 惰性删除

某个缓存key在查询时,若此时已过期,则会从缓存中删除,同时返回空

这种方式是被动触发的,

定期删除惰性删除虽然能清理一部分过期数据,但还存在一个问题:

​ 部分过期缓存key未被清理出缓存,长久占用缓存资源(随机策略存在的缺陷性),随着缓存数据的不断增加,

无法通过删除过期key的方式腾出空间,来储存新的热点数据。

这种情况下,如何淘汰旧的缓存数据,储存新的热点数据呢?内存淘汰机制

2.内存淘汰机制

redis提供8种策略来应对当使用内存达到限制值的情况

1.noeviction: 返回错误,不删除任何键值

2.allkeys-lru:尝试回收最少使用的键值(LRU算法)

3.volatile-lru:尝试回收最少使用的键值,但仅限于在过期键值集合中

4.allkeys-random:回收随机的键值

5.volatile-random:回收随机的键值,但仅限于在过期键值集合中

6.volatile-ttl:回收过期集合的键值,并优先回收存活时间较短的键值

7.allkeys-lfu:回收最少使用频次的键值(LFU算法)

8.volatile-lfu:回收最少使用频次的键值(LFU算法),但仅限于在过期键值集合中

这里有两个重要的算法:

LRU:最近最少被使用。访问时间越早越容易被淘汰

LFU:最近最少使用频次。使用频次越少越容易被淘汰

Redis的LRU算法采用一种近似LRU的方式来实现,通过对少量keys(maxmemory-samples,默认为5)进行取样,然后回收其中一个最好的key(被访问时间最早的)。

Redis3.0算法已改进为回收键的候选池子

1.第一次随机选取的key都放入一个pool中(pool大小为16),pool中的key是按照访问时间大小排序;

2.接下来每次随机选取的key都必须小于pool中最小的key,若pool未填满,则重复步骤1

3.放满之后,每次有新的key需要进入时,需要将pool中lru最大的一个key取出

4.淘汰的时候,直接从pool中取出一个lru最小的一个key然后淘汰

Redis有了LRU之后,为什么还需要LFU呢?因为Redis作者发现就算提高采样数量或者pool的大小,也无法再提高缓存命中率,而LFU算法能起到更好的效果。

LFU近似于LRU,它使用一个概率计数器(morris counter),用来估计访问频率;counter的计数有两个特点,1.随着访问次数的增加,counter的计数会越来越缓慢(counter最大值为255),2.随着时间的流逝,counter会逐渐衰减。淘汰时也会有一个pool,也采取与LRU类似的方式,但是排序是按照计数从大到小排列(越靠后越容易被淘汰)

为什么Redis不采用标准LRU算法

标准LRU算法为了达到查找和删除的时间复杂度一般采用hash表双向链表结合的数据结构。这样会增加额外的内存占用。


Summer
1 声望0 粉丝

Coding and Recording


« 上一篇
动态规划