首先,要明白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;
}
}
複製代碼