首先,要明白redis是用来作数据缓存的,不是用来作数据存储的(固然也能够当数据库用),因此数据时候过时的,过时的数据就不见了,过时主要有两种状况,
①在设置缓存数据时制定了过时时间,这样到了过时时间数据就不见了。
②redis的数据是存放在内存中的,而内存是有限的,是不可能放过多数据的,好比只有10G的内存,想要向里面放入20G的数据,那么就注定会有10G的数据会丢失。redis
redis采用了 “按期删除+惰性删除” 的过时策略。
①按期删除
原理:按期删除指的是redis默认每隔100ms就随机抽取一些设置了过时时间的key,检测这些key是否过时,若是过时了就将其删掉。
为何会选择一部分,而不是所有:由于若是这是redis里面有大量的key都设置了过时时间,那么若是所有去检测一遍,CPU负载就会很高,会浪费大量的时间在检测上面,甚至直接致使redis挂掉。全部只会抽取一部分而不会所有检查。
出现问题:这样的话就会出现大量的已通过期的key并无被删除,这就是 为何有时候大量的key明明已通过了失效时间,可是redis的内存仍是被大量占用的缘由 ,为了解决这个问题,就须要 惰性删除 这个策略了。算法
②惰性删除
原理:惰性删除不在是redis去主动删除,而是在你要获取某个key 的时候,redis会先去检测一下这个key是否已通过期,若是没有过时则返回给你,若是已通过期了,那么redis会删除这个key,不会返回给你。
这样两种策略就保证了 过时的key最终必定会被删除掉 ,可是这只是保证了最终必定会被删除,要是定时删除漏掉了大量过时的key,并且咱们也没有及时的去访问这些key,那么这些key不就不会被删除了吗?不就会一直占着咱们的内存吗?这样不仍是会致使redis内存耗尽吗?
因为存在这样的问题,因此redis引入了 内存淘汰机制 来解决。数据库
内存淘汰机制就保证了在redis的内存占用过多的时候,去进行内存淘汰,也就是删除一部分key,保证redis的内存占用率不会太高,那么它会删除那些key呢?
redis提供了6中内存淘汰策略,咱们能够去进行选择,六中策略以下:
①noeviction:当内存不足以容纳新写入数据时,新写入操做会报错,没法写入新数据,通常不采用。
②allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key,这个是最经常使用的。
③allkeys-random:当内存不足以容纳新写入的数据时,在键空间中,随机移除key,通常也不使用。
④volatile-lru:volatile-lru:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,移除最近最少使用的key(这个通常不太合适) 。
⑤volatile-random:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,随机移除某个key 。
⑥volatile-ttl:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,有更早过时时间的key优先移除。缓存
//基于JavaLinkedHashMap实现
public class LRUCache<K,V> extends LinkedHashMap<K,V>{
private final int CACHE_SIZE;
//保存传递进来的最大数据量
public LRUCache(int cacheSize){
//设置hashmap的初始大小,同时最后一个true指的是让linkedhashmap按照访问顺序来进行排序,
//最近访问的放在头,最老访问的放在尾
super((int)Math.ceil(cacheSize/0.75)+1,0.75f,true);
CACHE_SIZE = CacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest){
//当map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
return size() > CACHE_SIZE;
}
}
复制代码