Redis(过期策略)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis(过期策略)相关的知识,希望对你有一定的参考价值。
参考技术A 被动策略(懒惰策略);主动策略(定期策略)不会,原因当此过期key未被客户端调用并且未达到执行主动策略的时间,此key依旧存在内存中
当某个客户端试图访问key时,发现该key已超时会把此key从内存中删除
当Redis运行到设定的时期时会在具有过期设置的key中随机测试一些key,并且把其中过期的key从内存中删除
Redis的过期key清除策略
简单介绍了Redis如何设置key过期时间,以及Redis过期key删除策略。
1 Redis设置key过期时间
Redis支持为所有类型的数据设置过期时间,对于String
类型,只需要使用setex
命令或者set key value EX seconds
命令:
127.0.0.1:6379> SETEX a 10 sss
OK
127.0.0.1:6379> TTL a
(integer) 8
127.0.0.1:6379> TTL a
(integer) 1
127.0.0.1:6379> TTL a
(integer) -2
对于某个key重新设置值,将会清除该key目前关联的过期时间。更常见的设置过期时间方式是依靠EXPIRE/PEXPIRE
命令来设置或者更新过期时间为ttl秒/毫秒,依靠 EXPIREA/PEXPIREAT
命令来设置或者更新过期时间为timestamp 所指定的 秒数/毫秒数时间戳。
实际上EXPIRE、PEXPIRE、EXPIREAT
三个命令的底层都是使用PEXPIREAT
命令来实现的,且底层的时间进度都是毫秒。
PERSIST
命令则可以移除一个键的过期时间。
检查剩余时间需要使用TTL
或者PTTL
命令,非别返回秒和毫秒级别的剩余时间,它们都是通过计算键的过期时间和当前时间之间的差来实现的。
2 Redis过期key删除策略
在Redis中,内存的大小是有限的,所以为了防止内存饱和,需要实现某种键淘汰策略。主要有两种方法,一种是当Redis内存不足时所采用的内存释放策略。另一种是对过期key进行删除的策略,也可以在某种程度上释放内存。
Redis采用的默认内存释放策略是noeviction-不删除,达到最大内存时,如需更多内存(存入数据),则操作报错,内存释放策略我们之前就已经讲过了:Redis的内存淘汰策略;默认的过期key删除策略则是惰性删除+定期删除的方案;
常见的过期数据删除策略如下:
- 定时删除
- 在设置key的过期时间的同时,创建一个定时器,让定时器在key的过期时间来临时,立即执行对key的删除操作;
- 定时删除操作对于内存来说是友好的,内存不需要操作,而是通过使用定时器,可以保证尽快的将过期key删除,但是对于CPU来说不是友好的,如果过期key比较多的话,起的定时器也会比较多,每一个定时器会占用到CPU的资源;
- 惰性删除
- 不管key有没有过期都不主动删除,但是每次从键空间中获取键值时,都检查取得的key的过期时间,如果过期的话,返回null,然后删除key即可;
- 惰性操作对于CPU来说是友好的,过期key只有在程序读取时判断是否过期才删除掉,而且也只会删除这一个过期键,但是对于内存来说是不友好的,如果多个key都已经过期了,而这些key又恰好没有被访问,那么这部分的内存就都不会被释放出来;
- 定期删除
- 每隔一段时间,程序就对数据库进行一次检查,删除掉过期key;
- 定期删除是上面两种方案的折中方案,每隔一段时间来删除过期key,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,除此之外,还有效的减少内存的浪费;但是该策略的难点在于间隔时长,这个需要根据自身业务情况来进行设置,并且可能由于扫描不及时,导致过期的key也被返回。
目前,Redis采用的是惰性删除+定期删除的方案。Redis 的定期扫描只会扫描设置了过期时间的键,Redis 通过一个单独的过期字典expires(可以看作是 hash 表)来保存设置了过期时间的数据过期的时间,所以不会出现扫描所有键的情况,即使如此,redis也是默认是每隔 100ms 就随机抽取过期字典中的 key,检查其是否过期,如果过期就删除。如果不定时随机抽查而是全部扫描,那么将可能有很长的时间导致服务对外不可用,这是无异于一场灾难。
由于是随机扫描,那么对于已经过期但没有被扫描到的key怎么办呢,没关系,还有惰性删除,在获取某个 key 的时候,Redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,返回null。
过期字典dict的key是一个指针,这个指针指向键空间中的某个key对象(也即是某个数据库键)。过期字典的值是一个long long类型的整数,这个整数保存了key所指向的数据库key的过期时间——一个毫秒精度的UNIX时间戳。在实际中,键空间的key和过期字典的key都指向同一个key对象,所以不会出现任何重复对象,也不会浪费任何空间。
typedef struct redisDb {
dict *dict; //键空间,存放所有的key-value键值对
dict *expires; //设置了过期时间的key到它的过期时间的键值对
} redisDb;
PERSIST
命令在过期字典中查找给定的key,并解除key和值(过期时间)在过期字典中的关联。
相关文章:
- https://redis.io/topics/data-types
- https://redis.io/topics/data-types-intro
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
以上是关于Redis(过期策略)的主要内容,如果未能解决你的问题,请参考以下文章