目录
一、redis数据的淘汰策略
1.volatile-ttl:从已经设置过期时间的数据集中,挑选即将要过期的数据淘汰。
2.volatile-random:从已经设置过期时间的数据集中,随机挑选数据淘汰。
3.volatile-lru:从已经设置过期时间的数据集中,挑选最近最少使用的数据淘汰。
4.volatile-lfu:从已经设置过期时间的数据集中,挑选最近使用次数最少的数据淘汰。
5.allkeys-random:从所有的数据集中,随机挑选数据淘汰。
6.allkeys-lru:从所有的数据集中,挑选最近最少使用的数据淘汰。
7.allkeys-lru:从所有的数据集中,挑选最近使用次数最少的数据淘汰。
8.no-enviction:禁止淘汰数据,报错 OOM occured not allowed when used memory。
二、redis过期键的删除策略
1.定时删除:在设置键的过期时间的同时,创建一个timer,让定时器在键的过期时间到达时,立即执行对键的删除操作。(主动删除)
对内存友好,但是对cpu时间不友好,有较多过期键的而情况下,删除过期键会占用相当一部分cpu时间。
2.惰性删除:放任过期键不管,但是每次从键空间中获取键时,都检查取到的键是否过去,如果过期就删除,如果没过期就返回该键。(被动删除)
对cpu时间友好,程序只会在取出键的时候才会对键进行过期检查,这不会在删除其他无关过期键上花费任何cpu时间,但是如果一个键已经过期,而这个键又保留在数据库中,那么只要这个过期键不被删除,他所占用的内存就不会释放,对内存不友好。
3.定期删除:每隔一段时间就对数据库进行一次检查,删除里面的过期键。(主动删除)
采用对内存和cpu时间折中的方法,每个一段时间执行一次删除过期键操作,并通过限制操作执行的时长和频率来减少对cpu时间的影响。难点在于,选择一个好的策略来设置删除操作的时长和执行频率。
4.redis实际使用的过期键删除策略
「Redis实际使用的是惰性删除+定期删除的策略。」
通过这两种方式可以很好的利用CPU时间以及避免内存浪费的情况。
三、redis惰性删除策略以及定期删除策略的实现。
1.惰性删除策略的实现
惰性删除策略由 expireIfNeeded 函数实现,所有读写数据库的 Redis 命令在执行之前都会调用 exipreIfNeeded 函数对输入键进行检查。
- 如果键过期,会将键删除并返回空。
- 如果键没有过期,则不做操作。
2.定期删除策略的实现
定期删除策略由 activeExpireCucle 函数实现,被调用时,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的 expires 字典中随机检查一部分键的过期时间,并删除其中的过期键。
- 函数每次运行时,都是从一定数量的数据库键中随机取一定数量的键进行检查,并删除其中的过期键。
- 有一个全局变量 current_db 会记录当前 activeExpireCycle 函数检查的进度,并且下一次 函数执行时,接着上一次的进度进行处理。如,当前 activeExpireCycle 函数执行到了 10, 讲 current_db = 10;然后下一次函数执行时,从 current_db 取到 10 继续执行。
- 当所有的数据库键都被检查完时, current_db = 0。
单个节点 redis支持最大并发 10W PS,建议 最大存储数据量不超过 10G,超过10G不利于节点恢复及主从节点数据同步
四、redis刷盘参数说明
save <seconds> <changes>
指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合。
#Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
#分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改
以及60秒(1分钟)内有10000个更改,就将数据同步到数据文件。
Q1:为什么时间越长,越少的变更,就同步数据,而不是时间越长,越多的变更,才同步数据?
这是为了到达一定时间,只需要很少的更改(限制条件越低),就同步数据。通俗的讲,就是时间长了就同步;而短时间内,就需要满足一定数量变更才同步,防止短时间内频繁同步。