首页天道酬勤redis数据过期策略,redis过期键的删除策略

redis数据过期策略,redis过期键的删除策略

admin 05-05 17:00 154次浏览

众所周知,Redis是一个内存级kv数据库,所有操作都在内存中进行,并定期通过异步操作将数据库数据闪存存储在硬盘上。 因此,它是一种纯粹的内存操作,Redis的性能非常好,每秒钟可以处理10万次以上的读写操作。 内存数据库,但数据可以持久化,支持丰富的数据类型。

由于仅是内存级操作,而且受限于物理内存,因此Redis提供了过期密钥删除和内存销毁策略,可以避免在一定程度上达到内存上限。

本文首先介绍如何为一个key设置过期时间,然后再次介绍这些过期key有哪些处理策略,并分析redis在内存达到上限时采取的策略。

设定有效期限

有四种方法可以在redis中设置过期日期:

expire key seconds :设置key在n秒后过期;

pexpire key milliseconds :设置key在n毫秒后过期;

expire key timestamp :在时间戳后设置key的过期时间(以秒为单位)

pexpireatkeymillisecondstimestamp :将密钥设置为在时间戳之后过期。 准确到毫秒)

那么,让我们来看看具体命令的使用方法吧。

expire: N秒后过期

127.0.0.1:6379设置密钥值

好了

127.0.0.1:6379 expire key 100

(集成器) 1

127.0.0.1:6379 TTL密钥

(integer ) 93

其中命令TTL的全名是time to live,意味着key在n秒后过期。 例如上面的结果93表明key在93s后过期了。

pexpire: N毫秒后过期

127.0.0.1:6379 setkey2value 2

好了

127.0.0.1:6379 pexpirekey 2100000

(集成器) 1

127.0.0.1:6379 pttl key2

(integer ) 94524

pexpire key2 100000表示key2已设置为在100000毫秒(100秒)后过期。

expireat:将在某个时间戳中过期。 准确到秒。

127.0.0.1:6379 set key3 value 3

好了

127.0.0.1:6379 expireatkey 31630644399

(集成器) 1

127.0.0.1:6379 ttl key3

(integer ) 67

到达expired Key3 1630644399 (精确到秒)后过期。 使用TTL查询,可以看到Key3在67s后过期。

在redis中,可以使用time命令查询当前时间的时间戳(以秒为单位)。 以下是一个示例:

127.0.0.1:6379 time

1 )“1630644526”

2 ) " 239640 "

pexpireat:将在某个时间戳上过期。 准确到毫秒。

127.0.0.1:6379 setkey4value 4

好了

127.0.0.133606379 pexpireatkey 4163064499740

(集成器) 1

127.0.0.1:6379 pttl key4

(integer ) 3522

其中,pexpireat key4 1630644499740表示key4在时间戳1630644499740 (精确到毫秒)之后过期。 使用TTL查询,可以看到key4在3522ms后过期。

value是字符串时的过期设置

value可以通过以下几种方式直接操作字符串的过期日期:

设置密钥值ex seconds:n秒后过期

设置密钥值ex milliseconds :设置密钥在n毫秒后过期;

SETEX key seconds value :设置指定key的值及其过期时间。 如果key已经存在,setex命令将替换旧值。

kv对的设定在n秒后到期

127.0.0.1:6379 set k v ex 100

好了

127.0.0.1:6379 ttl k

(integer ) 97

kv对的设定在n毫秒后过期

127.0.0.133606379 setk 2v2 px 100000

好了

127.0.0.1:6379 pttl k2

(integer ) 92483

使用setex设置

127.0.0.1:6379 setex k3 100 v3

好了

127.0.0.1:6379 ttl k3

(integer ) 91

过期的取消

命令:使用永久密钥移除密钥值的溢出

期时间,如下代码所示:

127.0.0.1:6379> ttl k3
(integer) 97
127.0.0.1:6379> persist k3
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -1
可以看出,第一次使用TTL查询K3,97s后就会过期。使用persist命令查询K3的生命周期的结果是-1,表示K3永不过期。

过期策略
redis对过期key的删除策略,有定时删除、定期删除和惰性删除三种。

定时删除
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务执行对key的删除操作。

优点:节约内存,到时就删除,快速释放掉不必要的内存占用

缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量

定期删除
redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?假如redis存了几十万个key,每隔100ms就遍历所有的设置过期时间的key的话,就会给CPU带来很大的负载。

优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。
如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好,如果执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得到释放。

另外最重要的是,在获取某个键时,如果某个键的过期时间已经到了,但是还没执行定期删除,那么就会返回这个键的值,这是业务不能忍受的错误。

惰性删除
定期删除可能会导致很多过期key到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个key,才会被redis给删除掉。这就是所谓的惰性删除。expireIfNeeded(),检查数据是否过期,执行get的时候调用。

优点:节约CPU性能,发现必须删除的时候才删除。

缺点:内存压力很大,出现长期占用内存的数据

换句话说,惰性删除就是用存储空间换取处理器性能

结合上述三种策略的优缺点,redis采取了折中的删除策略,即采用的是定期删除+惰性删除策略。

1、定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略

定期删除+惰性删除是如何工作的呢?

2、定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

3、惰性删除,也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

但是这种方案,仍然存在缺点: 如果定期删除没删除key。然后你也没及时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。

内存淘汰策略
maxmemory 用于指定 Redis 能使用的最大内存。既可以在 redis.conf 文件中设置, 也可以在运行过程中通过 CONFIG SET 命令动态修改。

例如, 要设置 100MB 的内存限制, 可以在 redis.conf 文件中这样配置:

maxmemory 100mb

上述命令设置了redis内存上限,当内存中的数据量达到其设置的上限的时候,就需要采取一定的淘汰策略,否则会影响redis的正常访问。

为了更好的实现这一点,必须针对不同的应用场景提供不同的策略,下面,我们将介绍下redis支持的几种内存淘汰策略。

图片
Redis 提供了以下几种策略供用户选择,其中noeviction 策略的默认策略为。

noeviction:当内存不足以hhdz写入数据时,新写入操作会报错。

allkeys-lru:当内存不足以hhdz写入数据时,在键空间中,移除最近最少使用的key。

allkeys-random:当内存不足以hhdz写入数据时,在键空间中,随机移除某个key。

volatile-lru:当内存不足以hhdz写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

volatile-random:当内存不足以hhdz写入数据时,在设置了过期时间的键空间中,随机移除某个key。

volatile-ttl:当内存不足以hhdz写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

需要注意的是,如果没有设置 expire 的key, 不满足先决条件,那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。

Redis 使用的并不是完全LRU算法。自动驱逐的 key , 并不一定是最满足LRU特征的那个. 而是通过近似LRU算法, 抽取少量的 key 样本, 然后删除其中访问时间最古老的那个key。

驱逐算法, 从 Redis 3.0 开始得到了巨大的优化, 使用 pool(jxdxy) 来作为候选. 这大大提升了算法效率, 也更接近于真实的LRU算法。

在 Redis 的 LRU 算法中, 可以通过设置样本(sample)的数量来调优算法精度。

maxmemory-samples 5

以上就是Redis的六种淘汰策略。关于这六种策略的使用,使用者需要根据自身实际需要,选择合理的淘汰策略。读者可以根据自身需求,再结合下面的笔者经验,进行策略选择。

当部分数据访问频率较高而其余部分访问频率较低,或者数据的使用频率无法预测时,设置allkeys-lru比较合适。

如果所有数据访问概率大致相等,可以选择allkeys-random。

如果开发者需要通过设置不同的ttls来确定数据过期的顺序,此时可以选择volatile-ttl策略。

如果你想让一些数据长期保存,而一些数据可以消除,最好选择volatile-lru或volatile-random。

由于设置expire会消耗额外的内存,如果你打算避免Redis内存浪费在这一项上,可以选择allkeys-lru策略,这样就可以不再设置过期时间,高效利用内存。

经验之谈
对于redis的操作,我们应该慎之又慎。

不要放垃圾数据,及时清理无用数据。

key尽量都设置过期时间。对具有时效性的key设置过期时间,通过redis自身的过期key清理策略来降低过期key对于内存的占用,同时也能够减少业务的麻烦,不需要定期手动清理了。

单Key不要过大,这种key在get的时候网络传输延迟会比较大,需要分配的输出缓冲区也比较大,在定期清理的时候也容易造成比较高的延迟. 最好能通过业务拆分,数据压缩等方式避免这种过大的key的产生。

不同业务如果公用一个业务的话,最好使用不同的逻辑db分开。这是因为Redis的过期Key清理策略和强制淘汰策略都会遍历各个db。将key分布在不同的db有助于过期Key的及时清理。另外不同业务使用不同db也有助于问题排查和无用数据的及时下线。

【Java 框架学习】自学笔记(更新至 类与对象)共享带宽 基础网络 UNet
redis默认删除策略,redis数据更新策略 redis清理策略,redis 内存淘汰策略
相关内容