HBase 2.0 中的 In-Memory Compaction
使用HBase的現代產品對其讀寫性能的期望值不斷提高。理想情況下,HBase應用程序希望在不放棄可靠的持久存儲保證的情況下享受內存數據庫的速度。我們在HBase 2.0中引入了一種名為Accordion的新算法,它朝著這個目標邁出了重要的一步。
HBase將數據劃分為由RegionServer群集控制的region。 RegionServer的縱向可伸縮性對于最終用戶的性能以及整個系統的利用率至關重要。通過更好地使用RAM,accordion提高了RegionServer的可伸縮性。它可以在內存中容納更多數據,并減少寫入磁盤的頻率。這樣帶來多個好處。首先,降低了HBase的磁盤占用率和寫入放大率。其次,更多的讀寫操作落到RAM,更少的操作落到磁盤I/O,換句話說,HBase的性能得以提高。傳統上,這些指標被認為是不一致的,并且需要彼此進行權衡。使用accordion,它們會同時得到改善。
accordion的靈感來自于HBase的內部存儲結構Log-Structured-Merge(LSM)樹。 HBase region被存儲為一系列可搜索鍵值映射。最頂部是一個可變的內存存儲,稱為MemStore,它保存最近的寫入(put)操作。其余的是不可變的HDFS文件,稱為HFiles。 MemStore溢出后,被刷新到磁盤,創建一個新的HFile。 HBase采用了多版本并發控制,即MemStore將數據變化存儲為單獨的版本。因此,一個key的多個版本可以在MemStore和多個HFile中。讀取(get)操作通過key檢索值,該操作掃描BlockCache中的HFile數據,以查找最新版本。為了減少磁盤訪問次數,多個HFiles在后臺被合并。此過程稱為壓縮(compaction),將刪除冗余的cell并創建更大的文件。
accordion將LSM原理重新應用于MemStore,以消除數據仍在RAM中時的冗余和其他開銷。這樣做可以減少刷新到HDFS的頻率,從而減少寫放大和整個磁盤占用空間。由于MemStore溢出而產生的刷新減少,因而寫操作停頓的頻率降低,最后提高了寫性能。磁盤上較少的數據還意味著對塊緩存的壓力較小,命中率較高,并最終改善了讀取響應時間。最后,較少的磁盤寫入也意味著在后臺發生較少的壓縮,即,從生產(讀取和寫入)工作中竊取了較少的周期。總而言之,可以將內存壓縮的效果設想為一種催化劑,使整個系統運行起來更快。
accordion目前提供兩種級別的內存壓縮basic和eager。前者適用于所有數據更新模式的通用優化。后者對于數據流失率較高的應用程序(如生產者-消費者隊列,購物車,共享計數器等)最有用。所有這些用例均具有頻繁更新相同key的功能,這些key會生成多個冗余版本,算法可利用這些冗余版本提供更多價值。另一方面,eager優化可能會導致計算開銷(更多的內存副本和垃圾回收),這可能會影響密集寫入負載下的響應時間。如果MemStore使用on-heap的 MemStore-Local Allocation Buffer (MSLAB),則開銷很高。建議不要將這種配置與eager壓縮相結合。
在下一部分中,將了解有關Accordion壓縮算法的更多詳細信息。
如何使用
in-memory compaction可以全局配置,也可以按column family配置。 支持的級別為none(舊版實現),basic,eager。
默認情況下,所有表都應用basic in-memory compaction。 可以在hbase-site.xml中覆蓋此全局配置,如下所示:
也可以在HBase Shell中按column family配置級別,如下所示:
create?‘
性能提升
我們通過流行的Yahoo Cloud Service Benchmark(YCSB)對HBase進行了廣泛的壓力測試。我們的實驗使用了100-200 GB的數據集,并行使了各種代表性的工作負載。結果表明,Accordion可帶來顯著的性能提升。
Heavy-tailed (Zipf) 分布。第一個實驗執行了一個工作負載,其中key使用Zipf分布,遵循大多數現實場景。在這種情況下,當100%為寫時,Accordion最多可將寫入放大率降低30%,將寫入吞吐量提高20%,并將GC降低22%。50%為讀時,讀延遲減少了12%。
Uniform 分布。第二個實驗執行了另一個工作負載,其中所有key都同樣熱度的。在這種情況下,100%為寫時,Accordion可將寫入放大率降低多達25%,將寫入吞吐量提高50%,并將GC降低36%。讀延遲不受影響(這是意料之中的,因為完全缺乏局部性)
Accordion是如何工作
高層設計。Accordion引入了CompactingMemStore一種內部應用壓縮的MemStore實現。與默認的MemStore相比,后者將所有數據保持在一個整體的數據結構中,而Accordion將其作為一系列段進行管理。最年輕的部分稱為活動部分,是可變的。它接受put操作。發生溢出時(默認情況下,為32MB-MemStore大小的25%),活動段將移動到內存管道中,并且變得不可變。我們稱其為內存flush。 Get操作將掃描這些段和HFile(與HBase一樣,可通過block cache訪問后者)。
CompactingMemStore可能會不時在后臺合并多個不可變的段,從而創建更大和更精簡的段。因此,管道類似于“accordion bellows”(手風琴風箱),是“呼吸”(膨脹和收縮)的。
當RegionServer決定將一個或多個MemStore刷新到磁盤上以釋放內存時,將會使用CompactingMemStore。這樣做的理由是延長有效管理內存的MemStore的壽命,以減少總體I/O。當發生此類刷新時,所有管道段均移至復合snapshot,合并并流式傳輸到新的HFile。
段結構。 與默認的MemStore相似,CompactingMemStore在cell存儲的頂部維護一個索引,以允許通過key快速搜索。 傳統上,此索引被實現為Java跳表(ConcurrentSkipListMap)-動態但浪費的數據結構,用于管理許多小對象。 CompactingMemStore對不可變的段索引使用節省空間的扁平布局。 此通用優化可幫助所有壓縮策略減少RAM開銷,即使數據幾乎沒有冗余也是如此。 將段添加到管道后,索引被序列化為名為CellArrayMap的排序數組,該數組可以進行快速二分搜索。
CellArrayMap支持直接從Java堆分配cell,也支持從MSLAB的定制分配(堆上或堆外)。 通過從索引中引用的KeyValue對象可以抽象出實現上的差異。 CellArrayMap本身總是在堆上分配。
壓縮算法。in-memory compaction 算法在流水線段的頂部維護單個扁平索引。這樣可以節省空間,尤其是在數據項較小的情況下,因此可以更快的完成落盤操作。單個索引允許在一個位置進行搜索,因此控制住了讀取延遲。
當活動段刷新到內存時,它進入到壓縮管線隊列中,并立即安排后臺合并任務。后者同時掃描管道中的所有段(on-disk compaction),并將多個索引合并為一個。基本basic策略和eager壓縮策略之間的差異體現在它們如何處理cell。basic壓縮不會消除冗余數據版本,以避免物理復制。它只是重新排列對KeyValue對象的引用。相反,eager壓縮會濾除重復項。這是以額外的計算和數據遷移為代價的-例如,使用MSLAB存儲時,將尚存的cell復制到新創建的MSLAB。當數據高度冗余時,壓縮的開銷得到了回報。
壓縮的未來實現可能會自動在basic和eager壓縮策略之間進行選擇。例如,該算法可能會嘗試一次eager壓縮,并根據收到的值(例如,被淘汰的部分數據)安排下一次壓縮。這種方法可以減輕系統管理員的負擔,并適應不斷變化的訪問模式。
摘要
在這篇博客中,我們討論了Accordion的基本原理,配置,性能提升以及內存壓縮算法的一些細節。 下一篇文章將重點為HBase開發人員介紹系統的內部。
我們感謝Michael Stack,Anoop Sam John和Ramkrishna Vasudevan的持續支持,使該項目得以實現。
云計算
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。