JAVA面試題之四——Redis 中的緩存清空策略 LRU 說一下?

LRU 是一種緩存淘汰策略。常見的策略有三種:先進先出策略 FIFO(First In,First Out)、最少使用策略 LFU(Least Frequently Used)、最近最少使用策略 LRU(Least Recently Used)

方案一:使用鏈表實現 LRU

思路是這樣的:維護一個有序單鏈表,越靠近鏈表尾部的結點是越早之前訪問的。當有一個新的數據被訪問時,我們從鏈表頭開始順序遍歷鏈表。


  1. 如果此數據之前已經被緩存在鏈表中了,我們遍歷得到這個數據對應的結點,並將其從原來的位置刪除,然後再插入到鏈表的頭部。O(N)


    1. 如果此數據沒有在緩存鏈表中,又可以分爲兩種情況:如果此時緩存未滿,則將此結點直接插入到鏈表的頭部;如果此時緩存已滿,則鏈表尾結點刪除,將新的數據結點插入鏈表的頭部。O(N)

    當要緩存某個數據的時候,先在鏈表中查找這個數據。如果沒有找到,則直接將數據放到鏈表的尾部;如果找到了,我們就把它移動到鏈表的尾部。因爲查找數據需要遍歷鏈表,所以單純用鏈表實現的 LRU 緩存淘汰算法的時間複雜很高,是 O(n)。

    方案二:使用數組實現 LRU

    思路:數組首位保存最新訪問數據、末位置優先被清理


    1. 如果此數據之前已經被緩存在數組中了,找到對應的數據將其插入到首位,並從原位置刪除,插入到首位需要移動剩餘所有數據,時間複雜度O(N);


    1. 如果此數據沒有在數組中,分兩種情況:如果此時緩存未滿,則將節點直接插入到數組首位;如果此時緩存已經滿了,則刪除末尾節點,將新的數據插入到首位,時間複雜度O(N)

    方案三:使用散列表優化第一種方法

    散列表是什麼?

    散列表英文是 “Hash Table”, 也叫”Hash 表“或者”哈希表“。

    散列表用的是數組支持按照下標隨機訪問數據的特性,所以散列表其實就是數組的一種擴展,由數組演化而來。可以說,如果沒有數組,就沒有散列表。

    LRU 優化

    散列表+雙向鏈表的形式。——》LinkedHashMap也是這種結構。查看 LinkedHashMap 源碼就知道 JAVA 是怎麼實現 LRU 了。

    查找數據:散列表查找數據時間複雜度接近 O(1),如果存在散列衝突,時間複雜度會上升。

    刪除數據:找到數據所在的節點,然後將其刪除。刪除時間複雜度爲O(1)。

    添加數據:1)如果數據在緩存中了,將其啓動到雙向鏈表的尾部;2) 如果不在緩存中,看緩存有沒有滿: a) 如果滿了,將雙向鏈表的頭部節點刪除,然後將數據插入到雙向鏈表的尾部;b) 如果沒有滿,直接插入到鏈表尾部。

    Redis 中是怎麼實現 LRU 的

    Redis 中 LRU 有兩種。1)所有key都參與 LRU 算法的策略;2)只包含設置了過期時間的 key 參與 LRU 。

    • allkeys-lru: evict keys by trying to remove the less recently used (LRU) keys first, in order to make space for the new data added.

    • volatile-lru: evict keys by trying to remove the less recently used (LRU) keys first, but only among keys that have an expire set, in order to make space for the new data added.

    Redis 中的 LRU 算法並不是一個完整的 LRU 算法,只是一種近似。Redis 並不能選出那個最長空閒時間的 key 進行刪除,他會在局部(選擇的樣本 keys)刪除空閒時間最長的那個。

    Redis 不實現完整的 LRU 算法,是因爲完整的 LRU 算法太消耗內存了。近似實現在 Redis 中實際上是等效的。

    Redis 3.0 做了升級,能實現一個更近似的 LRU 算法。

    可以通過設置一個參數,進行調整 LRU 策略。參數如下:

    maxmemory-samples 5

    下圖比較真實 LRU 算法和 Redis 2.8和3.0版本中的 LRU.

    Redis 3.0 設置 maxmemory-samples 10 最接近真實 LRU.

    參考:

    1. Redis 官方文檔:https://redis.io/topics/lru-cache;

    2. 王爭,極客時間《數據結構與算法之美》06講 https://time.geekbang.org/column/article/41013

    本文分享自微信公衆號 - 哥妞(gh_d18ec82f19ea)。
    如有侵權,請聯繫 [email protected] 刪除。
    本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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