Redis也会因为内存不足造成一些错误,或者是因为回收内存时间太久造成系统停顿的情况,所以需要合理设置内存的回收策略,在 Redis 的配置文件 redis.conf 中有一个 maxmemory-policy 的配置项,其中有六种键值淘汰的策略

volatile-lru:采用最近使用最少的淘汰策略,Redis 将回收那些超时的(仅仅是超时的)键值对,也就是它只淘汰那些超时的键值对

allkeys-lru:采用淘汰最少使用的策略,Redis 将对所有的(不仅仅是超时的)键值对采用最近使用最少的淘汰策略

volatile-random:采用随机淘汰策略删除超时的(仅仅是超时的)键值对

allkeys-random:采用随机淘汰策略删除所有的(不仅仅是超时的)键值对,这个策略不常用

volatile-ttl:采用删除存活时间最短的键值对策略

noeviction:根本就不淘汰任何键值对,当内存已满时,如果做读操作,例如 get 命令,它将正常工作,而做写操作,它将返回错误。也就是说,当 Redis 采用这个策略内存达到最大的时候,它就只能读而不能写了

默认采取的是 noeviction 淘汰键值对策略,但是对于如今动辄百万数据的互联网时代,设置到的用户数据太多,如果采取这种策略,将带来非常不好的用户影响和体验,所以一般键值淘汰策略都需要设置好

注意:这里的 ttl 和 lru 算法计算时间都不是一个准确值,也就是说 redis 不会专门准确的去计算这些键值对的时间来对比,而是一个近似的算法

Redis 的配置文件种有一个 maxmemory-samples,默认值为 3
Redis内存回收策略
注意,此时即将过期且剩余超时秒数最短的 A4 却还在内存中,因为它不属于探测样本。这就是 Redis 中采用的近似算法。当设置 maxmemory-samples 越大,则 Redis 删除的就越精确,但是与此同时带来不利的是,Redis 也就需要花更多的时间去计算和匹配更为精确的值
当设置 maxmemory-samples 越大,则 Redis 删除的就越精确,但是与此同时带来不利的是,Redis 也就需要花更多的时间去计算和匹配更为精确的值

缺点:
(1)这种键值对的淘汰策略,往往需要指明键值对的超时时间,这也会增加开发者的工作量
(2)如果是采用 allkeys-random ,则可能会把正在使用的键值对删除,增加系统的不稳定性

总结:所以在控制回收时间的时候,不能太长或者太短,太短会造成回收过于频繁,太长会导致因为回收工作而造成系统停顿

上面已经知道如何淘汰过期的这些过期的 key ,通过以下三种具体的删除策略来对过期 key 进行删除

定时删除

在设置键的过期时间同时,创建一个定时任务,当键到达过期时间时,立即执行对键 key 的删除操作
优点:
对内存友好,保证过期的键能够及时的被删除,从而释放内存空间
缺点:
对 CPU 不友好,如果过期的键比较多,那么定时任务也就多了,CPU 的一部分资源会用在定时任务删除过期 key 上,影响其他的业务处理效率

惰性删除

如果键 key 过期了但是不会立马取删除它,在每次获取键的时候,来检查该键是否过期,如果过期的话对他删除,没有的话直接返回,类似于乐观锁

优点:
对 CPU 友好,不会因为定时任务占用太多的 CPU 资源
缺点:
对内存不友好,如果多个键已经早就过期了,但是这些键又恰巧没被访问到,那么就白白浪费内存空间

定期删除

每隔一定的时间,检查数据库的数据,并且删除其中过期的键,至于检查的范围大小和删除的过期键数量由具体场景决定

它结合了定时删除和惰性删除的优点,并且对他们的缺点进行了中和改进,是一种折中的方案,通过限制删除的键的数量来缓解 CPU 资源的占用影响,并且定期的对过期的键进行删除,减少内存空间的浪费

相关文章: