Redis缓存淘汰策略与Redis键的过时删除策略并不彻底相同,前者是在Redis内存使用超过必定值的时候(通常这个值能够配置)使用的淘汰策略;然后者是经过按期删除+惰性删除二者结合的方式进行内存淘汰的。缓存,不是存储,没法保证之前设置的缓存绝对存在。由于缓存容量是有上限的,即便set值的时候不设置过时时间,在内存不够的时候,会根据内存淘汰策略删除一些缓存。设置过时时间的key是如何删除的?过时后会当即释放内存吗?redis
Redis过时Key清理的机制对清理的频率和最大时间都有限制,在尽可能不影响正常服务的状况下,进行过时Key的清理,以达到长时间服务的性能最优。redis会把设置了过时时间的key放在单独的字典中,每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过时key的操做。算法
具体的算法以下:数据库
这是一个基于几率的简单算法,基本的假设是抽出的样本可以表明整个key空间,redis持续清理过时的数据直至将要过时的key的百分比降到了25%如下。这也意味着在长期来看任何给定的时刻已通过期但仍占据着内存空间的key的量最多为每秒的写操做量除以4。缓存
根据以上原理,系统中应避免大量的key同时过时,给要过时的key设置一个随机范围。服务器
优势:经过限制删除操做的时长和频率,来减小删除操做对CPU时间的占用,处理"定时删除"的缺点,按期删除过时key,处理"惰性删除"的缺点
缺点:在内存友好方面,不如"定时删除" 在CPU时间友好方面,不如"惰性删除"
难点:合理设置删除操做的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间作一次删除),这个要根据服务器运行状况来定了dom
过时的key并不必定会立刻删除,还会占用着内存。 当你真正查询这个key时,redis会检查一下,这个设置了过时时间的key是否过时了? 若是过时了就会删除,返回空。这就是惰性删除。ide
优势:删除操做只发生在从数据库取出key的时候发生,并且只删除当前key,因此对CPU时间的占用是比较少的,并且此时的删除是已经到了非作不可的地步(若是此时还不删除的话,咱们就会获取到了已通过期的key了)
缺点:若大量的key在超出超时时间后,好久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)性能
在设置key的过时时间的同时,为该key建立一个定时器,让定时器在key的过时时间来临时,对key进行删除。this
优势:保证内存被尽快释放
缺点:若过时key不少,删除这些key会占用不少的CPU时间,在CPU时间紧张的状况下,CPU不能把全部的时间用来作要紧的事儿,还须要去花时间删除这些key,定时器的建立耗时,若为每个设置过时时间的key建立一个定时器(将会有大量的定时器产生),性能影响严重
结论:此方法基本上没人用spa
过时key对RDB没有任何影响
1)从内存数据库持久化数据到RDB文件,持久化key以前,会检查是否过时,过时的key不进入RDB文件
2)从RDB文件恢复数据到内存数据库,数据载入数据库以前,会对key先进行过时检查,若是过时,不导入数据库(主库状况)
过时key对AOF没有任何影响
1)从内存数据库持久化数据到AOF文件:当key过时后,尚未被删除,此时进行执行持久化操做(该key是不会进入aof文件的,由于没有发生修改命令)当key过时后,在发生删除操做时,程序会向aof文件追加一条del命令(在未来的以aof文件恢复数据的时候该过时的键就会被删掉)
2)AOF重写:重写时,会先判断key是否过时,已过时的key不会重写到aof文件
当redis内存超出物理内存限制时,会和磁盘产生swap,这种状况性能极差,通常是不容许的。经过设置 maxmemory 限制最大使用内存。超出限制时,根据redis提供的几种内存淘汰机制让用户本身决定如何腾出新空间以提供正常的读写服务。
public class LRUCache<K,V> extends LinkedHashMap<K,V> { private int cacheSize; public LRUCache(int cacheSize){ super(10,0.75f,true); //设置hashmap大小,true是让linkedhashmap按照访问顺序排序 this.cacheSize = cacheSize; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { //当map中数量大于指定缓存个数的时候,自动删除最老的数据 return size()>cacheSize; } }