Redis_09_Redis内存回收机制
Posted 毛奇志
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis_09_Redis内存回收机制相关的知识,希望对你有一定的参考价值。
文章目录
一、前言
问题:redis为什么需要内存回收机制?
回答:内存回收就是数据过期,redis的数据都是存放在内存里面,当然可以通过RDB和AOF持久化到磁盘,但是运行的时候还是要加载到内存里面的,如果key-value键值对越来越多,撑爆了内存引起机器重启等不好境况,所以redis自带内存回收机制,清理掉一些访问频率不高的key-value键值对。
本文内容:
内存使用未达到最大内存极限,有三种删除方式:定时删除、惰性删除、定期删除;
内存使用已达到最大内存极限,有八种淘汰方式:volatile-lru、allkeys-lru、allkeys-lru、allkeys-lfu、volatile-random、allkeys-random、volatile-ttl、noeviction。
二、生存时间和三种过期策略
过期字典如何处理过期key,即过期key的删除,过期策略包括三种:立即过期 惰性过期 定期过期
被动删除/惰性删除:当客户端尝试访问某个key时,发现当前key已经过期了,就直接删除这个key。当然,有可能会存在一些key,一直没有客户端访问,就会导致这部分key一直占用内存,因此加了一个 主动删除/定时删除 方式。
主动删除/定时删除:Redis定期扫描期间中的key进行删除,它的删除策略是:
(1) 从过期键中随机获取20个key,删除这20个key中已经过期的key。
(2) 如果在这20个key中有超过25%的key过期,则重新执行当前步骤。实际上这是利用了一种概率算法。
一表总结,如下:
删除方式(过期key删除) | 解释名称 | 含义 | 删除类型 | 优点 | 缺点 | 备注 |
---|---|---|---|---|---|---|
定时删除 | 内部含有定时器,故称为定时删除 | 在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。 | 主动删除 | 对内存友好,过期key尽快被删除,被释放过期key的内存 | 对CPU时间不友好,较快删除key,占用CPU时间 | 该方式redis服务器中需要创建大量定时器,不现实,舍去。 |
惰性删除 | 一定要等到使用该键的时候才删除过期key,比较懒惰,故称为惰性删除 | 放任键不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 | 被动删除 | 对CPU时间友好,过期key尽可能慢地删除,取出时才检查是否过期,尽可能少的占用CPU时间 | 对内存不友好,过期地key删除不及时,一定要等到再次取出时才检查删除,这段时间内占用内存 | 由于存在着很多过期的key没有及时被删除,容易造成内存泄露 |
定期删除 | 均衡定时删除和惰性删除,得到一个合适的时间段删除,故称为定期删除 | 每隔一段时间,程序就会对数据库进行一个检查,删除里面的过期键。至于要删除多少个过期键,以及要检查多少个数据库,则由算法决定。 | 主动删除 | 定时删除和惰性删除的综合,合理使用CPU和内存 | 难以确定删除操作执行的时长和频率 | 若删除频繁,则接近定时删除,消耗太多CPU时间;若删除太少,则接近惰性删除,消耗内存。 |
总结:对于设置了过期时间的key,到了过期时间会使用定时删除掉;对于没有设置过期时间的key,Redis中同时使用了惰性删除和定期删除两种过期策略。
三、淘汰策略
Redis的内存淘汰策略,是指当内存使用达到最大内存极限的时候,需要使用淘汰算法来决定清除掉哪些数据,以保证新数据的写入。所以,这里涉及到两个问题:
第一,最大内存极限数值是多少?回答:可以自己设置
第二,常用的淘汰策略有哪些?
回答:淘汰策略分为两种
LRU,Least Recently Used:最近最少使用
LFU,Least Frequently Used
内存淘汰策略执行的一个前提是 内存使用达到最大内存极限,一般来说,只要三种删除 定时删除 惰性删除 定期删除 搞好,不会出现这种情况。
3.1 最大内存设置
最大内存极限数值是多少?如下:
./redis-cli --raw
config get maxmemory
config set maxmemory 512MB
config get maxmemory
3.2 淘汰策略
查看当前的redis使用的哪种淘汰策略,需要查看redis.conf文件,如下:
先看一下都有哪些淘汰策略?一共八种。
从前缀针对的对象来分:volatile针对设置了ttl的key,allkeys是针对所有key
从后缀使用的方法来分:
LRU,Least Recently Used:最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
LFU,Least Frequently Used:最小频率使用。Redis 4.0版本新增。
random:随机删除。
策略 | 含义 |
---|---|
volatile-lru | 针对带有过期时间的键,选择最远使用,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction |
allkeys-lru | 针对所有键(不管有没有设置超时时间),选择最远使用,直到腾出内存为止。 |
volatile-lfu | 针对带有过期时间的键,选择最少频率使用的,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction |
allkeys-lfu | 针对所有键(不管有没有设置超时时间),选择最少频率使用的,直到腾出内存为止。 |
volatile-random | 针对带有过期时间的键,随机选择删除,直到腾出内存为止。如果没有可以删除的键对象,回退到 noeviction |
allkeys-random | 针对所有键(不管有没有设置超时时间),随机选择删除,直到腾出内存为止。 |
volatile-ttl | 针对带有过期时间的键,删除最近ttl将要过期的数据。如果没有可以删除的键对象,回退到 noeviction |
noeviction | 默认策略,不会删除操作,会拒绝所有写入操作并返回客户端错误信息OOM,此时Redis只响应读操作 |
如果没有设置ttl,那么 volatile-lru volatile-lfu volatile-random volatile-ttl 相当于 noeviction ,不做内存回收。
建议使用 volatile-lru,在保证正常服务的情况下,优先删除最近最少使用的key.
./redis-cli --raw
config get maxmemory-policy
config set maxmemory-policy volatile-lru
config get maxmemory-policy
四、尾声
Redis内存回收包括两个部分,如下:
内存使用未达到最大内存极限,有三种删除方式:定时删除、惰性删除、定期删除;
内存使用已达到最大内存极限,有八种淘汰方式:allkeys-lru、volatile-lru、allkeys-lfu、volatile-lfu、volatile-random、allkeys-random、volatile-ttl、noeviction。
问题1:为什么Redis需要淘汰策略,而不是扫描全部设置了过期时间的key呢?
回答1:因为Redis里面所有的key都有过期时间,如果全部扫描压力太大,全扫描跟你去查数据库不带where条件不走索引全表扫描一样,不显示。
问题2:如果一直没随机到很多key,里面不就存在大量的无效key了,如何处理?
回答2:定时删除+惰性删除
定时删除:每隔一段实践删除一些,对CPU不友好,对内存友好;
惰性删除:不主动删,我等你来查询了我看看你过期没,过期就删去redis中这个key,没过期就取出,对CPU友好,对内存不友好。
问题3:如果某些key,定时删除没删,我也没查询(则惰性删除也没有删除),如何?
内存淘汰机制!官网上给到的内存淘汰机制是六个:
(1) noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
(2) allkeys-lru: 尝试回收距离现在最远使用的键(LRU),使得新添加的数据有空间存放。
(3) volatile-lru: 尝试回收距离现在最远使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
(4) allkeys-lfu:尝试回收最少频率使用的键(LFU),使得新添加的数据有空间存放。
(5) volatile-lfu:尝试回收最少频率使用的键(LFU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
(6) allkeys-random: 回收随机的键使得新添加的数据有空间存放。
(7) volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
(8) volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
最后,如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
Redis内存回收机制,完成了。
以上是关于Redis_09_Redis内存回收机制的主要内容,如果未能解决你的问题,请参考以下文章