过期策略与淘汰策略
过期策略
为key设置过期时间:expire key 5(5s过期)
查看key的剩余时间:ttl key(未设置超时返回-1,已超时返回-2)
redis的过期实现通过两种方式,分别是懒惰删除和定时遍历。
懒惰删除就是用到某个key的时候再去查它是否过期,如果过期就删除。
定时遍历是一个集中处理的方式,redis会把所有设置了过期时间的key放到同一个字典中,默认每秒10次过期扫描,每次随机查字典中的20个key,然后删除,如果其中过期的比例超过四分之一就重复这个动作,为了防止循环过度规定扫描时间的上限是25ms。不过即使如此,客户端如果设置超时的话,连接失败就会报出大量异常。
redis只能单线程处理,为了避免不产生大批key同时过期卡死,要给过期时间设置一个随机范围,一般用固定活动过期时间+随机冗余时间来防止。
从库的过期策略是被动的,只能等待主库删除key时将操作写进AOF日志文件,然后同步到从库。这种异步同步可能带来不一致的风险。
淘汰策略
可以设置maxmemory来限制最大使用内存,如果超出了还可以选择几种策略来应对:
noeviction:不会继续服务写请求,读请求可以继续进行,这是默认的淘汰策略
volatile-lru:淘汰已经过期的,最少使用的key
volatile-ttl:淘汰已经过期的,剩余寿命最短的
volatile-random:随机淘汰一些已经过期的
allkeys-lru:淘汰那些最少使用的key
allkeys-random:随机淘汰一些key
如果redis只起缓存功能,那么用allkeys就可以,如果想使用持久化功能,那么就必须使用volatile,保证永久的key不被淘汰。
在4.0版本中淘汰策略增加了两项:
volatile-lfu和allkeys-lfu分别是对已经过期的key和所有key进行LFU淘汰,开启了这个选项之后还能获得对象的LFU计数。LFU是根据访问频率来计算热度,优先淘汰热度低的。redis的LFU热度是分钟级的,redis缓存了系统时间戳(因为获取属于系统调用很费时间)。
淘汰的算法
redis采用的是一种近似LRU算法,因为严格的需要消耗大量内存,数据结构很复杂。这种近似LRU为每一个key增加了一个最后一次被访问的时间戳信息,如果发现内存超过maxmemory就会执行LRU,随机选择一些key,然后淘汰掉最旧的key,然后循环进行,直到内存低于maxmemory为止。在redis3.0中还增加了淘汰池来提升这个算法的效果,每次循环出来的key都会放入淘汰池中,然后再选择最旧的key淘汰,剩余保留在淘汰池中。