1、Redis內存若在配置文件中未設置,內存會無限制增長,直到超出物理內存,拋出out of memory內存耗盡異常
????????解決方法,調整maxmemory參數,一般設置為物理內存的3/4,并且添加緩存刪除策略
2、Redis對于設置了過期時間的的鍵并不是過期立馬刪除,有三種緩存刪除方案
? ? ? ? 1、定時刪除,定時任務去遍歷所有過期鍵值,會占用cpu和影響性能
? ? ? ? 2、惰性刪除,過期了并不刪,下次用到再刪,會占用memory和內存泄漏
? ? ? ? 3、定期刪除,每過一段時間抽取一部分過期了的鍵刪除,這種需要考慮具體的內存使用情況,配置好合理的定期時間。但依然會內存泄漏,需要兜底方案也就是內存淘汰策略。
3、Redis內存淘汰策略,可使用config set xxx命令或者修改配置文件種memory-policy
? ? ? ? ? ?分為兩類,每類四種
所有key |
| ||||||||
設置了過期時間的key |
|
?4、lru算法-淘汰不經常使用的key,思路每次get或者put時,將數據重新插入,超過內存限制則刪除最前面的數據。
public class LRUCache {private final Map<Integer, Integer> map = new LinkedHashMap<Integer, Integer>();private int capacity;public LRUCache(int capacity) {this.capacity = capacity;}public int get(int key) {if(!map.containsKey(key)){return -1;}int v = map.get(key);map.remove(key);map.put(key, v);return v;}public void put(int key, int value) {map.remove(key);map.put(key, value);if(map.size() > capacity) {map.remove(map.entrySet().iterator().next().getKey());}System.out.println(map);}public static void main(String[] args) {LRUCache l = new LRUCache(2);l.put(2,1);l.put(1,1);l.put(2,3);l.put(4,1);l.get(1);}
}
5、實際上LinkedHashMap已經幫我們實現了lru算法,可以繼承LinkedHashMap,具體如下
public class LRUCache extends LinkedHashMap {private int capacity;public LRUCache(int capacity) {super(capacity, 0.75f, true);this.capacity = capacity;}@Overrideprotected boolean removeEldestEntry(Map.Entry eldest) {return super.size() > capacity;}public static void main(String[] args) {LRUCache l = new LRUCache(2);l.put(2,1);l.put(1,1);l.put(2,3);l.put(4,1);l.get(1);l.get(2);System.out.println(l);}
}
6、如果不基于LinkedHashMap我們需要自己實現存儲+順序結構,可使用哈希+雙向鏈表實現。可以參考HashMap與AQS底層實現