Redis 過期策略、內存淘汰機制和 LRU 算法的實現

一 Redis 過期策略

Redis 過期策略是:定期刪除 + 惰性刪除

  • 定期刪除

       定期刪除,指的是 Redis 默認是每隔 100ms 就隨機抽取一些設置了過期時間的 key,檢查其是否過期,如果過期就刪除。假設 Redis 裏放了 10w 個 key,都設置了過期時間,你每隔幾百毫秒,就檢查 10w 個 key,那 Redis 基本上就死了,cpu 負載會很高的,消耗在你的檢查過期 key 上了。注意,這裏可不是每隔 100ms 就遍歷所有的設置過期時間的 key,那樣就是一場性能上的災難實際上 Redis 是每隔 100ms 隨機抽取一些 key 來檢查和刪除的

       既然有了定期刪除爲啥還需要惰性刪除呢?定期刪除可能會導致很多過期 key 到了時間並沒有被刪除掉,這個時候需要惰性刪除對定期刪除做一個補充。

  • 惰性刪除

       在你獲取某個 key 的時候,Redis 會檢查一下 ,這個 key 如果設置了過期時間那麼是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。

       但是實際上這還是有問題的,如果定期刪除漏掉了很多過期 key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期 key 堆積在內存裏,導致 Redis 內存塊耗盡了,這個時候就會走內存淘汰機制。

二 內存淘汰機制

Redis 內存淘汰機制有以下幾個:

  • noeviction: 當內存不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太噁心了。
  • allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)。
  • allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key,這個一般沒人用吧,爲啥要隨機,肯定是把最近最少使用的 key 給幹掉啊。
  • volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 key(這個一般不太合適)。
  • volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 key。
  • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 key 優先移除。

三 LRU 算法實現

       可以利用已有的 JDK 數據結構實現一個 Java 版的 LRU。

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;

    /**
     * 傳遞進來最多能緩存多少數據
     *
     * @param cacheSize 緩存大小
     */
    public LRUCache(int cacheSize) {
        // true 表示讓 linkedHashMap 按照訪問順序來進行排序,最近訪問的放在頭部,最老訪問的放在尾部。
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    /**
     * 鉤子方法,通過put新增鍵值對的時候,若該方法返回true
     * 便移除該map中最老的鍵和值
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 當 map中的數據量大於指定的緩存個數的時候,就自動刪除最老的數據。
        return size() > CACHE_SIZE;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章