LRU算法—緩存淘汰算法原理

1、LRU

1.1 LRU核心原理
Least recently used(LRU,最近最少使用)算法根據(jù)數(shù)據(jù)的歷史訪問記錄淘汰數(shù)據(jù)。其核心思想是“如果數(shù)據(jù)最近被訪問過丈秩,那么將來被訪問的幾率也更高”;

1.2 算法實(shí)現(xiàn)
最常見的實(shí)現(xiàn)是使用一個(gè)鏈表保存緩存數(shù)據(jù)淳衙,詳細(xì)算法實(shí)現(xiàn)如下:


LRU簡化模型算法.png

算法流程:

  1. 新數(shù)據(jù)插入到鏈表頭部蘑秽;
  2. 每當(dāng)緩存命中(即緩存數(shù)據(jù)被訪問)饺著,則將數(shù)據(jù)移到鏈表頭部;
  3. 當(dāng)鏈表滿的時(shí)候肠牲,將鏈表尾部的數(shù)據(jù)丟棄幼衰。

幾種實(shí)現(xiàn)方案:
1.用一個(gè)數(shù)組來存儲(chǔ)數(shù)據(jù),給每一個(gè)數(shù)據(jù)項(xiàng)標(biāo)記一個(gè)訪問時(shí)間戳缀雳,每次插入新數(shù)據(jù)項(xiàng)的時(shí)候渡嚣,先把數(shù)組中存在的數(shù)據(jù)項(xiàng)的時(shí)間戳自增,并將新數(shù)據(jù)項(xiàng)的時(shí)間戳置為0并插入到數(shù)組中肥印。每次訪問數(shù)組中的數(shù)據(jù)項(xiàng)的時(shí)候严拒,將被訪問的數(shù)據(jù)項(xiàng)的時(shí)間戳置為0。當(dāng)數(shù)組空間已滿時(shí)竖独,將時(shí)間戳最大的數(shù)據(jù)項(xiàng)淘汰。

2.利用一個(gè)鏈表來實(shí)現(xiàn)挤牛,每次新插入數(shù)據(jù)的時(shí)候?qū)⑿聰?shù)據(jù)插到鏈表的頭部;每次緩存命中(即數(shù)據(jù)被訪問)墓赴,則將數(shù)據(jù)移到鏈表頭部竞膳;那么當(dāng)鏈表滿的時(shí)候诫硕,就將鏈表尾部的數(shù)據(jù)丟棄。

3.利用LinkedHashMap章办。 LinkedHashMap是用的HashMap加雙鏈表實(shí)現(xiàn)的锉走,而且本身已經(jīng)實(shí)現(xiàn)了按照訪問順序的存儲(chǔ)藕届,這樣可以直接用這個(gè)類來保存數(shù)據(jù),只需要在移除元素時(shí)簡單處理就行休偶。

對(duì)于第一種方法,需要不停地維護(hù)數(shù)據(jù)項(xiàng)的訪問時(shí)間戳踏兜,另外词顾,在插入數(shù)據(jù)碱妆、刪除數(shù)據(jù)以及訪問數(shù)據(jù)時(shí),時(shí)間復(fù)雜度都是O(n)山橄。對(duì)于第二種方法垮媒,鏈表在定位數(shù)據(jù)的時(shí)候時(shí)間復(fù)雜度為O(n)。所以在一般使用第三種方式來是實(shí)現(xiàn)LRU算法睡雇。

1.3 分析
【命中率】
當(dāng)存在熱點(diǎn)數(shù)據(jù)時(shí),LRU的效率很好它抱,但偶發(fā)性的秕豫、周期性的批量操作會(huì)導(dǎo)致LRU命中率急劇下降,緩存污染情況比較嚴(yán)重观蓄。
【復(fù)雜度】
實(shí)現(xiàn)簡單混移。
【代價(jià)】
命中時(shí)需要遍歷鏈表,找到命中的數(shù)據(jù)塊索引侮穿,然后需要將數(shù)據(jù)移到頭部歌径。
1.4 代碼實(shí)現(xiàn)

/**
 * 類說明:利用LinkedHashMap實(shí)現(xiàn)LRU緩存, 必須實(shí)現(xiàn)removeEldestEntry方法
 */
public class LRU<K, V> {
    private static final float LOAD_FACTOR = 0.75f;
    private LinkedHashMap<K, V> map;
    private int capacitySize;

    public LRU(int capacitySize) {
        this.capacitySize = capacitySize;
        map = new LinkedHashMap<K, V>(capacitySize, LOAD_FACTOR, true) {
            @Override
            protected boolean removeEldestEntry(Entry<K, V> eldest) {
                return size() > capacitySize;
            }
        };
    }

    public synchronized V get(K key) {
        return map.get(key);
    }

    public synchronized void put(K key, V value) {
        map.put(key, value);
    }

    public synchronized void clear() {
        map.clear();
    }
}

2亲茅、LRU-K

2.1 LRU-K核心原理
LRU-K中的K代表最近使用的次數(shù)回铛,因此LRU可以認(rèn)為是LRU-1。LRU-K的主要目的是為了解決LRU算法“緩存污染”的問題克锣,其核心思想是將“最近使用過1次”的判斷標(biāo)準(zhǔn)擴(kuò)展為“最近使用過K次”茵肃。

2.2 算法實(shí)現(xiàn)


LRU-K模型算法.png

算法流程:
1)數(shù)據(jù)第一次被訪問,加入到訪問歷史記錄表(簡稱記錄表)袭祟;在記錄表中對(duì)應(yīng)的K單元中設(shè)置最后訪問時(shí)間=new()验残,且設(shè)置訪問次數(shù)為1;
2)如果數(shù)據(jù)訪問次數(shù)沒有達(dá)到K次巾乳,則訪問次數(shù)+1您没。最后訪問時(shí)間與當(dāng)前時(shí)間間隔超過預(yù)設(shè)的值(如30秒),訪問次數(shù)清0并加1胆绊;
3)當(dāng)數(shù)據(jù)訪問計(jì)數(shù)超過(>=)K次后紊婉,則訪問次數(shù)+1。將數(shù)據(jù)保存到LRU緩存隊(duì)列中辑舷,緩存隊(duì)列重新按照時(shí)間排序喻犁;
4)LRU緩存隊(duì)列中數(shù)據(jù)被再次訪問后,重新排序何缓;
5)LRU緩存隊(duì)列需要淘汰數(shù)據(jù)時(shí)肢础,淘汰緩存隊(duì)列中排在末尾的數(shù)據(jù),即:淘汰“倒數(shù)第K次訪問離現(xiàn)在最久”的數(shù)據(jù)碌廓。

2.3 分析
【命中率】
LRU-K降低了“緩存污染”帶來的問題传轰,命中率比LRU要高。
【復(fù)雜度】
LRU-K隊(duì)列是一個(gè)優(yōu)先級(jí)隊(duì)列谷婆,算法復(fù)雜度和代價(jià)比較高慨蛙。
【代價(jià)】
由于LRU-K還需要記錄那些被訪問過辽聊、但還沒有放入緩存的對(duì)象,因此內(nèi)存消耗會(huì)比LRU要多期贫;當(dāng)數(shù)據(jù)量很大的時(shí)候跟匆,內(nèi)存消耗會(huì)比較可觀。
LRU-K需要基于時(shí)間進(jìn)行排序(可以在需要淘汰時(shí)再排序通砍,也可以即時(shí)排序)玛臂,CPU消耗比LRU要高。

總結(jié):
LRU-K具有LRU的優(yōu)點(diǎn)封孙,同時(shí)能夠避免LRU的缺點(diǎn)迹冤,實(shí)際應(yīng)用中LRU-2是綜合各種因素后最優(yōu)的選擇,LRU-3或者更大的K值命中率會(huì)高虎忌,但適應(yīng)性差泡徙,需要大量的數(shù)據(jù)訪問才能將歷史訪問記錄清除掉。

參考:
1) 緩存淘汰算法--LRU算法
2)基于LRU-K算法設(shè)計(jì)本地緩存實(shí)現(xiàn)流量削峰
3)LRU算法四種實(shí)現(xiàn)方式介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膜蠢,一起剝皮案震驚了整個(gè)濱河市锋勺,隨后出現(xiàn)的幾起案子狡蝶,更是在濱河造成了極大的恐慌贮勃,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奏瞬,死亡現(xiàn)場離奇詭異泉孩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)珍昨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門句喷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兄春,你說我怎么就攤上這事锡溯⊙埔Γ” “怎么了芜茵?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宛乃。 經(jīng)常有香客問我蒸辆,道長,這世上最難降的妖魔是什么躬贡? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任拂玻,我火速辦了婚禮,結(jié)果婚禮上檐蚜,老公的妹妹穿的比我還像新娘。我一直安慰自己闯第,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布填帽。 她就那樣靜靜地躺著咙好,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘹悼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天绘迁,我揣著相機(jī)與錄音缀台,去河邊找鬼。 笑死膛腐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哲身。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼怔揩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了商膊?” 一聲冷哼從身側(cè)響起宠进,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎实幕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昆庇,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡整吆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年圈暗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裕膀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寸齐,死狀恐怖抄谐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蛹含,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布吸耿,位于F島的核電站,受9級(jí)特大地震影響咽安,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妆棒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望动分。 院中可真熱鬧,春花似錦刺啦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至慧脱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宗兼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國打工殷绍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹊漠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓登钥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牧牢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355