看到过期删除策略,大家现在脑袋里面可能会想为什么要学这个? 这有什么好说的,之前不是已经学过EXPIRE命令了, 给key设置过期时间,到期了不就删除了吗?
大家这个想法是没有任何问题的, 但是,绝对没有大家想象的那么简单。我们现在思考一个问题:如果一个key过期了,那么它实际是在什么时候被删除的呢?
可能很多同学的答案是: 到期了就直接被删除了。 但是这里告诉大家,这个答案是错误的。
这就需要给大家介绍下,Redis中对于过期键的过期删除策略:
下面我就来逐一学习这三种过期删除策略的工作机制。
它会在设置键的过期时间的同时,创建一个定时器, 当键到了过期时间,定时器会立即对键进行删除。 这个策略能够保证过期键的尽快删除,快速释放内存空间。
但是有得必有失。 Redis的操作频率是非常高的。绝大多数的键都是携带过期时间的,这样就会造成出现大量定时器执行,严重降低系统性能。
总的来说:该策略对内存空间足够友好, 但对CPU非常不友好,会拉低系统性能,因此不建议使用。
为了解决定时删除会占用大量CPU资源的问题, 因此产生了惰性删除。
**它不持续关注key的过期时间, 而是在获取key时,才会检查key是否过期,如果过期则删除该key。**简单来说就是:平时我不关注你,我用到你了,我才关注你在不在。
根据惰性删除来说,大家感觉它存在什么问题呢?
虽然它解决了定时删除会占用大量CPU资源的问题, 但是它又会造成内存空间的浪费。假设Redis中现在存在大量过期key,而这些过期key如果都不被使用,它们就会保留在redis中,造成内存空间一直被占用。
总的来说:惰性删除对CPU足够友好,但是对内存空间非常不友好,会造成大量内存空间的浪费。
根据刚才的学习大家可以发现,不管是定时删除还是惰性删除优缺点都非常明显:
那现在有没有一种策略,能够平衡这两者的优缺点呢? 因此出现了定期删除。
定期删除,顾名思义,就是每隔一段时间进行一次删除。 那么大家想一下,应该隔多久删一次? 一次又删除多少过期key呢?
所以定期删除最关键的就在于执行时长和频率的设置。
默认每秒扫描10次,对于这个参数能不能手动调整呢?
当然是可以的,只需要修改redis.conf中的hz参数即可。
对于hz参数,官方建议不要超过100,否则会对CPU造成比较大的压力。
学习完过期删除策略后, 大家思考两个问题:
举个例子:
有一些已经过期的key,定期扫描一直都没有扫描到它,而且这些key也一直没有被使用。 那么它们就会一直在内存中存在。同时继续向Redis不断插入新数据,最终造成内存空间不足的问题。
对于这种问题的解决,就用到了内存淘汰策略。
那么现在有的同学可能会想,那我把内存空间设置的很大不就可以了。 ok,你可以把它设置的大一些,但是怎么设置呢?
修改redis.conf中的maxmemory 来设置最大内存。
在64位操作系统中,如果未设置或设置0,代表无限制。而在32位系统中,默认内存大小为3GB。但是实际生产环境下,一般会设置物理内存的四分之三左右。
当客户端执行命令,添加数据时,Redis会检查内存空间大小,如超过最大内存,则触发内存淘汰策略。
在Redis中默认提供了三类八种淘汰策略。
对于这些策略各自的含义,我们还需要一点前置知识的铺垫,这里我们可以看到两个名称:lru、lfu,他俩是什么意思呢?
他们的学名叫做:数据驱逐策略。 其实所谓的驱逐就是将数据从内存中删除掉。
那理解了lru和lfu之后,我们再回来看这三类八种内存淘汰策略各自的机制。
知识小贴士:
对于LRU和TTL相关策略,每次触发时,redis会默认从5个key中一个key符合条件的key进行删除。如果要修改的话,可以修改redis.conf中maxmemory-samples属性值
刚才已经为大家介绍完了redis中的八种内存淘汰策略,那么此时大家可能在想,这些策略我应该如何设置?何时来选择哪种策略使用?
对于这两个问题,来给大家做一个一一解答:
redis默认使用noeviction,我们可以通过修改redis.conf中maxmemory-policy属性值设置不同的内存淘汰策略。
1、Redis只做缓存,不做DB持久化,使用allkeys。如状态性信息,经常被访问,但数据库不会修改。
2、同时用于缓存和DB持久化,使用volatile。如商品详情页。
3、存在冷热数据区分,则选择LRU或LFU。如热点新闻,热搜话题等。
4、每个key被访问概率基本相同,选择使用random。如企业内部系统,访问量不大,删除谁对数据库也造成太大压力。
5、根据超时时间长久淘汰数据,选择选用ttl。如微信过期好友请求。