畫像體系之-HBase緩存漫談


背景

用戶/內容畫像的對存儲的要求其實是比較高的:

    能批量更新(比如更新所有用戶某個屬性)
    大量隨機讀取(甚至可能沒有熱點數據)
    隨機屬性更新/添加
    可持久化
    易於橫向擴展解決性能問題

上一次重度使用HBase已經是兩年前了。HBase能夠滿足上面五個要求,所以用HBase作爲畫像體系的主要存儲引擎便水到渠成。
問題

因爲有批量更新,隨機屬性的更新/添加,那麼必然會緩存失效,從而觸發磁盤IO導致讀取響應時間受到影響。在畫像體系裏,隨機讀取量大,比如召回了1000個id,然後你需要取這1000個id的屬性集合,並且要求響應時間能夠控制在100ms。基本只要碰到磁盤IO就歇菜了。所以現在我們希望HBase能夠把所有數據都緩存住。
HBase讀緩存特色

HBase的緩存目前我所瞭解的是Block Cache. Block Cache是什麼概念的呢,我們知道HBase的最小文件單元是HFile, HFile是有結構的,主要包含:

    索引,可以是多層
    數據
    元數據

當然還有一個布隆過濾器,方便確定一個元素是不是在HFile裏。

並且只會有三個動作:

    新增HFile
    HFile 合併
    HFile的分裂

這裏需要注意HFile一旦生成裏面的元素就不會被改變。

一個HFile的數據會被切分成多個Block,每個Block一般而言都會有一些元信息。當然這些切分其實是邏輯上的。Block Cache就是前面三部分的Cache. 在HBase裏,當打開一個HFile時,默認會cache住一些索引信息,文件信息,讀取時則會連數據都會Cache起來。當然你也可以通過參數讓HBase在打開時就把數據Cache住。

如果是傳統意義上的緩存,如果有更新,那麼必然會導致一個問題:緩存失效。但是HBase其實並沒有這個問題。一個簡單的Get請求,HBase的讀取方式是讀MemStore 和HFile,讀HFile的時候會看數據是不是已經在BlockCache裏。

    MemStore,這個是寫緩存,但是是有結構的,可以直接查。
    BlockCache, 這個是讀緩存,也是有結構的,可以直接查。
    HFile,這個就是HDFS文件,會touch到IO。

假設我在讀取的時候,MemStore沒有進行flush,那麼可能不會觸碰到磁盤,雖然BlockCache的數據已經是老版本的了,MemStore裏卻有最新版本的數據,所以HBase簡單的到MemStore/BlockCache都拿一遍。第二次再來拿,假設正好碰到MemStore flush生成新的HFile,這個時候就觸發磁盤IO了。當然,其他如Compaction也會導致觸發磁盤。
解決方案

下面解決方案的前提是,可用於BlockCache的內存大於你的數據。在畫像體系裏,這點可以做到的,因爲內容和用戶都是有限的。

根據前面的描述,爲了能夠保證隨機讀不觸發磁盤IO操作,那麼我們在生成新HFile的同時,也需要讓它寫進BlockCache,HBase也提供了相關參數讓你完成這個功能:

    hfile.block.index.cacheonwrite  寫HFile時把索引加入到Cache
    hfile.block.bloom.cacheonwrite 寫HFile時把布隆過濾器加入到Cache
    hbase.rs.cacheblocksonwrite 寫HFile時把數據也寫入到Cache裏

這裏我們基本知道寫Cache的幾個時機點:

    打開HFile
    讀HFile
    寫HFile
 

發佈了170 篇原創文章 · 獲贊 117 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章