天天看點

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

前言

HBase是當下流行的一款海量資料存儲的分布式資料庫。往往海量資料存儲會涉及到一個成本問題,如何降低成本。常見的方案就是通過冷熱分離來治理資料。冷資料可以用更高的壓縮比算法(ZSTD),更低副本數算法(Erasure Coding),更便宜儲存設備(HDD,高密集型存儲機型)。

HBase冷熱分離常見解決方案

1.主備叢集

備(冷)叢集用更廉價的硬體,主叢集設定TTL,這樣當資料熱度退去,冷資料自然隻在冷叢集有。

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

優點:方案簡單,現成核心版本都能搞

缺點:維護開銷大,冷叢集CPU存在浪費

1.x版本的HBase在不改核心情況下,基本隻能有這種方案。

2.HDFS Archival Storage + HBase CF-level Storage Policy

需要在2.x之後的版本才能使用。結合HDFS分層存儲能力 + 在Table層面指定資料存儲政策,實作同叢集下,不同表資料的冷熱分離。

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

優點:同一叢集冷熱分離,維護開銷少,更靈活的配置不同業務表的政策

缺點:磁盤配比是個很大的問題,不同業務冷熱配比是不一樣的,比較難整合在一起,一旦業務變動,叢集硬體配置是沒法跟着變的。

雲HBase冷熱分離解決方案

上述2套方案都不是最好的方案,對于雲上來說。第一套方案就不說了,客戶搞2個叢集,對于資料量不大的客戶其實根本降不了成本。第二套方案,雲上客戶千千萬,業務各有各樣,磁盤配置是很難定制到合适的狀态。

雲上要做 cloud native 的方案,必須滿足同叢集下,極緻的彈性伸縮,才能真正意義上做到産品化。雲上低成本,彈性存儲,隻有OSS了。是以很自然的想到如下架構:

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

實作這樣的架構,最直接的想法是直接改HBase核心:1)增加冷表資料标記 2)根據标記增加寫OSS的IO路徑。

這樣做的缺陷非常明顯,你的外部系統(如:備份恢複,資料導入導出)很難相容這些改動,他們需要感覺哪些是冷檔案得去OSS哪個位置讀,哪些是熱檔案得去部署在雲盤上的HDFS上讀。這些本質上都是一些重複的工作,是以從架構設計角度來看必須抽象出一層。這一層能讀寫HDFS檔案,讀寫OSS檔案,感覺冷熱檔案。這一層也就是我最後設計出的ApsaraDB FileSystem,實作了Hadoop FileSystem API。對于HBase,備份恢複,資料導入導出等系統隻要替換原先FileSystem的實作即可獲得冷熱分離的功能。

下面将詳細闡述,這套FileSystem設計的細節與難點。

ApsaraDB FileSystem 設計

核心難點A

1.OSS并非檔案系統

OSS并不是一個真正意義上的檔案系統,它僅僅是兩級映射 bucket/object,是以它是對象存儲。你在OSS上看到類似這樣一個檔案:

/root/user/gzh/file

。你會以為有3層目錄+1個檔案。實際上隻有一個對象,這個對象的key包含了

/

字元罷了。

這麼帶來的一個問題是,你要想在其上模拟出檔案系統,你必須先能建立目錄。很自然想到的是用

/

結尾的特殊對象代表目錄對象。Hadoop社群開源的OssFileSystem就是這麼搞的。有了這個方法,就能判斷到底存不存在某個目錄,能不能建立檔案,不然會憑空建立出一個檔案,而這個檔案沒有父目錄。

當然你這麼做依然會有問題。除了開銷比較大(建立深層目錄多次HTTP請求OSS),最嚴重的是正确性的問題。試想一下下面這個場景:

把目錄

/root/user/source

rename 成

/root/user/target

。這個過程除了該目錄,它底下的子目錄,子目錄裡的子檔案都會跟着變。類似這樣:

/root/user/source/file => /root/user/target/file

。這很好了解,檔案系統就是一顆樹,你rename目錄,實際是把某顆子樹移動到另一個節點下。這個在NameNode裡的實作也很簡單,改變下樹結構即可。

但是如果是在OSS上,你要做rename,那你不得不遞歸周遊

/root/user/source

把其下所有目錄對象,檔案對象都rename。因為你沒法通過移動子樹這樣一個簡單操作一步到位。這裡帶來的問題就是,假設你遞歸周遊到一半,挂了。那麼就可能會出現一半目錄或檔案到了目标位置,一半沒過去。這樣rename這個操作就不是原子的了,本來你要麼rename成功,整個目錄下的内容到新的地方,要麼沒成功就在原地。是以正确性會存在問題,像HBase這樣依賴rename操作将臨時資料目錄移動到正式目錄來做資料commit,就會面臨風險。

2.OSS rename實則是資料拷貝

前面我們提到了rename,在正常檔案系統中應該是一個輕量級的,資料結構修改操作。但是OSS并沒有rename這個操作實際上,rename得通過

CopyObject

+

DeleteObject

兩個操作完成。首先是copy成目标名字,然後delete掉原先的Object。這裡有2個明顯的問題,一個是copy是深度拷貝開銷很大,直接會影響HBase的性能。另一個是rename拆分成2個操作,這2個操作是沒法在一個事物裡的,也就是說:可能存在copy成功,沒delete掉的情況,此時你需要復原,你需要delete掉copy出來的對象,但是delete依然可能不成功。是以rename操作本身實作上,正确性就難以保證了。

解決核心難點A

解決上面2個問題,需要自己做中繼資料管理,即相當于自己維護一個檔案系統樹,OSS上隻放資料檔案。而因為我們環境中仍然有HDFS存儲在(為了放熱資料),是以直接複用NameNode代碼,讓NodeNode幫助管理中繼資料。是以整體架構就出來了:

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

ApsaraDB FileSystem(以下簡稱ADB FS)将雲端存儲分為:主存(PrimaryStorageFileSystem)和 冷存(ColdStorageFileSystem)。由

ApsaraDistributedFileSystem

類(以下簡稱ADFS)負責管理這兩類存儲檔案系統,并且由ADFS負責感覺冷熱檔案。

ApsaraDistributedFileSystem: 總入口,負責管理冷存和主存,資料該從哪裡讀,該寫入哪裡(ADFS)。

主存:PrimaryStorageFileSystem 預設實作是 DistributedFileSystem(HDFS)

冷存:ColdStorageFileSystem 預設實作是 HBaseOssFileSystem(HOFS) ,基于OSS實作的Hadoop API檔案系統,可以模拟目錄對象單獨使用,也可以隻作為冷存讀寫資料,相比社群版本有針對性優化,後面會講。

具體,NameNode如何幫助管理冷存上的中繼資料,很簡單。ADFS在主存上建立同名索引檔案,檔案内容是索引指向冷存中對應的檔案。實際資料在冷存中,是以冷存中的檔案有沒有目錄結構無所謂,隻有一級檔案就行。我們再看下一rename操作過程,就明白了:

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

rename目錄的場景也同理,直接在NameNode中rename就行。對于熱檔案,相當于全部代理HDFS操作即可,冷檔案要在HDFS上建立索引檔案,然後寫資料檔案到OSS,然後關聯起來。

核心難點B

引入中繼資料管了解決方案,又會遇到新的問題:是索引檔案和冷存中資料檔案一緻性問題。

我們可能會遇到如下場景:

  • 主存索引檔案存在,冷存資料檔案不存在
  • 冷存資料檔案存在,主存索引檔案不存住
  • 主存索引檔案資訊不完整,無法定位冷存資料檔案

先排除BUG或者人為删除資料檔案因素,上訴3種情況都會由于程式crash産生。也就是說我們要想把法,把生成索引檔案,寫入并生成冷資料檔案,關聯,這3個操作放在一個事物裡。這樣才能具備原子性,才能保證要麼建立冷檔案成功,那麼索引資訊是完整的,也指向一個存在的資料檔案。要麼建立冷檔案失敗(包括中途程式crash),永遠也見不到這個冷檔案。

解決核心難點B

核心思想是利用主存的rename操作,因為主存的rename是具備原子性的。我們先在主存的臨時目錄中生産索引檔案,此時索引檔案内容已經指向冷存中的一個路徑(但是實際上這個路徑的資料檔案還沒開始寫入)。在冷存完成寫入,正确close後,那麼此時我們已經有完整且正确的索引檔案&資料檔案。然後通過rename一把将索引檔案改到使用者實際需要寫入到目标路徑,即可。

如果中途程序crash,索引檔案要麼已經rename成功,要麼索引檔案還在臨時目錄。在臨時目錄我們認為寫入沒有完成,是失敗的。然後我們通過清理線程,定期清理掉N天以前臨時目錄的檔案即可。是以一旦rename成功,那目标路徑上的索引檔案一定是完整的,一定會指向一個寫好的資料檔案。

為什麼我們需要先寫好路徑資訊在索引檔案裡?因為如果先寫資料檔案,在這個過程中crash了,那我們是沒有索引資訊指向這個資料檔案的,進而造成類似“記憶體洩漏”的問題。

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

冷熱檔案标記

對于主存,需要實作給檔案冷熱标記的功能,通過标記判斷要打開怎樣的資料讀寫流。這點NameNode可以通過給檔案設定StoragePolicy實作。這個過程就很簡單了,不詳細贅述,下面說HBaseOssFileSystem寫入優化設計。

HBaseOssFileSystem 寫入優化

在說HOFS寫設計之前,我們先要了解Hadoop社群版本的OssFileSystem設計(這也是社群使用者能直接使用的版本)。

社群版本寫入設計

Write -> OutputStream -> disk buffer(128M) -> FileInputStream -> OSS           

這個過程就是先寫入磁盤,磁盤滿128M後,将這128M的block包裝成FileInputStream再送出給OSS。這個設計主要是考慮了OSS請求成本,OSS每次請求都是要收費的,但是内網流量不計費。如果你1KB寫一次,費用就很高了,是以必須大塊寫。而且OSS大檔案寫入,設計最多讓你送出10000個block(OSS中叫MultipartUpload),如果block太小,那麼你能支援的最大檔案大小也是受限。

是以要攢大buffer,另外一個因素是Hadoop FS API提供的是OutputStream讓你不斷write。OSS提供的是InputStream,讓你提供你要寫入内容,它自己不斷讀取。這樣你必然要通過一個buffer去轉換。

這裡會有比較大的一個問題,就是性能慢。寫入磁盤,再讀取磁盤,多了這麼兩輪會比較慢,雖然有PageCache存在,讀取過程不一定有IO。那你肯定想,用記憶體當buffer不就好了。記憶體當buffer的問題就是前面說的,有費用,是以buffer不能太小。是以你每個檔案要開128M記憶體,是不可能的。更何況當你送出給OSS的時候,你要保證能繼續寫入新資料,你得有2塊128M記憶體滾動,這個開銷幾乎不能接受。

HBaseOssFileSystem 寫入設計

我們既要解決費用問題,也要解決性能問題,同時要保證開銷很低,看似不可能,那麼怎麼做呢?

這裡要利用的就是這個InputStream,OSS讓你提供InputStream,并從中讀取你要寫入的内容。那麼我們可以設計一個流式寫入,當我傳入這個InputStream給OSS的時候,流中并不一定得有資料。此時OSS調read讀取資料會block在read調用上。等使用者真的寫入資料,InputStream中才會有資料,這時候OSS就能順利讀到資料。當OSS讀了超過128M資料時候,InputStream會自動截斷,傳回EOF,這樣OSS會以為流已經結束了,那麼這塊資料就算送出完成。

是以我們本質隻要開發這麼一個特殊的InputStream即可。使用者向Hadoop API提供的OutputStream中寫入資料,資料每填滿一個page(2M)就發給InputStream讓其可讀取。OuputStream相當于生産者,InputStream相當于消費者。這裡的記憶體開銷會非常低,因為生産者速度和消費者速度相近時,也就2個page的開銷。最後将這整套實作封裝成OSSOutputStream類,當使用者要寫入冷檔案時,實際提供的是OSSOutputStream,這裡面就包含了這個特殊InputStream的控制過程。

當然實際生産中,我們會對page進行控制,每個檔案設定最多4個page。并且這4個page循環利用,減少對GC對影響。是以最後我們得到下面一個環形緩沖的寫入模式:

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

性能對比1:社群版本 vs 雲HBase版

因為不用寫磁盤,是以寫入吞吐可以比社群的高很多,下圖為HBase1.0上測試結果。在一些大KV,寫入壓力更大的場景,實測可以接近1倍。這個比較是通過替換ADFS冷存的實作(用社群版本和雲HBase版本),都避免了rename深拷貝問題。如果直接裸用社群版本而不用ADFS那性能會差數倍。

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

性能對比2:熱表 vs 冷表

熱表資料在雲盤,冷表資料在OSS。

解密 雲HBase 冷熱分離技術原理前言HBase冷熱分離常見解決方案雲HBase冷熱分離解決方案ApsaraDB FileSystem 設計總結

得益于上述優化,加上冷表WAL也是放HDFS的,并且OSS相對HBase來說是大叢集(吞吐上限高),冷表的HDFS隻用抗WAL寫入壓力。是以冷表吞吐反而會比熱表略高一點點。

不管怎麼說,冷表的寫入性能和熱表相當了,這樣的表現已經相當不錯了。基本是不會影響使用者灌資料,否則使用冷存後,吞吐掉很多,那意味着要更多機器,那這功能就沒什麼意義了。

總結

這大約是1年多前落地的項目,已經穩定運作很久。之前也有出去分享過,但是沒有今天這麼細緻。現在寫出來主要是自我總結下。當設計一個服務去解決某個問題的時候,上下遊的關系,可能存在的問題得考慮清楚。在做這個項目最初的時候,想把HBase直接架設在社群版本OssFileSytem上,發現性能不行外,正确性也存在很大風險。不斷思考,考慮各種情況後才有了今天這套方案。

繼續閱讀