本文主要讲解了 redis 缓存过期淘汰策略, 后面我们会结合 LeetCode 的 LRU 算法题目,自己动手实现 LRU 的算法案例(LRU 算法实践)。
常见的问题
1、生产上你们的 redis 设置的内存多少?
2、如果配置、修改 redis 内存的大小?
3、如果内存满了你怎么办?
4、redis 清理内存的方式?定期删除和惰性删除了解过吗?
5、redis 缓存淘汰策略
6、redis 的 lru 了解过吗?是否可以手写一个 lru 算法?
redis 内存满了怎么办?
redis 默认内存多少? 在哪里查看?如何设置和修改?
1、查看 redis 最大占用内存?
2、redis 默认内存多少可以用?
如果不设置最大内存大小或者设置对打内存大小 0 , 在 64 位操作系统下不限制内存大小,在 32位操作系统下最多使用 3G 内存
3、一般生产上你如何配置?
一般推荐 reids 设置内存为最大物理内存的 3/4
4、如何修改 redis 内存设置?
通过修改文件配置
通过命令修改
5、什么命令查看 redis 内存使用情况?
info memory
如果要是 redis 的内存满会怎么样?如果redis 内存使用超过了最大设置会怎么样?
1、如果要是 redis 的内存满会怎么样?如果redis 内存使用超过了最大设置会怎么样?
如果 redis 内存被打满了,会提示 “(error) OOM command not allowed when used memory > 'maxmemory'.”
结论
- 设置了 maxmemory 的选项,加入 redis 内存使用达到了上限
- 没有加上过期时间就会导致数据写满 maxmemory 为了避免这个问题,下面我们将在内存淘汰策略中详细阐述
redis 缓存淘汰策略?
1、往 redis 里面写了数据但是为什么会没了?
redis 过期键的删除策略
- 如果一个键是过期的,那它到了过期时间之后是不是马上就从内存中被删除了呢?
- 肯定不是
- 如果不是,那过期之后到底什么时候被删除?? 是一个什么操作
三种不同的删除策略
1、定时删除
Redis 不可能时时刻刻遍历所有被设置了生存时间的key, 来检查数据是否已经到达过期时间,然后对他进行删除。
立即删除能把整内存中数据最大的新鲜度,因为它保证过期键值会在过期后马上被删除,其所占的内存也会随之释放,但是立即删除对 CPU 是最不友好的。因为删除操作会占用 CPU 的时间,如果刚好碰到 CPU 很忙的时候,比如正在做交集或者排序等计算的时候,这个时候会给 CPU 造成额外的压力,让 CPU 心累,有时候需要删除。忙死。。。。
这个时候会产生大量的性能消耗,同时也会影响数据的读取操作。
总结:对 CPU 不友好,用处理器吸能换存储空间(拿时间换空间)。
2、惰性删除
数据到达过期时间,不做处理,等下次访问该数据时,
如果未过期,返回数据:
发现已过期,删除,返回不存在
惰性删除策略的缺点是,它对内存最不友好的。
如果一个键已经过期,而这个键仍保留在数据库中, 那么只要这个过期键不被删除,它所占用的内存就不会释放。
在使用惰性删除策略时,如果数据库有非常多的过期键,而这这些过期键恰好🈶️没有被访问的话,那么他们也许永远不会被删除(除非用户手动执行 flushdb), 我们甚至可以将这种情况看作是一种内存泄漏 - 无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放他们,这对于运行状态非常依赖与内存的 Redis 服务器来说,肯定不是一个好消息。
总结:对 memory 不友好,用存储空间换处理器性能(拿空间换时间)
3、上面两种方案都走极端
定期删除
定期删除策略是前面两种策略的择中
定期删除策略每间隔一段时间执行一次删除过期键操作,并且通过限制删除操作执行的时间和频率来减少删除操作对 CPU 时间的影响。
周期性轮询 redis 库中时效性数据,采用随机抽泣的策略,利用过期数据占比的方式控制删除频度
特点1:CPU 性能占用设置有峰值, 检测频度可自己自定义设置。
特点2: 内存压力不是很大,长期占用内存的冷数据会被持续清理
总结:周期性抽查存储空间(随机抽查,重点抽查)
举个例子:
redis 默认每100ms 检查,是否有过期的 key, 如果有 key 则删除。注意: redis 不是间隔 100ms 将所有的 key 检查一次而是随机抽取进行检查(如果每间隔 100ms , 全部 key 进行检查,redis 直接进入 icu ). 如果只采用定期删除策略,会导致很多 key 到时间没有删除。
定期删除策略的难点是确定删除操作执行的时长和频率。如果删除操作执行得太频繁,或者执行操的时间太长,定期删除策略就会退化成定时删除策略,以至于 CPU 时间过多的消耗在删除过期键上,如果删除操作执行得太少,或者珍惜i给你的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。因为,如果采用定期删除策略的话,服务器必须根据情况,合理的删除操作执行时间长短和执行频率。
总结: 定期抽样 key , 判断是否过期
依旧有漏网之鱼
上述步骤都通过了,还有漏洞吗?
1、定期删除,从来没有被抽查到
2、惰性删除,也从来没有被点中过
上述2步骤 ==> 大量过期 key 堆积唉内存中,导致 redis 内存空间紧张或者很快耗尽。
必须要要有一个更好的兜底方案 。。。。。
内存淘汰策略
redis.conf
redis 的 8 种淘汰策略
官方配置文件中的原文:
volatile-lru -> Evict using approximated LRU among the keys with an expire set.
allkeys-lru -> Evict any key using approximated LRU.
volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
allkeys-lfu -> Evict any key using approximated LFU.
volatile-random -> Remove a random key among the ones with an expire set.
allkeys-random -> Remove a random key, any key.
volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
noeviction -> Don't evict anything, just return an error on write operations.
默认配置: noeviction
中文总结
1、noevication : 不会驱逐任何 key (默认)
2、allkeys-lru: 对所有的 key 使用 lru 算法进行删除
3、volatile-lru: 对所有的设置了过期时间的 key 进行 lru 算法进行删除
4、allkeys-random: 对所有 key 随机删除
5、volatile-random: 对所有设置了过期时间的 key 随机删除
6、volatile-ttl :马上删除要过期的 key
7、allkeys-lfu: 对所有 key 进行 lfu 算法进行删除
8、volatile-lfu: 对所有设置了过期时间的 key 使用 lfu 算法进行删除
总结:
- 2 * 4 = 8
- 两个维度: 过期键中筛选;所有键中筛选
- 4个方面: LRU ,LFU , random , ttl
- 8 个选项
你平时用那种?
一般平时用 : allkeys-lru
如何修改
1、命令方式
2、配置文件
作者:心城以北
链接:https://juejin.cn/post/7063998360469897229
来源:稀土掘金
网友评论