这是我参与「第五届青训营 」笔记创作活动的第8天
人生没有白走的路,每一步它都算数——考研政治老师孔昱力
1. 内存数据删除策略
1.1 带有时效性的数据
Redis是一种内存级数据库,所有数据均放在内存中,可以通过TTL查看数据状态
17:具有时效性的数据,过期时间剩余17s-1:永久有效的数据-2:内存中不存在的数据(过期了,被删除了,没有定义过的数据)
那时效性数据的存储结构是什么样子的呢?具有时效性的数据其过期时间存放在expires中。
过期的数据真的从内存中删除了么,不占用内存了么?
并不是的,Redis的过期数据会根据数据删除策略的不同在内存中赖上一段时间。因为数据到期立刻删除必然会占用CPU去删除数据,因此Redis的数据删除目标是在内存占用与CPU占用之间寻找一种平衡。顾此失彼都会造成整体Redis性能下降,甚至引发服务器宕机或内存泄漏。接下来我们聊一聊Redis的数据删除策略。
1.2 数据删除策略
Redis数据删除策略共有三种:
- 定时删除
- 惰性删除(懒删除)
- 定期删除
1.2.1 定时删除
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器立即执行对key的删除操作。
总结:用时间换空间。给CPU带来压力。
1.2.2 惰性删除
惰性删除顾名思义,就是key到期了不立即删除,等到下一次访问时判断是否过期,如果已经过期再执行删除操作;如果没有过期就返回数据。
总结:用空间换时间。给内存带来压力。
1.2.3 定期删除
折中定时删除和惰性删除。具体操作:
-
Redis启动服务器初始化时,读取配置
server.hz的值,默认为10。 -
每秒执行
server.hz次serverCron()→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继续向下执行
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