RocksDB 二級緩存
本文分享自天翼云開(kāi)發(fā)者社區《RocksDB 二級緩存》,作者:b****n
RocksDB 團隊正在實(shí)現對非易失性介質(zhì)上的塊緩存的支持??梢钥醋魇?RocksDB 當前的易失性塊緩存的擴展。非易失性塊緩存充當第二層緩存,其中包含從易失性緩存中逐出的塊。當這些塊由于訪(fǎng)問(wèn)而變得更熱時(shí),它們會(huì )被提升到易失性緩存中。
此功能適用于數據庫位于遠程存儲或云存儲上的情況。非易失性緩存在 RocksDB 中被稱(chēng)為 SecondaryCache。通過(guò)維護比 DRAM 大一個(gè)數量級的二級緩存,需要從遠程存儲讀取的次數會(huì )更少,從而減少讀取延遲和網(wǎng)絡(luò )帶寬消耗。
從用戶(hù)的角度來(lái)看,本地閃存緩存將支持以下需求:
1.打開(kāi)數據庫時(shí)提供指向二級緩存的指針。
2.能夠在同一進(jìn)程中跨DB共享二級緩存。
3.一臺主機上有多個(gè)二級緩存。
4.通過(guò)確保緩存鍵的可重復性,支持跨進(jìn)程重啟和重啟持久化緩存。
設計
在為 SecondaryCache 設計 API 時(shí),我們可以選擇使其對 RocksDB 代碼可見(jiàn)或將其隱藏在 RocksDB 塊緩存后面。將它隱藏在塊緩存后面有幾個(gè)優(yōu)點(diǎn):
1.允許靈活地將塊插入二級緩存。塊可以在從 RAM 層逐出時(shí)插入,也可以立即插入。
2.無(wú)論是否配置了二級緩存,它通過(guò)提供統一的接口來(lái)降低 RocksDB 代碼的其余部分的復雜性。
3.使并行讀取、在緩存中查看預取、故障處理等更容易。
4.如果需要,可以更輕松地擴展為壓縮數據,并允許將其他持久性媒體添加為附加層。
我們決定通過(guò)將二級緩存隱藏在block cache后面,使二級緩存對其余 RocksDB 代碼透明。我們需要解決的一個(gè)關(guān)鍵問(wèn)題是緩存項的內存分配和所有權,插入二級緩存可能需要由其分配內存。這意味著(zhù)需要將緩存對象中可以轉移到二級緩存的部分復制出來(lái),并且在查找時(shí)需要將二級緩存中存儲的數據提供給對象構造函數。對于 RocksDB 緩存對象,如數據塊、索引和過(guò)濾器塊以及壓縮字典,解包涉及復制出塊的原始未壓縮塊,打包涉及使用原始未壓縮數據構造相應的塊/索引/過(guò)濾器/字典對象。
我們考慮的另一種選擇是現有的 PersistentCache 接口。但是,我們決定不追求它并最終棄用它,原因如下:
1.它直接暴露給表讀取器代碼,這使得實(shí)現不同策略將其擴展到更復雜的準入控制策略變得更加困難。
2.該接口不允許自定義內存分配和對象打包/解包,因此無(wú)論如何都必須定義新的 API。
3.當前的 PersistentCache 實(shí)現非常簡(jiǎn)單,沒(méi)有任何準入控制策略。
應用程序接口
RocksDB 的塊緩存和二級緩存之間的接口被設計為允許可插拔實(shí)現。對于企業(yè)內部使用,我們計劃使用帶有wrapper的Cachelib提供插件實(shí)現,并使用folly等f(wàn)bcode庫,RocksDB無(wú)法直接使用,來(lái)高效實(shí)現緩存操作。下圖顯示了塊的插入和查找流程:
二級緩存中的項目由 SecondaryCacheHandle 引用。句柄可能不會(huì )立即準備好或具有有效值。調用者可以調用 IsReady() 以確定它是否準備就緒,并且可以調用 Wait() 以阻塞直到它準備就緒。調用方必須在準備就緒后調用 Value() 以確定項目是否已成功讀取。Value() 必須在失敗時(shí)返回 nullptr。
二級緩存的用戶(hù)(例如,通過(guò) LRUCache 間接調用的 BlockBasedTableReader)必須實(shí)現 CacheItemHelper 中定義的回調,以便于解包/打包對象以保存到二級緩存和從中恢復。必須實(shí)現 CreateCallback 以從二級緩存中的原始數據構造可緩存對象。
二級緩存提供者必須提供 SecondaryCache 抽象類(lèi)的具體實(shí)現。
SecondaryCache 由用戶(hù)通過(guò)在 LRUCacheOptions 中提供指向它的指針來(lái)配置。
當前進(jìn)展
最初的 RocksDB 對二級緩存的支持已經(jīng)合并到主分支中,并將在 6.21 版本中提供。這包括在實(shí)例化 RocksDB 的 LRU 緩存(易失性塊緩存)時(shí)為用戶(hù)提供一種配置二級緩存的方法,將從 LRU 緩存驅逐的塊溢出到閃存緩存,將塊從 SecondaryCache 讀取到 LRU 緩存,更新工具例如 cache_bench 和 db_bench 來(lái)指定閃存緩存。相關(guān)的 PR 是#8271、#8191和#8312。
我們使用上述 PR 以及基于 Cachelib 的 SecondaryCache 實(shí)現制作了端到端解決方案的原型。我們運行了一個(gè) mixgraph 基準測試來(lái)模擬真實(shí)的讀/寫(xiě)工作負載。結果顯示,與沒(méi)有本地緩存相比,使用本地閃存緩存可提高 15%,網(wǎng)絡(luò )讀取減少約 25-30%,緩存未命中率相應減少。
未來(lái)展望
在短期內,我們計劃執行以下操作以將 SecondaryCache 與 RocksDB 完全集成:
1.使用DB session ID作為緩存鍵前綴,保證唯一性和可重復性
2.優(yōu)化 MultiGet 和迭代器工作負載的閃存緩存使用
3.壓力測試
4.更多基準測試
從長(cháng)遠來(lái)看,我們計劃將其部署在 Facebook 的生產(chǎn)環(huán)境中。
*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。