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内存回收机制的主要内容,如果未能解决你的问题,请参考以下文章