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