首先要区分master主节点和slave从节点。
为什么呢?因为slave过期key的删除策略和master过期key的删除策略是不同的。
一,redis主节点过期key的删除策略
1,定时删除:在设置键的过期时间的同时,创建一个timer,让定时器在键的过期时间到达时,立即执行对键的删除操作。(主动删除)
优缺点:对内存友好,但是对cpu时间不友好,有较多过期键的而情况下,删除过期键会占用相当一部分cpu时间。
2,定期删除:每隔一段时间就对数据库进行一次检查,删除里面的过期键。(主动删除)
优缺点:采用对内存和cpu时间折中的方法,每隔一段时间执行一次删除过期键操作,并通过限制操作执行的时长和频率来减少对cpu时间的影响。难点在于,选择一个好的策略来设置删除操作的时长和执行频率。
3,惰性删除:放任过期键不管,但是每次从键空间中获取键时,都检查取到的键是否过期,如果过期就删除,如果没过期就返回该键。(被动删除)
优缺点:对cpu时间友好,程序只会在取出键的时候才会对键进行过期检查,这不会在删除其他无关过期键上花费任何cpu时间,但是如果一个键已经过期,而这个键又保留在数据库中,那么只要这个过期键不被删除,他所占用的内存就不会释放,对内存不友好。
二,redis从节点过期key的删除策略
主节点在key到期时,会在AOF文件里增加一条del指令。AOF文件被同步到从节点以后,从节点根据AOF中的这个del指令来执行删除过期key的操作。
优缺点:从节点的这个过期key的处理策略,会导致一个问题,主节点已经删除的key,在从节点还是存在的。因为AOF同步del指令是异步的。从节点不会过期扫描,从节点对过期的处理是被动的。
目前,Redis采用的是惰性删除+定期删除的方案;
三、主从复模式下对过期键的处理总结
通常在主从模式下,主服务器来读取写命令,从服务器用来读取读命令,分担主服务器的压力(与那种持久化模式无关),需要注意的是:
-
如果当前服务器是
Slave
的话,如果有命令读取当前过期键的话,不会惰性删除,因为这会影响读取的性能,因此不会删除,并且返回过期键对应的值;除非是Master
服务器同步告知Slave
服务器需要删除过期键才会删除; -
如果当前服务器是
Master
的话,当服务器通过策略得知某个键过期,则将该过期键给删除,并且同步给其他从服务器让它们删除掉该键;
四、其他模块的淘汰处理
目前Redis提供了两种持久化方式,分别是RDB和AOF;
1.RDB 快照持久化
创建
RDB是通过创建快照获取内存中的数据在某一个时间点上的数据的副本;有两个命令可以创建RDB文件,分别是SAVE
和BGSAVE
,两者的区别在于是否阻塞进程去创建RDB文件,这两个命令都不会将数据空间中的过期键给保存到RDB文件中;
载入
在启动Redis服务器时,如果服务器开启了RDB文件,那么服务器就会对RDB文件进行载入,需要注意⚠️的是:
-
如果当前服务器是
Master
,那么过期键将会被忽略,不会载入到主服务器中; -
如果当前服务器是
Slave
,文件中所有键,不过是否过期都会被载入到从服务器中;
2.AOF 只追加持久化
写入
数据库中的过期键没有被删除时,其不会对AOF文件有任何的影响;当过期键被删除以后,程序会向AOF文件追加一条DEL
命令,显示记录该键已经被删除;
重写
AOF是将执行的写命令添加到AOF文件的末尾来记录数据的变化;为了避免文件被添加得越来越大,甚至有可能用完硬盘的所有空间,因此Redis提供了Rewrite
的优化策略,分别是REWRITEAOF
和BGREWRITEAOF
,两个命令的区别也是在于是否阻塞主进程,这两个命令都不会将数据空间中的过期键给保存到AOF文件中;
五、淘汰Key策略
Redis中通过maxmemory参数来设定内存的使用上限,当Redis使用内存达到设定的最大值的时候,会根据配置文件中的策略选取要删除的key来删除,从而给新的键值留出空间;
目前Redis提供了6种的淘汰策略(默认的是noeviction):
-
volatile-lru,在设置了过期时间的键空间中,移除最近最少使用的key;
-
allkeys-lru,移除最近最少使用的key;
-
volatile-random,在设置了过期时间的键空间中,随机移除一个key;
-
allkeys-random,随机移除一个key;
-
volatile-ttl,在设置了过期时间的键空间中,移除将要过期的key;
-
noeviction,当内存使用达到阀值的时候,所有引起申请内存的命令会报错;