您的位置 首页 技术

Redis删除策略和逐出策略

本文知识点 过期数据概念 数据删除策略 逐出算法 过期数据 先来看三个key值,分别为sex、name、age。 这三个值设置的指令为 set name kaka setex ag…

本文知识点

过期数据概念

数据删除策略

逐出算法

过期数据

先来看三个key值,分别为sex、name、age。

这三个值设置的指令为 set name kaka setex age 100 24 setex sex 10 1

在redis中我们可以使用ttl来获取某个key的状态,下面我们来使用ttl分别获取一下上边name、age、sex的状态

可以看到出来了三个值,分别为 -1 775 -2

那么这三个值给出的信息是什么呢!

  • -1 表示永久有效的数据
  • 775 这个值是设置在age上,使用的指令为setex age 1000 24,表示为剩余有效时间
  • -2 表示已经过期的数据,或者是被删除的数据,或者说是么有定义的数据

过期数据的存储结构

  • 当我们设置一个带有时效性的name时,redis存储的是一个内存地址0x10101
  • 然后redis会再开辟一个空间用来存储带有时效性的key
  • 但是存储方式是key对应的内存地址 和 过期时间那么今天我们所说的redis删除策略,就是删除的这部分数据。

定时删除

定时删除就是写一个定时器,然后当key的时间过期后,定时器任务立即对过期的key进行删除

优点:可想而知key到期就删,肯定对内存时最友好的,节约内存

缺点:redis单线程的特性是所有的命令都在按照一定的顺序进行执行。key值到期就删cpu的压力就会变大,会直接影响到redis服务器响应时间和IO

定时删除就是用时间来换取空间

当执行完定时删除后,key值对应的数据会被删除,同时在过期的内存区里边也会直接删除。

惰性删除

在来看这个图当key值过期后不会直接删除,那是什么时候删除呢!继续往下看

当我们使用惰性删除时,数据到期了也不会自动删除,那么他的删除方式是,在下一次在获取这个key值时,会做一个判断,判断这个key是否过期,如果过期了在执行删除。

也就是说当再次执行get name时 会走一个函数expirelfNeeded() 这个函数就是判断此key是否过期的。过期的返回nil,然后从内存在进行删除

优点:会减少一定的CPU性能,只有到必须要删的时候才会删除

缺点:那肯定就是内存压力大了,例如一些热点新闻,热点过了就基本没人访问了,没有人访问这个key就一直存在,就会出现长期占用一定的内存空间

也就说这种方式是用空间换时间

定期删除

在上文中我们提及了俩种删除方式,一种是定时删除,一种是惰性删除。一个是用空间换时间。一个是用时间换空间。俩种方案都是比较极端的方式。那么接下来我们在来看看定期删除的实现方案。

先来看一下redis的存储空间,一共有默认为16个,在redis.conf里边有一个配置参数database这个参数控制的。每个数据库都有自己的过期分区,里边存储就是数据地址 和 数据过期时间。

实现方式

redis在启动时,会取读取server下的hz的值,默认为10。这个值直接在终端使用info server就可以查看的到

然后会每秒钟执行server下hz次 进行serverCron()轮询

继续使用databasesCron对redis的16个库进行挨个访问信息

访问时候会再执行activeExpireCycel对每个expires[*]逐一进行检测,每个执行的时间为250ms / server hz这个参数

在对每个expirs[*]逐一检测时,会随机拿出ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC个可以进行检测

  • 如果key超时,直接删除key
  • 一轮中删除的key数量>ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC*25%继续循环该过程
  • 如果一轮中删除的key数量<=ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC25% ,检查下一个expires[]

那么现在问题来了,我们的250ms / hz这个时间执行完了,但是把expires的16个数据库没有循环完怎么办呢! 下次来在循环那个库呢! 其实这个值是有存的,就是current_db这个值。这个值会记录activeExpireCycel 下次进入那个expires[*]执行

特点1:CPU使用没有高峰值,检测频率自定义设置

特点2:内存压力不会很大, 长时间占用的内存会被持续的清理

逐出算法

在上文中我们说了三种删除策略,但是这三种策略都是相对于设置了有效期的key才会有效。

那现在我们的redis使用的内存不足了,就会使用逐出策略来保证redis的正常使用。

redis在每次执行命令前会调用freeMemorylfNeeded()检测内存是否充足,当不充足时就会清理一些key,这种清除数据的策略称为逐出策略。

redis最大可使用内存的参数为:maxmemory 默认为0 指的是占用物理内存的比例 一般设置50%就可以了

每次选取待删除key的个数:maxmemory-samples

删除策略:maxmemory-policy

下面我们来着重说明删除策略

  • 检测易失数据(也就是我们设置了有效期,但是还没有到期的数据,就是上文expires[*])
    • volatile-lru:挑选最近少使用的数据
    • volatile-lfu:挑选最近使用次数最少的数据
    • volatile-ttl:挑选将要淘汰的数据
    • volatile-random:随机选择

接下来看一幅图

  • 9s就是现在的时间
  • 距离9s最长的一个key就是age
  • 使用次数最少的就是gender这个key
  • 如果按照volatile-lru就会把age删除掉
  • 如果按照volatile-lfu就会把gender删除掉
  • 检测全部数据
    • allkeys-lru:挑选最近少使用的数据
    • allkeys-lfu:挑选最近使用次数最少的数据
    • allkeys-random:全库随机删除
  • 放弃数据驱逐
    • no-enviction : 数据不会进行任何的删除,直到内存用完,引发oom错误。

总结

以上就是redis对数据的删除策略和逐出策略。

这里就一个注意点就是在逐出策略中,易失数据指的是设置了过期时间的key,并非永久性的值。

全库是指的全部的值,设置了过期时间和永久数据。

以上就是Redis删除策略和逐出策略的详细内容,更多请关注24课堂在线网其它相关文章!

本文来自网络,不代表24小时课堂在线立场,转载请注明出处:https://www.24ketang.cn/65825.html

为您推荐

返回顶部