一條數(shù)據(jù)的HBase之旅,簡明HBase入門教程-Flush與Compaction

Flush與Compaction其實屬于Write流程的繼續(xù),所以本文應(yīng)該稱之為"Write后傳"。在2.0版本中,最主要的變化就是新增了In-memory Flush/Compaction,而DateTieredCompaction并不算2.0新加入的特性,2.0版本在Compaction核心算法方面并沒有什么新的突破。本文將帶你探討Compaction的一些本質(zhì)問題。

在閱讀本文之前,希望你已經(jīng)閱讀過:

一條數(shù)據(jù)的HBase之旅,簡明HBase入門教程-開篇

一條數(shù)據(jù)的HBase之旅,簡明HBase入門教程-Write全流程

前文回顧

前文《一條數(shù)據(jù)的HBase之旅,簡明HBase入門教程:Write全流程》主要講了如下內(nèi)容:

1. 介紹HBase寫數(shù)據(jù)可選接口以及接口定義
2. 通過一個樣例,介紹了RowKey定義以及列定義的一些方法,以及如何組裝Put對象
3. 數(shù)據(jù)路由,數(shù)據(jù)分發(fā)、打包,以及Client通過RPC發(fā)送寫數(shù)據(jù)請求至RegionServer
4. RegionServer接收數(shù)據(jù)以后,將數(shù)據(jù)寫到每一個Region中。寫數(shù)據(jù)流程先寫WAL再寫MemStore,這里展開了一些技術(shù)細(xì)節(jié)
5. 簡單介紹了HBase權(quán)限控制模型

至此,數(shù)據(jù)已經(jīng)被寫入WAL與MemStore,可以說數(shù)據(jù)已經(jīng)被成功寫到HBase中了。事實上,上篇文章講到的Flush流程是"簡化"后的流程,在2.0版本中,這里已經(jīng)變的更加復(fù)雜。

本文思路

  1. 回顧Flush&Compaction舊流程
  2. 介紹2.0版本的In-memory Flush & Compaction特性
  3. 介紹Compaction要解決的本質(zhì)問題是什么
  4. 在選擇合理的Compaction策略之前,用戶應(yīng)該從哪些維度調(diào)研自己的業(yè)務(wù)模型
  5. HBase現(xiàn)有的Compaction策略有哪些,各自的適用場景是什么
  6. Compaction如何選擇待合并的文件
  7. 關(guān)于Compaction更多的一些思考
  8. 本計劃列出所有的價值問題單,但篇幅文字受限??梢渣c擊"閱讀原文"鏈接參考文末References信息部分

Flush&Compaction

這是1.X系列版本以及更早版本中的Flush&Compaction行為:

MemStore中的數(shù)據(jù),達(dá)到一定的閾值,被Flush成HDFS中的HFile文件。

但隨著Flush次數(shù)的不斷增多,HFile的文件數(shù)量也會不斷增多,那這會帶來什么影響?在HBaseCon 2013大會上,Hontonworks的名為《Compaction Improvements in Apache HBase》的演講主題中,提到了他們測試過的隨著HFile的數(shù)量的不斷增多對讀取時延帶來的影響:

盡管關(guān)于Read的流程在后面文章中才會講到,但下圖可以幫助我們簡單的理解這其中的原因:


圖中說明了從一個文件中指定RowKey為“66660000431^201803011300”的記錄,以及從兩個文件中讀取該行記錄的區(qū)別,明顯,從兩個文件中讀取,將導(dǎo)致更多的IOPS。這就是HBase Compaction存在的一大初衷,Compaction可以將一些HFile文件合并成較大的HFile文件,也可以把所有的HFile文件合并成一個大的HFile文件,這個過程可以理解為:將多個HFile的“交錯無序狀態(tài)”,變成單個HFile的“有序狀態(tài)”,降低讀取時延。小范圍的HFile文件合并,稱之為Minor Compaction,一個列族中將所有的HFile文件合并,稱之為Major Compaction。除了文件合并范圍的不同之外,Major Compaction還會清理一些TTL過期/版本過舊以及被標(biāo)記刪除的數(shù)據(jù)。下圖直觀描述了舊版本中的Flush與Compaction流程:

Flush

在2.0版本中,F(xiàn)lush的行為發(fā)生了變化,默認(rèn)的Flush,僅僅是將正在寫的MemStore中的數(shù)據(jù)歸檔成一個不可變的Segment,而這個Segment依然處于內(nèi)存中,這就是2.0的新特性:In-memory Flush and Compaction,而且該特性在2.0版本中已被默認(rèn)啟用(系統(tǒng)表除外)。
上文中簡單提到了MemStore的核心是一個CellSet,但到了這里,我們可以發(fā)現(xiàn),MemStore的結(jié)構(gòu)其實更加復(fù)雜:MemStore由一個可寫的Segment,以及一個或多個不可寫的Segments構(gòu)成。


MemStore中的數(shù)據(jù)先Flush成一個Immutable的Segment,多個Immutable Segments可以在內(nèi)存中進行Compaction,當(dāng)達(dá)到一定閾值以后才將內(nèi)存中的數(shù)據(jù)持久化成HDFS中的HFile文件。

看到這里,可能會有這樣的疑問:這樣做的好處是什么?為何不直接調(diào)大MemStore的Flush Size?

如果MemStore中的數(shù)據(jù)被直接Flush成HFile,而多個HFile又被Compaction合并成了一個大HFile,隨著一次次Compaction發(fā)生以后,一條數(shù)據(jù)往往被重寫了多次,這帶來顯著的IO放大問題,另外,頻繁的Compaction對IO資源的搶占,其實也是導(dǎo)致HBase查詢時延大毛刺的罪魁禍?zhǔn)字?/strong>。而In-memory Flush and Compaction特性可以有力改善這一問題。

那為何不干脆調(diào)大MemStore的大???這里的本質(zhì)原因在于,ConcurrentSkipListMap在存儲的數(shù)據(jù)量達(dá)到一定大小以后,寫入性能將會出現(xiàn)顯著的惡化。

在融入了In-Memory Flush and Compaction特性之后,F(xiàn)lush與Compaction的整體流程演變?yōu)椋?div id="u0z1t8os" class="image-package">

關(guān)于Flush執(zhí)行的策略

一個Region中是否執(zhí)行Flush,原來的默認(rèn)行為是通過計算Region中所有Column Family的整體大小,如果超過了一個閾值,則這個Region中所有的Column Family都會被執(zhí)行Flush。

2.0版本中合入了0.89-fb版本中的一個特性:HBASE-10201/HBASE-3149:Make flush decisions per column family。

2.0版本中默認(rèn)啟用的Flush策略為FlushAllLargeStoresPolicy,也就是說,這個策略使得每一次只Flush超出閾值大小的Column Family,如果都未超出大小,則所有的Column Family都會被Flush。

改動之前,一個Region中所有的Column Family的Flush都是同步的,雖然容易導(dǎo)致大量的小HFile,但也有好處,尤其是對于WAL文件的快速老化,避免導(dǎo)致過多的WAL文件。而如果這些Column Family的Flush不同步以后,可能會導(dǎo)致過多的WAL文件(過多的WAL文件會觸發(fā)一些擁有老數(shù)據(jù)的Column Family執(zhí)行Flush),這里需要結(jié)合業(yè)務(wù)場景實測一下。如果每一行數(shù)據(jù)的寫入,多個Column Family的數(shù)據(jù)都是同步寫入的,那么,這個默認(rèn)策略可能并不合適。

Compaction

在這個章節(jié),我們繼續(xù)探討HBase Compaction,主要是想理清這其中所涉及的一些"道"與"術(shù)":

  • "道":HBase Compaction要解決的本質(zhì)問題是什么?
  • "術(shù)":針對HBase Compaction的問題本質(zhì),HBase有哪些具體的改進/優(yōu)秀實踐?

Compaction會導(dǎo)致寫入放大
我們先來看看Facebook在Fast 14提交的論文《Analysis of HDFS Under HBase: A Facebook Messages Case Study》所提供的一些測試結(jié)論(在我之前寫的一篇文章《從HBase中移除WAL?3D XPoint技術(shù)帶來的變革》已經(jīng)提到過):

在Facebook Messages業(yè)務(wù)系統(tǒng)中,業(yè)務(wù)讀寫比為99:1,而最終反映到磁盤中,讀寫比卻變?yōu)榱?6:64。>WAL,HDFS Replication,Compaction以及Caching,共同導(dǎo)致了磁盤寫IO的顯著放大。
雖然距離論文發(fā)表已經(jīng)過去幾年,但問題本質(zhì)并未發(fā)生明顯變化。尤其是在一個寫多讀少的應(yīng)用中,因Compaction帶來的寫放大(Write Amplification)尤其明顯,下圖有助于你理解寫放大的原因:

隨著不斷的執(zhí)行Minor Compaction以及Major Compaction,可以看到,這條數(shù)據(jù)被反復(fù)讀取/寫入了多次,這是導(dǎo)致寫放大的一個關(guān)鍵原因,這里的寫放大,涉及到網(wǎng)絡(luò)IO與磁盤IO,因為數(shù)據(jù)在HDFS中默認(rèn)有三個副本。

Compaction的本質(zhì)

我們先來思考一下,在集群中執(zhí)行Compaction,本質(zhì)是為了什么?容易想到如下兩點原因:

  • 減少HFile文件數(shù)量,減少文件句柄數(shù)量,降低讀取時延

  • Major Compaction可以幫助清理集群中不再需要的數(shù)據(jù)(過期數(shù)據(jù),被標(biāo)記刪除的數(shù)據(jù),版本數(shù)溢出的數(shù)據(jù))

很多HBase用戶在集群中關(guān)閉了自動Major Compaction,為了降低Compaction對IO資源的搶占,但出于清
理數(shù)據(jù)的需要,又不得不在一些非繁忙時段手動觸發(fā)Major Compaction,這樣既可以有效降低存儲空間,也>可以有效降低讀取時延。

而關(guān)于如何合理的執(zhí)行Compaction,我們需要結(jié)合業(yè)務(wù)數(shù)據(jù)特點,不斷的權(quán)衡如下兩點:

  • 避免因文件數(shù)不斷增多導(dǎo)致讀取時延出現(xiàn)明顯增大
  • 合理控制寫入放大

HFile文件數(shù)量一定會加大讀取時延嗎?也不一定,因為這里與RowKey的分布特點有關(guān)。我們通過列舉幾個典型場景來說明一下不同的RowKey分布,為了方便理解,我們先將一個Region的RowKey Range進一步劃分成多個Sub-Range,來說明不同的RowKey分布是如何填充這些Sub-Ranges的:

下面的不同行代表不同的時間點(我們使用不斷遞增的時間點T1,T2,T3,T4,來描述隨著時間演變而產(chǎn)生的RowKey分布變化):
分布A

在這個Region中,某一個時間段只填充與之有關(guān)的一個Sub-Range,RowKey隨著時間的演進,整體呈現(xiàn)遞增趨勢。但在填充每一個Sub-Range的時候,又可能有如下兩種情形(以Sub-Range1的填充為例,為了區(qū)別于T1T4,我們使用了另外4個時間點TaTd):

分布A-a

這種情形下,RowKey是嚴(yán)格遞增的。
分布A-b

這種情形下,RowKey在Sub-Range1的范圍內(nèi)是完全隨機的。

下面則是一種隨機RowKey的場景,也就是說,每一個時間點產(chǎn)生的數(shù)據(jù)都是隨機分布在所有的Sub-Range中的:
分布B

對于分布A-a來說,不同的HFile文件在RowKey Range(該HFile文件所涉及到的最小數(shù)據(jù)RowKey與最大數(shù)據(jù)RowKey構(gòu)成的RowKey區(qū)間)上并不會產(chǎn)生重疊,如果要基于RowKey讀取一行數(shù)據(jù),只需要查看一個文件即可,而不需要查看所有的文件,這里完全可以通過優(yōu)化讀取邏輯來實現(xiàn)。即使不做Compaction,對于讀取時延的影響并不明顯(當(dāng)然,從降低文件句柄數(shù)量,降低HDFS側(cè)的小文件數(shù)量的維度來考慮,Compaction還是有意義的)。

對于分布B來說,如果有多個HFiles文件,如果想基于RowKey讀取一行數(shù)據(jù),則需要查看多個文件,因為不同的HFile文件的RowKey Range可能是重疊的,此時,Compaction對于降低讀取時延是非常必要的。

調(diào)研自己的業(yè)務(wù)模型

在選擇一個合理的Compaction策略之前,應(yīng)該首先調(diào)研自己的業(yè)務(wù)模型,下面是一些參考維度:

1.寫入數(shù)據(jù)類型/單條記錄大小 ;是否是KB甚至小于KB級別的小記錄?還是MB甚至更大的圖片/小文件數(shù)據(jù)?

2.業(yè)務(wù)讀寫比例

3.隨著時間的不斷推移,RowKey的數(shù)據(jù)分布呈現(xiàn)什么特點?

4.數(shù)據(jù)在讀寫上是否有冷熱特點? 是否只讀取/改寫最近產(chǎn)生的數(shù)據(jù)?

5.是否有頻繁的更新與刪除?

6.數(shù)據(jù)是否有TTL限制?

7.是否有較長時間段的業(yè)務(wù)高峰期和業(yè)務(wù)低谷期?

幾種Compaction策略
HBase中有幾種典型的Compaction策略,來應(yīng)對幾類典型的業(yè)務(wù)場景:

一. Stripe Compaction

它的設(shè)計初衷是,Major Compaction占用大量的IO資源,所以很多HBase用戶關(guān)閉了自動觸發(fā)的Major Compaction,改為手動觸發(fā),因為Major Compaction依然會被用來清理一些不再需要的數(shù)據(jù)。

隨著時間的推移,Major Compaction要合并的文件總Size越來越大,但事實上,真的有必要每一次都將所有的文件合并成一個大的HFile文件嗎?尤其是,不斷的將一些較老的數(shù)據(jù)和最新的數(shù)據(jù)合并在一起,對于一些業(yè)務(wù)場景而言根本就是不必要的。

因此,它的設(shè)計思路為:

將一個Region劃分為多個Stripes(可以理解為Sub-Regions),Compaction可以控制在Stripe(Sub-Region)層面發(fā)生,而不是整個Region級別,這樣可以有效降低Compaction對IO資源的占用。

那為何不直接通過設(shè)置更多的Region數(shù)量來解決這個問題?更多的Region意味著會加大HBase集群的負(fù)擔(dān),尤其是加重Region Assignment流程的負(fù)擔(dān),另外,Region增多,MemStore占用的總體內(nèi)存變大,而在實際內(nèi)存無法變大的情況下,只會使得Flush更早被觸發(fā),F(xiàn)lush的質(zhì)量變差。

新Flush產(chǎn)生的HFile文件,先放到一個稱之為L0的區(qū)域,L0中Key Range是Region的完整Key Range,當(dāng)對L0中的文件執(zhí)行Compaction時,再將Compaction的結(jié)果輸出到對應(yīng)的Stripe中:

HBase Document中這么描述Stripe Compaction的適用場景:

  • Large regions. You can get the positive effects of smaller regions without additional overhead for MemStore and region management overhead.

  • Non-uniform keys, such as time dimension in a key. Only the stripes receiving the new keys will need to compact. Old data will not compact as often, if at all

在我們上面列舉的幾種RowKey分布的場景中,分布A(含分布A-a,分布A-b)就是特別適合Stripe Compaction的場景,因為僅僅新寫入數(shù)據(jù)的Sub-Range合并即可,而對于老的Sub-Range中所關(guān)聯(lián)的數(shù)據(jù)文件,根本沒有必要再執(zhí)行Compaction。

Stripe Compaction關(guān)于Sub-Region的劃分,其實可以加速Region Split操作,因為有的情形下,直接將所有的Stripes分成兩部分即可。

二. Date Tiered Compaction

我們假設(shè)有這樣一種場景:

  • 新數(shù)據(jù)的產(chǎn)生與時間有關(guān),而且無更新、刪除場景

  • 讀取時通常會指定時間范圍,而且通常讀取最近的數(shù)據(jù)

在這種情形下,如果將老數(shù)據(jù)與新數(shù)據(jù)合并在一起,那么,指定時間范圍讀取時,就需要掃描一些不必要的老數(shù)據(jù):因為合并后,數(shù)據(jù)按RowKey排序,RowKey排序未必與按照數(shù)據(jù)產(chǎn)生的時間排序一致,這使得新老數(shù)據(jù)交叉存放,而掃描時老數(shù)據(jù)也會被讀到。

這是Date Tiered Compaction的設(shè)計初衷,Date Tiered Compaction在選擇文件執(zhí)行合并的時候,會感知Date信息,使得Compaction時,不需要將新老數(shù)據(jù)合并在一起。這對于基于Time Range的Scan操作是非常有利的,因為與本次Scan不相關(guān)的文件可以直接忽略。

什么是Time Range Based Scan?

HBase的Scan查詢,通常都是指定RowKey的Range的,但HBase也支持這樣一類查詢:通過指定一個起始的Timestamp,掃描出所有的落在此Timestamp Range中的所有數(shù)據(jù),這就是Time Range Based Scan。

可以參考接口:Scan#setTimeRange(long minStamp, long maxStamp)

Time Range Based Scan可以用來實現(xiàn)針對HBase數(shù)據(jù)表的增量數(shù)據(jù)導(dǎo)出/備份能力。

容易想到,時序數(shù)據(jù)就是最典型的一個適用場景。但需要注意的是,如下場景并不適合使用Date Tiered Compaction:

  • 讀取時通常不指定時間范圍
  • 涉及頻繁的更新與刪除
  • 寫入時主動指定時間戳,而且可能會指定一個未來的時間戳
  • 基于bulk load加載數(shù)據(jù),而且加載的數(shù)據(jù)可能會在時間范圍上重疊
三. MOB Compaction

能否使用HBase來存儲MB級別的Blob(如圖片之類的小文件)數(shù)據(jù)?

這是很多應(yīng)用面臨的一個基礎(chǔ)問題,因為這些數(shù)據(jù)相比于普通的存儲于HBase中的結(jié)構(gòu)化/半結(jié)構(gòu)化數(shù)據(jù)顯得過大了,而如果將這些數(shù)據(jù)直接存儲成HDFS中的獨立文件,會加重HDFS的NameNode的負(fù)擔(dān),再者,如何索引這些小文件也是一個極大的痛點。

當(dāng)然,也有人采用了這樣的方式:將多個小文件合并成HDFS上的一個大文件,這樣子可以減輕HDFS的NameNode的負(fù)擔(dān),但需要維護每一個小文件的索引信息(文件名以及每一個小文件的偏移信息)。

如果存這些這些小文件時,像普通的結(jié)構(gòu)化數(shù)據(jù)/半結(jié)構(gòu)化數(shù)據(jù)一樣,直接寫到HBase中,會有什么問題?這樣子多條數(shù)據(jù)可以被合并在較大的HFile文件中,減輕了NameNode的負(fù)擔(dān),同時解決了快速索引的問題。但基于前面的內(nèi)容,我們已經(jīng)清楚知道了Compaction帶來的寫放大問題。試想一下,數(shù)MB級別的Blob數(shù)據(jù),被反復(fù)多次合并以后,會帶來什么樣的影響?這對IO資源的搶占將會更加嚴(yán)重。

因此,HBase的MOB特性的設(shè)計思想為:將Blob數(shù)據(jù)與描述Blob的元數(shù)據(jù)分離存儲,Blob元數(shù)據(jù)采用正常的HBase的數(shù)據(jù)存儲方式,而Blob數(shù)據(jù)存儲在額外的MOB文件中,但在Blob元數(shù)據(jù)行中,存儲了這個MOB文件的路徑信息。MOB文件本質(zhì)還是一個HFile文件,但這種HFile文件不參與HBase正常的Compaction流程。僅僅合并Blob元數(shù)據(jù)信息,寫IO放大的問題就得到了有效的緩解。

MOB Compaction也主要是針對MOB特性而存在的,這里涉及到數(shù)據(jù)在MOB文件與普通的HFile文件之間的一些流動,尤其是MOB的閾值大小發(fā)生變更的時候(即當(dāng)一個列超過預(yù)設(shè)的配置值時,才被認(rèn)定為MOB),本文暫不展開過多的細(xì)節(jié)。

在HBase社區(qū)中,MOB特性(HBASE-11339)一直在一個獨立的特性分支中開發(fā)的,直到2.0版本才最終合入進來(華為的FusionInsight的HBase版本中,以及華為云的CloudTable的HBase版本中,都包含了完整的MOB特性)。

關(guān)于mob可查看另一篇文章HBase 的MOB壓縮分區(qū)策略介紹

四. Default Compaction

就是默認(rèn)的Compaction行為,2.0版本和舊版本中的行為沒有什么明顯變化。

所謂的Default Compaction,具有更廣泛的適用場景,它在選擇待合并的文件時是在整個Region級別進行選擇的,所以往往意味著更高的寫IO放大。

在實際應(yīng)用中,應(yīng)該結(jié)合自己的應(yīng)用場景選擇合適的Compaction策略,如果前幾種策略能夠匹配自己的應(yīng)用場景,那么應(yīng)該是優(yōu)選的(這幾個策略的質(zhì)量狀態(tài)如何尚不好判斷,建議結(jié)合業(yè)務(wù)場景進行實測觀察),否則應(yīng)該選擇Default Compaction。

如果上述幾種Compaction策略都無法很好的滿足業(yè)務(wù)需求的話,用戶還可以自定義Compaction策略,因為HBase已經(jīng)具備良好的Compaction插件化機制。

如何選擇待合并的文件
無論哪種Compaction策略,都涉及一個至關(guān)重要的問題:“如何選擇待合并的文件列表”
Major Compaction是為了合并所有的文件,所以,不存在如何選擇文件的問題。
選擇文件時,應(yīng)該考慮如下幾個原則:

  1. 選擇合理的文件數(shù)量
    如果一次選擇了過多的文件: 對于讀取時延的影響時間范圍可能比較長,但Compaction產(chǎn)生的寫IO總量較低。
    如果一次選擇了較少的文件: 可能導(dǎo)致過于頻繁的合并,導(dǎo)致寫IO被嚴(yán)重放大。

  2. 選擇的文件在時間產(chǎn)生順序上應(yīng)該是連續(xù)的,即應(yīng)該遵循HBase的Sequence ID的順序

這樣子,HBase的讀取時可以做一些針對性的優(yōu)化,例如,如果在最新的文件中已經(jīng)讀到了一個RowKey的記錄,那就沒有必要再去看較老的文件。

在HBase中,有一種"歷史悠久"的選擇文件的策略,名為ExploringCompactionPolicy,即使在最新的版本中,該策略依然在協(xié)助發(fā)揮作用,它選擇文件的原理如下(下面的圖片和例子源自HBASE-6371):

將HFile文件從老到新的順序排序,通常,舊文件較大,因為舊文件更可能是被合并過的文件。
每一次需要從文件隊列中選取一個合適的開始文件位置,通過如下算法:

f[start].size <= ratio * (f[start+1].size + ….. + f[end - 1].size)

找到一個滿足條件的開始位置,以及滿足條件的文件組合。

舉例:假設(shè)ratio = 1.0:

  1. 如果候選文件[1200, 500, 150, 80, 50, 25, 12, 10],則最終選擇出來的需要合并的文件列表為[150, 80, 50, 25, 12, 10]


    image
  2. 如果候選文件[1200, 500, 150, 80, 25, 10],則選不出任何文件。
    每一次Minor Compaction所涉及的文件數(shù)目都有上下限。如果超過了,會減去一些文件,如果小于下限,則忽略此次Compaction操作。待選擇的文件也有大小限制,如果超出了預(yù)設(shè)大小,就不會參與Compaction。這里可以理解為:Minor Compaction的初衷只是為了合并較小的文件。另外,BulkLoad產(chǎn)生的文件,在Minor Compaction階段會被忽略。
    RatioBasedCompactionPolicy曾一度作為主力文件選擇算法沿用了較長的時間,后來,出現(xiàn)了一種ExploringCompactionPolicy,它的設(shè)計初衷為:

RatioBasedCompactionPolicy雖然選擇出來了一種文件組合,但其實這個文件組合并不是最優(yōu)的,因此它期望在所有的候選組合中,選擇一組性價比更高的組合,性價比更高的定義為:文件數(shù)相對較多,而整體大小卻較小。這樣,即可以有效降低HFiles數(shù)量,又可能有效控制Compaction所占用的IO總量。

也可以這么理解它們之間的一些不同:

RatioBasedCompactionPolicy僅僅是在自定義的規(guī)則之下找到第一個"可行解"即可,而ExploringCompactionPolicy卻在盡可能的去尋求一種自定義評價標(biāo)準(zhǔn)中的"最優(yōu)解"。

另外,需要說明的一點:ExploringCompactionPolicy在選擇候選組合時,正是采用了RatioBasedCompactionPolicy中的文件選擇算法。

更多的一些思考
Compaction會導(dǎo)致寫入放大,前面的內(nèi)容中已經(jīng)反復(fù)提及了很多次。在實際應(yīng)用中,你是否關(guān)注過Compaction對于查詢毛刺的影響(查詢時延總是會出現(xiàn)偶發(fā)性的陡增)?

關(guān)于Compaction的參數(shù)調(diào)優(yōu),我們可能看到過這樣的一些建議:盡可能的減少每一次Compaction的文件數(shù)量,目的是為了減短每一次Compaction的執(zhí)行時間。這就好比,采用Java GC算法中的CMS算法時,每一次回收少量的無引用對象,盡管GC被觸發(fā)的頻次會增大,但可以有效降低Full GC的發(fā)生次數(shù)和發(fā)生時間。

但在實踐中,這可能并不是一個合理的建議,例如,HBase默認(rèn)的觸發(fā)Minor Compaction的最小文件數(shù)量為3,但事實上,對于大多數(shù)場景而言,這可能是一個非常不合理的默認(rèn)值,在我們的測試中,將最小文件數(shù)加大到10個,我們發(fā)現(xiàn)對于整體的吞吐量以及查詢毛刺,都有極大的改進,所以,這里的建議為:Minor Compaction的文件數(shù)量應(yīng)該要結(jié)合實際業(yè)務(wù)場景設(shè)置合理的值。另外,在實踐中,合理的限制Compaction資源的占用也是非常關(guān)鍵的,如Compaction的并發(fā)執(zhí)行度,以及Compaction的吞吐量以及網(wǎng)絡(luò)帶寬占用等等。

另外,需要關(guān)注到的一點:Compaction會影響B(tài)lock Cache,因為HFile文件發(fā)生合并以后,舊HFile文件所關(guān)聯(lián)的被Cache的Block將會失效。這也會影響到讀取時延。HBase社區(qū)有一個問題單(HBASE-20045),試圖在Compaction時緩存一些最近的Blocks。

在Facebook的那篇論文中,還有一個比較有意思的實踐:


他們將Compaction下推到存儲層(HDFS)執(zhí)行,這樣,每一個DateNode在本地合并自己的文件,這樣可以降低一半以上的網(wǎng)絡(luò)IO請求,但本地磁盤IO請求會增大,這事實上是用磁盤IO資源來換取昂貴的網(wǎng)絡(luò)IO資源。在我們自己的測試中也發(fā)現(xiàn),將Compaction下推到HDFS側(cè)執(zhí)行,能夠明顯的優(yōu)化讀寫時延毛刺問題。

總結(jié)

本文基于2.0版本闡述了Flush與Compaction流程,講述了Compaction所面臨的本質(zhì)問題,介紹了HBase現(xiàn)有的幾種Compaction策略以及各自的適用場景,更多是從原理層面展開的,并沒有過多講述如何調(diào)整參數(shù)的實際建議,唯一的建議為:請一定要結(jié)合實際的業(yè)務(wù)場景,選擇合理的Compaction策略,通過不斷的測試和觀察,選擇合理的配置,何謂合理?可以觀察如下幾點:

  • 寫入吞吐量能否滿足要求。隨著時間的推移,寫入吞吐量是否會不斷降低?

  • 讀取時延能否滿足要求。隨著時間的推移,讀取時延是否出現(xiàn)明顯的增大?

  • 觀察過程中,建議不斷的統(tǒng)計分析Compaction產(chǎn)生的IO總量,以及隨著時間的變化趨勢。2.0版本中盡管增加了一些與Compaction相關(guān)的Metrics信息,但關(guān)于Compaction IO總量的統(tǒng)計依然是非常不充分的,這一點可以自己定制實現(xiàn),如果你有興趣,也完全可以貢獻(xiàn)給社區(qū)。

原文出自:一條數(shù)據(jù)的HBase之旅,簡明HBase入門教程-Flush與Compaction

更多技術(shù)交流,可關(guān)注微信交流群,微信公眾號等:

或參考文章: HBase中文社區(qū)官網(wǎng)、交流群

1. 微信群

掃描添加小編微信好友(或搜索微信號: Mr_wanyue 添加),回復(fù): HBase 加群

2. 釘釘群:

掃一掃添加

3. 微信公眾號:
掃描關(guān)注

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容