一、redis的过期策略和内存淘汰机制
1、定期删除+惰性删除
定期删除:指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除
惰性删除:在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了,如果过期了此时就会删除,不会给你返回任何东西
2、如果大量过期key堆积在内存里,导致redis内存块耗尽了,怎么办?
内存淘汰机制:
redis.conf中配置:
1
|
# maxmemory-policy noeviction |
noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
allkeys-lru:在主键空间中,优先移除最近未使用的key。
volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
allkeys-random:在主键空间中,随机移除某个key。
volatile-random:在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。
二、手写LRU缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class LRUCache { private Map<Integer, Integer> map; private final int capacity; public LRUCache( int capacity) { this .capacity = capacity; //定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序(true) map = new LinkedHashMap<Integer, Integer>(capacity, 0 .75f, true ){ @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) { //当map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据 return size() > capacity; } }; } public int get( int key) { return map.getOrDefault(key, - 1 ); } public void put( int key, int value) { map.put(key, value); } } |
LinkedHashMap的源码说明 :
对于 LinkedHashMap 而言,它继承与 HashMap(public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
)、
底层使用哈希表与双向链表来保存所有元素。
LinkedHashMap 中的 Entry 集成与 HashMap 的 Entry,但是其增加了 before 和 after 的引用,指的是上一个元素和下一个元素的引用
1
2
3
4
5
6
|
static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; Entry( int hash, K key, V value, Node<K,V> next) { super (hash, key, value, next); } } |
初始化:
在 LinkedHashMap 的构造方法中,实际调用了父类 HashMap 的相关构造方法来构造一个底层存放的 table 数组,但额外可以增加 accessOrder 这个参数,如果不设置,默认为 false,代表按照插入顺序进行迭代;当然可以显式设置为 true,代表以访问顺序进行迭代
1
2
3
4
5
6
|
public LinkedHashMap( int initialCapacity, float loadFactor, boolean accessOrder) { super (initialCapacity, loadFactor); this .accessOrder = accessOrder; } |