深入理解redis——Redis的缓存过期淘汰策略

1.Redis内存满了怎么办

2.往redis里写的数据是怎么没了的?它如何删除的?

3.redis缓存淘汰策略

4.总结

1.Redis内存满了怎么办
redis是我们每天都在开发和使用的一个工具,但是我们在使用它的时候,有仔细关注过它的默认占用内存是多少吗?以及如何修改呢?

1.1Redis默认内存多少?怎么查看?如何修改?

我们打开redis的配置文件,搜索一下maxmemory,会发现这么一行代码:
image.png

可以看出,把这个设置打开,并且在部分设置值之后,就可以设置redis占用内存的大小了,maxmemory是bytes字节类型,注意转换。

设置为 0 ,或者不设置这个字段,表示不限制 Redis 内存使用。

1.2生产上如何配置redis占用内存的大小?
一般推荐Redis设置内存为最大物理内存的四分之三。

1.3 如果打满了redis的使用内存会怎么样?

我们设置一下redis的缓存使用上限,我们设置为10个byte,再设置一个值,看看。

image.png
因为这个key没有加上过期时间,就会导致maxmemory异常,为了避免这个情况,我们要有缓存淘汰策略。

2.往redis里写的数据是怎么没了的?它如何删除的?

我们先来思考一个问题,在什么都不配置的情况下,redis的一个键如果是设置了过期时间的到期之后,是不是马上就会从redis中被删除呢?

答案:如果不配置缓存淘汰策略,redis是不会把过期的key从内存中删除出去的,虽然看起来这个key已经查不到了:

image.png

让我们来思考一下,如果要删除过期的key,能有什么策略?常规能想到的有:

1)立即删除

redis一直遍历着所有被设置了过期时间的key,来检测是否已经到了过期时间,然后对它进行删除。

立即删除能保证内存中数据的最大新鲜度,因为它能保证键值对在过期后马上被删除,所占用的内存也会被释放,但这样对cpu是不友好的,因为遍历/删除都会占用cpu的时间,如果刚好碰倒cpu很忙的时候,就会给cpu造成额外的压力,产生极大的性能消耗,同时也会影响读取操作。

总结:对内存友好,对cpu不友好。

2)惰性删除

数据到达过期时间,不做处理,等下次访问该数据的时候
如果未过期,返回该数据
如果过期了,就删除这个key,返回不存在

惰性删除的缺点是,它对内存极其不友好。
如果这个key已经过期,而且是一个大key,如果这个key不被访问,就会一直存在于数据库中,那么它永远也不会被删除。我们甚至可以将这种情况视为内存泄漏-无用的垃圾数据占用了大量的内存,而服务器却不去释放他们,对于非常依赖内存的redis而言,肯定不是一个好消息。

3)定期删除策略
定期删除策略是上面两种方式的折中处理
每隔一段时间执行一次删除过期key操作,并通过限制删除操作执行时长和频率来减少删除操作对cpu时间都的影响(有点像jvm虚拟机中能控制吞吐量的Parallel垃圾收集器)。定期轮询redis库中的时效性数据,采用随机抽取的策略,抽到过期的key就进行删除。

特点1:cpu性能占用设置有峰值,检测频率和自行控制
特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理

缺点:
1)定期删除执行的时长和频率很难界定,如果执行地太频繁,或者执行时间太长,这种策略就会变为立即删除策略,消耗cpu,如果执行地太不频繁,又会像惰性删除策略一样,出现浪费内存的情况。
2)会有一直都没被抽查到的key(漏网之鱼)的存在

这时,为了解决这些问题,我们的redis缓存淘汰策略就登场了!

3.redis缓存淘汰策略

我们打开redis的配置文件,搜索 'maxmemory-policy'

image.png

就会发现,默认的缓存淘汰策略就是什么都不淘汰。

redis的缓存淘汰策略有哪些:

1)noeviction: 不会驱逐任何key
2)allkeys-lru: 对所有key使用LRU算法进行删除
3)volatile-lru: 对所有设置了过期时间的key使用LRU算法进行删除
4)allkeys-random: 对所有key随机删除
5)volatile-random: 对所有设置了过期时间的key随机删除
6)volatile-ttl: 删除马上要过期的key
7)allkeys-lfu: 对所有key使用LFU算法进行删除
8)volatile-lfu: 对所有设置了过期时间的key使用LFU算法进行删除

上面出现了两个名词,LRU和LFU,我们先来解释一下这两个词语的意思:

LRU:
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法。

image.png

LFU:
最不经常使用页置换算法,要求在页置换时置换引用计数最小的页。
image.png

一个强调的是使用频率,一个强调的是最近未使用。

我们可以先把上面的redis缓存淘汰策略进行归类:
1)是对所有key,还是对设置了过期时间的key
2)是随机删除,全部删除,还是用LRU或者LFU删除。

两个维度和四个方面,获得了八种结果。

那我们平时使用哪个呢?

如果分为一般的热数据和冷数据,那么我们都推荐使用 allkeys-lru 策略,其中一部分key经常被读写,如果在不确定业务的情况下,allkeys-lru是一个比较好的选择(被淘汰的冷数据如果又要再次被访问,则可以通过业务逻辑代码重新读入缓存中)。

如果各个key访问的频率差不多,则可以使用 allkeys-random 策略, 即读写所有元素的概率差不多。

如果要让redis根据ttl来筛选要删除的key,请使用volatile-ttl 策略。
volatile-lru 和 volatile-random 策略应用场景是: 既有要过期的key,又有持久key的实例中。 对于这类场景,我们一般使用两个单独的redis。

4.总结

今天我们学习了redis缓存的淘汰策略,注意一开始redis服务占用的缓存大小和淘汰策略都是没有配置过的,而且很少的公司会去配置,如果公司redis场景用的多,我们就要注意一下这方面了!

你可能感兴趣的:(redis缓存)