redis内存删除策略 & 缓存逐出算法 | 青训营笔记

174 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第8天

人生没有白走的路,每一步它都算数——考研政治老师孔昱力

image-20230124155953117

1. 内存数据删除策略

1.1 带有时效性的数据

Redis是一种内存级数据库,所有数据均放在内存中,可以通过TTL查看数据状态

  • 17:具有时效性的数据,过期时间剩余17s
  • -1:永久有效的数据
  • -2:内存中不存在的数据(过期了,被删除了,没有定义过的数据)

那时效性数据的存储结构是什么样子的呢?具有时效性的数据其过期时间存放在expires中。

未命名文件 (3)

过期的数据真的从内存中删除了么,不占用内存了么?

并不是的,Redis的过期数据会根据数据删除策略的不同在内存中赖上一段时间。因为数据到期立刻删除必然会占用CPU去删除数据,因此Redis的数据删除目标是在内存占用与CPU占用之间寻找一种平衡。顾此失彼都会造成整体Redis性能下降,甚至引发服务器宕机或内存泄漏。接下来我们聊一聊Redis的数据删除策略。

1.2 数据删除策略

Redis数据删除策略共有三种:

  • 定时删除
  • 惰性删除(懒删除)
  • 定期删除

1.2.1 定时删除

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

总结:用时间换空间。给CPU带来压力。

image-20230124143813003

1.2.2 惰性删除

惰性删除顾名思义,就是key到期了不立即删除,等到下一次访问时判断是否过期,如果已经过期再执行删除操作;如果没有过期就返回数据。

总结:用空间换时间。给内存带来压力。

image-20230124144421847

1.2.3 定期删除

折中定时删除和惰性删除。具体操作:

  • Redis启动服务器初始化时,读取配置server.hz的值,默认为10。

  • 每秒执行server.hzserverCron()databaseCron()activeExpire()

    • databaseCron()对每个数据库进行轮询
    • activeExpire()对每个expires[*]逐一进行检测。
  • 对某个expires[*]检测时,随机挑选W个key检测

    • 如果key超时,删除该key
    • 如果一轮中删除的key数量>W*25%,在该expires[*]内继续执行检测
    • 如果一轮中删除的key数量<=W*25%,则到下一个expires[*]进行检测
    • W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP属性值
  • 参数current_db用于记录activeExpireCycle() 进入哪个expires[*] 执行

  • 如果activeExpireCycle()执行时间到期,下次从current_db继续向下执行

未命名文件 (7)

1.3 小结

删除策略内存CPU特点
定时删除节约内存,无占用不分时段占用CPU资源,频度高拿时间换空间
惰性删除内存占用严重延时执行,CPU利用率高拿空间换时间
定期删除内存定期随机清理每秒花费固定的CPU资源维护内存随机抽查,重点抽查

2. 缓存逐出算法

当新数据进入Redis时,如果内存不足怎么办?

Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()检测内存是否充足。如果内存不满足新加入数据的最低存储要求,Redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法。

注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。

影响缓存逐出的相关配置如下:

  • 检测带有过期时间的数据(可能会过期的数据集server.db[i].expires

    • volatile-lru:挑选最近最少使用的淘汰。也就是淘汰最长时间未被使用的。(Least Recently Used)
    • volatile-lfu:挑选最近一段时间内用的最少的淘汰。(Least Frequently Used)
    • volatile-ttl:挑选快过期的淘汰。
    • volatile-random:任意选择数据淘汰。
  • 检测全库数据(所有的数据集server.db[i].dict

    • allkeys-lru:挑选最近最少使用的淘汰。
    • allkeys-lfu:挑选最近一段时间内用的最少的淘汰
    • allkeys-random:任意选择数据淘汰。
  • 放弃内存逐出

    • no-enviction:禁止内存逐出(redis4.0中默认策略),会导致OOM