論文《TinyLFU: A Highly Ecient Cache Admission Policy》閱讀筆記

1. Introduction

LFU的侷限:前端

  • LFU實現須要維護大而複雜的元數據(頻次統計數據等)
  • 大多數實際工做負載中,訪問頻率隨着時間的推移而發生根本變化(這是外賣業務不適合樸素LFU的根本緣由)

針對LFU的問題,已經存在了一些LFU的替代或優化方案,例如WLFU(Window LFU):算法

  • 老化機制
  • 限制採樣爲:最後W次訪問的有限大小窗口

在絕大多數狀況下,新訪問的數據老是被直接插入到緩存中,緩存方案僅設計驅逐策略,即,決定應該驅逐哪一個數據。這是由於維護當前不在緩存中的對象的元數據被認爲是不切實際的。緩存

因爲維護全部訪問的頻率數據消耗過大,不少LFU的實現只維護了緩存中數據的頻率數據。對於前者,咱們稱爲Perfect LFU(PLFU),後者則稱爲In-Memory LFU。因爲WLFU(Window-LFU)優於In-Memery LFU(以更大的元數據爲代價),因此論文在第一節只討論了WLFU和PLFU。數據結構

LRU是一個很常見的用來替代LFU的算法,LRU的淘汰最近最少使用的元素。相較於LFU,LRU可能會有更加高效的實現,能夠並自動適應突發的訪問請求;然而基於LRU的緩存,在較大的負載下,須要更多的空間來保持和LFU同樣的緩存命中率。app

本文的貢獻:性能

  • 闡明瞭一種近似LFU准入策略的緩存結構/算法的有效性優化

    • 提出了一種緩存結構,只有在准入策略認爲將其替換進入緩存會提升緩存命中率的狀況下,纔會被插入
    • 提出了一種空間利用率很高的新的數據結構——TinyLFU,能夠在較大訪問量的場景下近似的替代LFU的數據統計部分(meta-data)。
    • 經過形式化的證實和模擬,證實了TinyLFU得到的Freq排序與真實的訪問頻率排序是幾乎近似的
    • 以優化的形式將TinyLFU實如今了Caffeine項目中:W-TinyLFU
    • 與其餘幾種緩存管理策略進行了比較,包括ARC、LIRC

對於較爲靜態的訪問分佈,各類的緩存管理策略的差別是微不足道的,而對於偏倚較大的負載場景,TinyLFU體現出了較大的優點。即使是使用了TinyLFU准入策略進行優化的LRU也得到了較大的提高(LRU原生沒有準入策略)。spa

2. Related Work

2.1 Cache Replacement

PLFU更加適合相對靜態的訪問分佈,但不能很好的適應動態的訪問頻率分佈。
In-Memory LFU僅維護已存在於緩存中的數據項的訪問頻率,並始終將最近訪問的項插入緩存中,若是須要,逐出緩存中最不頻繁訪問的項。一般In-Memory LFU使用堆來管理緩存,而且由Anirban優化到了O(1)。然而即使有了這樣的改進,但In-Memory LFU仍然對頻率分佈的變化顯得反應遲緩。在靜態的頻率分佈下,性能也落後於PLFU(由於其再也不爲【不在緩存中的數據】維護任何頻率數據)。設計

  • Aging對象

    • 是對In-Memory LFU的優化,提升了其對變化的響應能力。
    • 增長了一個【最大平均引用計數】,當緩存中的數據引用計數平均值超過了該值,則將全部的數據的頻率技術都進行減小。可是如何減小(通常是存在一個衰減因子)是一個棘手且tricky的問題。
  • WLFU

    • 只保存一個時間窗口內的訪問數據來統計頻次,這個機制要求按照時序對訪問進行持續的採樣。對變化的調整是優於PLFU的。
  • ARC
  • LIRS
  • SLRU
  • 2Q
  • LRU-K
  • GDSF

2.2 近似統計結構(Approximate Counting Architectures)

簡單說就是對全流量採樣,TinyLFU須要一種近似的流量統計結構來替代全量Hash,減小內存的佔用,而且要儘量高效,且儘可能保持精度。能夠詳見3.2

3. TinyLFU Architecture

3.1 TinyLFU Overview

TinyLFU的准入&淘汰策略是:新增一個新的元素時,判斷使用該元素替換一箇舊元素,是否能夠提高緩存命中率。
clipboard.png

上圖爲TinyLFU的主要結構,可是在闡述前須要強調咱們面臨的兩個主要的挑戰:

  1. 維護一個新鮮度機制(freshness mechanism),來保持歷史最近訪問且能夠移除舊事件(keep the history recent and remove the history old events)
  2. 如何減小內存的消耗

3.2 Approximate Counting Overview

  • Minimal Increment Counting Bloom Filter Counting Bloom Filter參考連接

    • Minimal Increment CBF 和CBF 使用一個合適大小的計數器來代替了Bloom Filter中的bit
    • Minimal Increment CBF支持如下兩個方法(下面的闡述,假設咱們的場景是來爲key計算k=3個hash value,來定位)

      • Estimate

        • 例如,獲取到3個hash位置上的計數值:{2, 2, 5},取全部值中的最小值返回
      • Add

        • 在元素到達後,獲取到已有的3個計數值{2, 2, 5},Add操做僅增長兩個較小的計數值,來避免針對最大值的沒必要要的增長

clipboard.png

3.3 Freshness Mechanism

TinyLFU使用reset機制來保證sketch中的數據儘量最新。每增長一個新的元素到approximation sketches,會增長一個計數值,一旦計數值達到了一個預設的採樣尺寸(W),就會將頻率採樣(CBF)維護的全部計數值除以2(可使用高效的寄存器位移來實現);論文也花了較大的篇幅來證實了這種Reset機制的正確性,且評估了其存在的截斷錯誤(3會被reset爲1,而非1.5),而且得出瞭如下結論:

reset在固定的頻率分佈下徹底正確,且能夠應對流量頻率的變化(數學概括法證實,感興趣的能夠參考原文3.3.1)

採樣數W越大,截斷錯誤的帶來的影響越小

3.4 Space Reduction

clipboard.png
在兩個維度減小了空間的佔用:

  1. 減少了sketch中計數值的尺寸

    1. 對於咱們的採樣大小W,咱們的計數值須要佔用log(W) bit
  2. 減小了sketch分的計數器的數量

    1. Doorkeeper

      1. 引入了Doorkeeper機制,來避免爲長尾流量分配計數器
      2. 由一個常規的Bloom Filter攔截在CBF以前
      3. 若是一個元素,在Doorkeeper中,則直接插入TinyLFU的主結構,不然先插入Doorkeeper;對於數據查詢,會將Doorkeeper中的那一個計數值也加到計數值上去
      4. reset操做會清空Doorkeeper
      5. 這樣對於每一個W週期內,都會過濾僅有一次的訪問的數據

儘管Doorkeeper須要一些額外的空間,可是相對於在主要結構中節約的空間來講,顯得微不足道。

3.5 TingLFU vs a Strwman

3.6 Connecting TinyLFU to Caches

對於LRU和隨機緩存而言,緩存存儲本質上是個黑盒。而TinyLFU不一樣,因爲reset機制的存在,須要在reset時,同步更新緩存中的item;

4. Winwod TinyLFU(W-TinyLFU)

主要是優化了「sparse bursts(突發的稀疏流量)」,新的突發流量可能會由於沒法構建足夠的頻率數據來保證本身駐留在緩存中。
clipboard.png

前端是一個小的LRU(window cache);window cache淘汰後,會送到DoorKeeper過濾;過濾經過後,元素存儲到一個大的Segmented LRU緩存裏。Window LRU,它的容量只佔據1%的總空間,它的目的就是用來存放短時間突發訪問記錄。存放主要元素的Segmented LRU(SLRU)是一種LRU的改進,主要把在一個時間窗口內命中至少2次的記錄和命中1次的單獨存放,這樣就能夠把短時間內較頻繁的緩存元素區分開來。具體作法上,SLRU包含2個固定尺寸的LRU,一個叫Probation段A1,一個叫Protection段A2。新記錄老是插入到A1中,當A1的記錄被再次訪問,就把它移到A2,當A2滿了須要驅逐記錄時,會把驅逐記錄插入到A1中。W-TinyLFU中,SLRU有80%空間被分配給A2段。

5. 實驗

相關文章
相關標籤/搜索