1、键的过期删除策略
Redis中键到达设定的过期时间后并不会马上被删除,这是因为如果是一个存储多个数据的大列表,那么删除时是会阻塞命令执行线程的,这会造成其他命令无法执行,因此Redis采用的是定时删除和懒惰删除兼具的做法。
定时删除:在一个给定时间批量删除过期键,如果键的过期时间基本一致就会带来跟即时删除一样的问题,因此建议设置过期时间时添加随机值。Redis默认每秒会进行十次过期扫描,会从过期字典中随机取出二十个键,删除其中已经过期的,如果已过期的占总数的1/4那么就再进行一次扫描,以此循环,当然Redis默认设置了扫描的最长时间为25ms;
懒惰删除:只有当这个键被访问到时才会删除;
2、内存淘汰机制
淘汰机制在内存不足(达到设定上限)时会进行,目的是给缓存数据库腾出空间,保存更有价值的数据。
volatile-lru:在过期键字典中,使用lru算法进行内存淘汰;
volatile-random:在过期键字典中,随机挑选键淘汰;
volatile-lfu:在过期键字典中,使用lfu算法进行内存淘汰;
volatile-ttl:在过期键字典中,根据过期时间先后进行内存淘汰;
allkeys-lru:在所有键中,使用lru算法进行内存淘汰;
allkeys-lfu:在所有键中,使用lfu算法进行内存淘汰;
allkeys-random:在所有键中,随机挑选键淘汰;
noeviction:不进行淘汰,这种方式会保持数据的完整性,但后面来的写请求就不能处理了;
这里需要注意,Redis中使用的是近似的LRU算法,在第一次采样是从数据中随机选出N个存入集合中,之后将这N个中lru字段最小的淘汰出去,如果缓存空间还是到达限制,就接着再次进行随机抽取数据,跟现有集合数据进行比较,淘汰出最小的那个。这里的N取决于 maxmemory-samples
值。
3、懒惰删除
这里的懒惰删除指的是对于键使用DEL命令引发的删除,这种情况下默认会马上释放内存,如果一个对象中包含多个元素,这时候就会造成单线程卡顿。为了解决这个问题,Redis还提供了一个unlink指令,代表对键的删除进行懒处理,交由后台的异步线程进行操作,从名字也可以看出来,这里似乎只是断开了断开了连接关系,并不是真正马上释放内存。
此外,对于清空数据库的操作可以使用flushdb 或者 flushall ,这两个操作也可能会造成单线程的卡顿,因此可以使用 flushall async 让异步线程去处理键清除空间释放的工作。