共计 1479 个字符,预计需要花费 4 分钟才能阅读完成。
我们一般都用内存作为缓存,但是内存是无限的吗?当然不是,内存是很宝贵且有限的自然。
可能一台机器也就十几 G 的内存,但是却可以挂几个 T,十几个 T 的硬盘空间,Reids 主要是基于内存做高性能,高并发的读写操作的。
那么问题来了?既然内存时有限的,比如 Redis 就只给分配了 10G 的内存,你却要往里硬怼 20G 的数据,会咋办?毫无疑问,当然会被干掉 10G 的数据了,那问题又来了,干掉那些数据?保留那些数据?我们当然希望干掉那些不常用的,保留常用的数据了。
所以说,这是缓存的一种基本概念,数据是会过期的,要么你自己设置过期时间,要么在满足某些条件下 Redis 帮你干掉。
如果自己设置了过期时间,那你知道 Redis 是怎么给你弄过期的吗?什么时候被删除的?
比如我们在 set key 时可以给定一个 expire time 就是过期时间,比如指定这个 key 的过期时间为 1 小时?10 分钟?这个很有用的,我们自己控制缓存的存活时间。
假如你设置了一批 key 只能存活 1 小时,那么一小时后,Redis 是如何对这一批 key 进行删除的尼?请往下看!
定期删除 + 惰性删除
所谓定期删除指的是 Redis 默认会每隔一定时间(默认 100ms)就会抽取一批设置了过期时间的 key 来检测是否过期,过期就删除。假设你 Redis 存放了 100 万 key 都设置了过期时间,你每隔几百毫秒,就检查 100 万 key,那 Reids 基本就挂了,cup 负载会飙升,都消耗在你检测过期 key 上了。
注意⚠️!这里可不是每隔 100ms 就遍历所有的设置了过期的 key,那样将是一场性能上的灾难。实际上 Redis 是每隔 100ms 随机的抽取 一部分 设置过期时间的 key 来检测和删除。
但是问题来了??定期删除可能会导致一部分过期了的 key 时间到了却并没有被删除,怎么办?别着急,这就该我们的惰性删除登场了。
惰性删除,就是你在获取某个 Key 时 Redis 会先检测一下,这个 key 是否设置了过期时间?如果设置了过期时间那么是否过期?过期就删除。
通过上述两种手段基本上可以保证过期的 key 一定会被干掉。
但是实际问题比这复杂多了,比喻定期删除漏掉了很多过期的 key, 然后也没及时的去查也就没有走惰性删除,此时会怎么样?大批的过期 key 躺在内存了,导致 Redis 内存很快别被耗尽,咋办?咋办?咋办?
别急!这种情况会走内存淘汰机制
内存淘汰
如果 Redis 的内存占用过多的时候,此时 Redis 会进行内存淘汰,如何淘汰?会有如下几种淘汰策略。
- noeviction: 当内存不足以容纳新写入的数据时,新写入数据时会报错。这个一般不会有人使用,感觉太???? 人了。
- allkeys-lru: 当内存不足以容纳新写入的数据时,在键空间中,移除最近最少使用的 key.(这也是我们经常使用的策略)
- allkes-random: 当内存不足以容纳新写入的数据时,在键空间中,随机移除某个 key。(这个正常人都不会使用吧,为啥要随机?肯定移除最近最少使用的 key 呀)
- volatile-lru: 当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,移除最近最少使用的 key。(这个一般也不太合适)
- volatile-random: 当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,随机移除某个 key。
- volatile-ttl: 当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。(这个也不合理)
到这 Redis 的过期策略基本介绍完了。也就三把 ???? ???? ????
???? 定期删除 +???? 惰性删除 +???? 内存淘汰(最常用的 allkeys-lru)