Redis_06_Redis内存回收机制

Posted 毛奇志

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis_06_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。

二、生存时间和三种过期策略

过期策略包括三种:立即过期 惰性过期 定期过期

2.1 生存时间的设置与读取

介绍四个命令(和TTL time to live 生存时间有关的),用表格清晰些,如下:

命令含义
EXPIRE设置剩余生存时间,以秒为单位,将键key的生存时间设置为ttl秒
PEXPIRE设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为ttl毫秒
EXPIREAT设置剩余生存时间,以秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳
PEXPIREAT设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳
TTL返回指定key的剩余生存时间,以秒为单位
PTTL返回指定key的剩余生存时间,以毫秒为单位

这个表格给出了指定key的过期时间的存储,这里需要注意一个点,设置指定key生存时间一共有四个命令EXPIRE PEXPIRE EXPIREAT PEXPIREAT,这里展示四个命令底层关系,如图:

我们可以看到,四个命令底层关系:四个设置生存时间的命令,底层最终都是使用PEXPIREAT命令去实现的。

2.2 生存时间的底层保存(过期字典)

redis是基于key-value存储的一个非关系型数据库,对于每一个记录的key,都有一个生存时间TTL,上面介绍了指定key的生存时间的读写,那么,redis中每一个key的生存时间是底层是如何存储的呢?答案是使用“过期字典”存储。

过期字典引入:redisDB结构的expires字典保存了数据库中所有键的过期时间,这个expires字典就是过期字典。

过期字典的键:是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)。

过期字典的值:是一个long long类型的整数 ,这个整数保存了键所指向的数据库键的过期时间,即—个毫秒精度的UNIX时间戳。

展示了一个带有过期字典的数据库例子,在这个例子中,键空间保存了数据库中的所有键值对,而过期时间则保存了数据库中所有按键值对的过期时间。

生存时间(过期时间)的添加和删除略过。

2.3 过期字典如何处理过期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

四、尾声

内存使用未达到最大内存极限,有三种删除方式:定时删除、惰性删除、定期删除;
内存使用已达到最大内存极限,有八种淘汰方式:volatile-lru、allkeys-lru、allkeys-lru、allkeys-lfu、volatile-random、allkeys-random、volatile-ttl、noeviction。

Redis内存回收机制,完成了。

以上是关于Redis_06_Redis内存回收机制的主要内容,如果未能解决你的问题,请参考以下文章

redis实战_06_持久化机制

redis内存回收

redis过期策略和内存淘汰机制

Redis 系列(04-2)Redis原理 - 内存回收

redis内存回收——过期淘汰

Redis原理篇之通信协议和内存回收