首页天道酬勤redis默认删除策略,redis存储

redis默认删除策略,redis存储

admin 05-05 17:04 162次浏览

文章前言1、过期数据删除策略1.1定时删除1.2惯性删除1.3定期删除2、内存销毁策略

前言

在将Redis用于缓存的过程中,我们一般会对key设定一定的有效期。 Redis中除了包含用于设置字符串类型特定过期日期的命令setex外,还必须依赖expire命令设置过期日期。

命令格式:

EXPIRE key ttl命令用于将键key的生存时间设置为ttl秒PEXPIRE key ttl命令用于将键key的生存时间设置为ttl毫秒EXPIREAT key timestame命令键key的生存时间为timestame指定的秒数te 用于设置为IRE的命令AT key timestame命令将密钥key的生存时间设置为由timestame指定的毫秒时间戳。 此外,persist命令还会删除密钥的过期时间。 那么再考虑一个问题吧。过期时间除了有助于缓解内存的消耗,还有什么其他么?

在很多情况下,在我们的业务场景中,某个数据必须只存在于某个时间段。 例如,我们的邮件验证码可能只在一分钟内有效,用户登录的token可能只在一天内有效。 使用传统数据库处理时,通常自己判断过期,这更麻烦,性能也更差。那么Redis是如何判断数据是否过期的呢?

最初,Redis使用过期词典(可以视为hash表)来存储数据过期的时间。 过期词典的关键

Redis数据库中的密钥。 过期词典的值为长整型整数,保存有密钥处

的数据库密钥的过期时间。 UNIX时间戳,以毫秒为单位。

过期词典存储在名为redisDb的结构中:

typedefstructredisdb { . dict * dict; //保存数据库中所有键值和dict *expires的数据库密钥区域//过期词典、密钥过期. } Redis词典类似于java的HashMap。 如果Redis词典封装了哈希表,就很容易理解了。 这部分对Redis词典的结构理解和java HashMap的区别以及阿里面试官: hashmap熟悉吗? 好的,那么谈谈Redis词典吧!

一、过期数据的删除策略如果你把批密钥设置为只能活一分钟,一分钟后,Redis是怎么删除这些密钥的呢?

Redis的过期数据删除策略分为以下三部分:

1.1定时删除计划删除策略是指每当key过期时,计时器(timer )就会启动,并在key过期后立即执行key删除操作。优点:此策略对内存非常有用,因为它在计时器到期时清除过期的密钥,并且不占用额外的内存。缺点:毫无疑问,此策略对CPU最不友好。 在过期密钥较多的情况下,删除过期密钥的行为可能会占用相当大的CPU时间,在内存不紧张但CPU时间非常紧张的情况下,会将大量的CPU时间浪费在删除过期策略上,而不是处理客户端的请求。

1.2惯性删除惯性删除策略只需在每次获取密钥时先确定expires对象中的密钥是否过期,如果已过期则删除密钥,否则返回与该密钥对应的数据。优点:此策略对CPU最容易使用,仅在取出key时对key进行过期检查。 也就是说,只有在不能时才进行删除,删除的目标仅限于当前正在处理的密钥,而不需要CPU时间删除其他无关的过期密钥。缺点:该战略的缺点是对内存最不友好。 如果一个key已过期,且该key仍留在数据库中,则除非删除该过期key,否则不会释放正在使用的内存。 例如,如果数据库中有非常多的过期密钥,且这些过期密钥未被访问,则它们可能不会被删除,除非用户手动运行flushdb命令将其清空。 因此,大量无用的脏数据占用大量内存,存在内存泄漏的风险。

1.3发现,定时删除比定期删除更不善待CPU,惯性删除会浪费内存,存在内存泄漏风险。

定期删除策略是CPU和内存消耗之间的折衷,通过每隔一定时间执行删除过期密钥的操作,限制删除操作执行的时长频率,从而向CPU时间提供删除操作否则,删除操作可能会影响CPU时间

此类策略的最大难点是如何设置删除操作的执行时间和频率。 的设定过于频繁,会退化为定时删除,浪费大量的CPU资源,设置间隔时

间长一点,则又可能出现内存大量堆积。

Redis实际上使用的是惰性删除和定期删除两种策略,通过配合使用,服务器可以很好的平衡 CPU 和内存。那么是怎么实现的呢?我们在《Redis设计与实现》中能看到:
惰性删除策略的实现:
每次取数据的时候都会调用过滤函数(db.c/expireIfNeeded),该函数主要用来判断键是否过期,如果过期,则删除键,否则,则取得对应键的值。

定期删除键的策略实现:

过期键的定期删除策略由 redis.c/activeExpireCycle函数实现,每当 Redis 的服务器周期性操作 redis.c/serverCron函数执行时, activeExpireCycle 函数就会被调用,它在规定的时间内分多次遍历服务器的各个数据库,检查数据库的 expires 字典中部分键(相当于分页查询)的过期时间,并删除它。步骤如下:
 1、函数每次运行时,都从一定数量的数据库取出一定数量的随机键进行检查,并删除其中的过期键。
 2、全局变量 current_db 会记录当前 activeExpireCycle 函数的检查进度,并在下一次 activeExpireCycle 调用时,接着上一次的进度进行处理。
 3、随着 activeExpireCycle 函数的不断执行,服务器中的所有数据库都会被检查一遍,当到达最后时,把 current_db 设置为 0,然后又重新开始,如此循环下去。

但是,仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉
了很多过期 key 的情况。这样就导致⼤量过期 key 堆积在内存⾥,然后就Out of memory了。
怎么解决这个问题呢?答案就是: Redis 内存淘汰机制。

二、内存淘汰策略

相关问题:MySQL ⾥有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数
据都是热点数据?

Redis 提供 8 种数据淘汰策略:

1. volatile-lru:从已设置过期时间的数据集中挑选最近最少使⽤的数据淘汰。
2. volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
3. allkeys-lru:当内存不⾜以容纳新写⼊数据时,在键空间中,移除最近最少使⽤的 key(这个是最常⽤的)
4. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰。
5. volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
6. no-eviction:禁⽌驱逐数据,也就是说当内存不⾜以容纳新写⼊数据时,新写⼊操作会报 错OOM。
4.0 版本后增加以下两种:
7. volatile-lfu:从已设置过期时间的数据集中挑选最不经常使⽤的数据淘汰。
8. allkeys-lfu:当内存不⾜以容纳新写⼊数据时,在键空间中,移除最不经常使⽤的 key。

相关术语解释:LRU:least recently used,LFU:least frequently used

参考文章:
1、Redis过期键删除策略
2、《JavaGuide4.0》

【Java 框架学习】自学笔记(更新至 类与对象)删除ULB 负载均衡 ULB
redis选举算法,redis删除过期key 硬件,stc8f2k08s2引脚图
相关内容