redis的数据都是保存在内存中,但是内存大小是有限的,所以这一节来看看redis中过期数据的删除,以及内存占用满以后新数据的插入问题。
过期数据
在内存中有专门的一块区域用来记录key的地址和过期时间,暂且叫做过期时间表。如果key有过期时间就会被放进这个表。
不过一个key过期了,redis为了提升性能,并不会马上将这个过期的key从内存删除,毕竟删除key也是会消耗cpu影响整体性能的。一方面是删除key节约内存,另一方面是保留key节约cpu,为了找到CPU和内存使用的一个平衡点,就有了不同的数据删除策略。
数据删除策略
定时删除
key一旦到达过期时间就被删除,CPU占用高,会影响redis服务器响应时间和指令吞吐量。用CPU换内存,拿时间换空间,适合CPU不太紧张而数据量较大的场景。
惰性删除
过期的时候不直接处理,等到下次访问该数据时再删除。内存压力比较大,会出现长期占用内存的旧数据。用内存换CPU,空间换时间,适合数据量不是很大但是CPU压力较大的场景。
定期删除
但是前面两者都太极端,还有一种中庸的方法。
info server
命令可以查询一个叫做hz
的配置值,默认是10,表示每秒钟执行10次轮询操作,最终操作的函数是activeExpireCycle()
,该函数会对所有的db逐一检测过期时间表。轮询的时候会随机挑选W个key检测过期时间,如果超时就删除key。检测完W个以后如果删除的key的数量多过25%W,就会继续在该db中进行检查,如果删除的key的数量少过25%W,就会继续检查下一个db。按照这个思路,CPU性能会出现峰值,频率可以通过hz
来配置;内存压力不是很大,长期占用内存的冷数据会被持续清理。同时总有部分过期数据没有被删除,不过redis并不会显示给客户端。
Redis中用的比较多的是惰性删除和定期删除。
逐出算法
假设极端情况下一直没有数据过期,内存中数据不断增多。最后新数据进来的时候没有足够的内存,这时redis会临时删除一些数据为当前指令清理存储空间,清理的策略称为逐出算法。
开关
通过info Memory
可以查看如下两个开关
- maxmemory,redis最多会用到的内存量,默认值是0,表示全部占用
- maxmemory_policy,redis会用什么逐出算法,默认值是noeviction,表示不进行逐出,修改这个值选择不同的算法
算法
一共有下面8种逐出算法
(volatile表示在可能会过期的key集合中进行查找)
- volatile-lru,least recently used,越久没被使用的越容易被干掉
- volatile-lfu,least frequently used,使用的频率越少的越容易被干掉
- volatile-ttl,time to live,越快要过期的越容易被干掉
- volatile-random,随机抽取
(allkeys表示检测全库的数据)
- allkeys-lru
- allkeys-lfu
- allkeys-random
通常使用较多的还是volatile-lru
算法,针对过期的数据越久没使用的越容易被干掉
可以通过修改配置文件来设置逐出算法
[fuhanxiao@testmachine redis]$ cat redis.conf | grep '# maxmemory'
# maxmemory <bytes>
# maxmemory-policy noeviction
# maxmemory-samples 5
也可以直接通过命令快速修改
127.0.0.1:6379> config set maxmemory-policy volatile-lru
OK
注意这里的key名中间是短横线而不是info命令中看到的下划线
修改好以后可以通过如下命令进行查询是否生效
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "volatile-lru
性能指标
redis的性能指标是通过查询key时候的命中和失败次数来判断的,可以直接通过info
命令来查看这两个数字。
127.0.0.1:6379> info Stats
# Stats
...
...
evicted_keys:0
keyspace_hits:24
keyspace_misses:9
...
...
我这台因为是测试机器所以miss数目比较高。同时也可以看到被逐出的key的个数,这里是0。因为测试逐出需要大量的key,我这里就不测试了。
我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。