Redis
的过期策略以及内存淘汰策略
比如你 redis
只能存 5G
数据,可是你写了 10G
,那会删 5G
的数据。怎么删的?还有,你的数据已经设置了过期时间,但是时间到了,内存占用率还是比较高?答案: redis
采用的是定期删除 + 惰性删除两种策略
定期删除:用一个定时器来负责监视 key
,过期则自动删除。虽然内存及时释放,但是十分消耗 CPU
资源。在大并发请求下,CPU
要将时间应用在处理请求,而不是删除 key
,因此没有采用这一策略
过期策略
定期删除 + 惰性删除是如何工作的
redis
默认会每隔 100ms
检查是否有过期的 key
,如有过期的 key
则删除。需要说明的是,redis
不是每隔 100ms
将所有的 key
检查一次,而是随机抽取进行检查(如果每隔 100ms
对全部的 key
进行检查,那 redis
岂不是卡死)
因此,如果只采用定期删除策略,会导致很多 key
过期了,而没有删除。于是,惰性删除派上用场。也就是说在你获取某个 key
的时候 redis
会检查一下,这个 key
如果设置了过期时间那么是否过期了?如果过期了此时就会删除(并不是 key
到了过期时间,就会被删除掉。而是在你获取查询这个 key
时,redis
再惰性的检查一下)
采用定期删除 + 惰性删除就没其他问题了么
不是的,如果定期删除没有删除 key
。然后你也没即时去请求 key
,也就是说惰性删除也没生效。这样,redis
的内存会越来越高。那么就应该采用内存淘汰机制
内存淘汰策略
Redis
提供了 6
种的淘汰策略,配置方法如下
maxmemory-policy volatile-lru
noeviction
:默认使用的策略,当内存不足以容纳新写入数据时,新写入操作会报错。不推荐使用allkeys-lru
:当内存不足以容纳新写入数据时,移除最近最少使用的key
。也就是从所有key
中使用LRU
算法进行淘汰。推荐使用allkeys-random
:当内存不足以容纳新写入数据时,随机移除某个key
。应该也没人用吧,你不删最少使用Key
,去随机删volatile-lru
:当内存不足以容纳新写入数据时,在设置了过期时间的key
中使用LRU
算法进行淘汰。
这种情况一般是把redis
既当缓存,又做持久化存储的时候才用。不推荐volatile-random
:当内存不足以容纳新写入数据时,在从设置了过期时间的key
中随机淘汰。依然不推荐volatile-ttl
:当内存不足以容纳新写入数据时,在设置了过期时间的key
中,根据key
的过期时间进行淘汰,越早过期的越优先被淘汰
当使用 volatile-lru、volatile-random、volatile-ttl
这三种策略时,如果没有 key
可以被淘汰,则和 noeviction
一样返回错误
如果 Redis
内存满了怎么办
我们知道 Redis
是一个非常常用的内存型数据库,数据从内存中读取是它非常高效的原因之一,那么但是如果有一天,Redis
分配的内存满了怎么办?遇到这个问题不要慌,这种问题我们分为两角度回答就可以
- 我们可以怎么做
Redis
会怎么做
我们可以怎么做
我们可以增加 Redis
的可用内存
增加 Redis
可用内存
这种方法很暴力,也很好用。我们直接通过增加 Redis
可用内存就可以了, 有两种方式
通过配置文件配置
通过在 Redis
安装目录下面的 redis.conf
配置文件中添加以下配置设置内存大小
// 设置 Redis最大占用内存大小为 1000M
maxmemory 1000mb
通过命令修改
Redis
支持运行时通过命令动态修改内存大小
// 设置redis最大占用内存大小为 1000M
127.0.0.1:6379> config set maxmemory 1000mb
这种方法的确立竿见影,Redis
内存总归受限于机器的内存,也不能无限制的增长。那么如果没有办法再增加 Redis
的可用内存怎么办呢?我们可以看看 Redis
的内存淘汰策略
Redis
会怎么做
既然可以设置 Redis
最大占用内存大小,但 Redis
内存总归受限于机器的内存,也不能无限制的增长。那么如果没有办法再增加 Redis
的可用内存怎么办呢?实际上 Redis
定义了几种内存淘汰策略用来处理这种情况
Redis
的内存淘汰策略如上所述,Redis
提供了 6
种的淘汰策略
获取内存淘汰策略
127.0.0.1:6379> config get maxmemory-policy
通过配置文件设置内存淘汰策略
maxmemory-policy allkeys-lru
通过命令设置内存淘汰策略
127.0.0.1:6379> config set maxmemory-policy allkeys-lru
LRU
算法
什么是 LRU
算法
LRU
算法:即最近最少使用,是一种缓存置换算法。在使用内存作为缓存的时候,缓存的大小一般是固定的。当缓存被占满,这个时候继续往缓存里面添加数据,就需要淘汰一部分老的数据,释放内存空间用来存储新的数据。其核心思想是:如果一个数据在最近一段时间没有被用到,那么将来被使用到的可能性也很小,所以就可以被淘汰掉
LRU
算法在 Redis
中的实现
Redis
使用的是近似 LRU
算法,它跟常规的 LRU
算法还不太一样。近似 LRU
算法通过随机采样法淘汰数据,每次随机出 5
(默认)个 key
,从里面淘汰掉最近最少使用的 key
可以通过 maxmemory-samples
参数修改采样数量
maxmemory-samples 10
maxmenory-samples
配置的越大,淘汰的结果越接近于严格的 LRU
算法
Redis
为了实现近似 LRU
算法,给每个 key
增加了一个 24bit
的字段,用来存储该 key
最后一次被访问的时间
LFU
算法
LFU
算法与 Redis 4.0
LFU
算法是 Redis4.0
里面新加的一种淘汰策略。它的核心思想是根据 key
的最近被访问的频率进行淘汰,很少被访问的优先被淘汰,被访问的多的则被留下来
LFU
算法能更好的表示一个 key
被访问的热度。假如你使用的是 LRU
算法,一个 key
很久没有被访问到,只刚刚是偶尔被访问了一次,那么它就被认为是热点数据,不会被淘汰,而有些 key
将来是很有可能被访问到的则被淘汰了。如果使用 LFU
算法则不会出现这种情况,因为使用一次并不会使一个 key
成为热点数据
LFU
一共有两种策略
volatile-lfu
:在设置了过期时间的key
中使用LFU
算法淘汰key
allkeys-lfu
:在所有的key
中使用LFU
算法淘汰数据
设置使用这两种淘汰策略跟前面讲的一样,不过要注意的一点是这两种策略只能在 Redis4.0
及以上设置,如果在 Redis4.0
以下设置会报错