解密 雲HBase 冷熱分離技術原理

2020-12-17 阿里云云棲號

前言

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

HBase冷熱分離常見解決方案

1.主備集群

備(冷)集群用更廉價的硬體,主集群設置TTL,這樣當數據熱度退去,冷數據自然只在冷集群有。

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

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

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

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

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

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

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

雲HBase冷熱分離解決方案

上述2套方案都不是最好的方案,對於雲上來說。第一套方案就不說了,客戶搞2個集群,對於數據量不大的客戶其實根本降不了成本。第二套方案,雲上客戶千千萬,業務各有各樣,磁碟配置是很難定製到合適的狀態。

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

實現這樣的架構,最直接的想法是直接改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幫助管理元數據。所以整體架構就出來了:

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

ApsaraDistributedFileSystem

類(以下簡稱ADFS)負責管理這兩類存儲文件系統,並且由ADFS負責感知冷熱文件。

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

主存:PrimaryStorageFileSystem 默認實現是 DistributedFileSystem(HDFS)

冷存:ColdStorageFileSystem 默認實現是 HBaseOssFileSystem(HOFS) ,基於OSS實現的Hadoop API文件系統,可以模擬目錄對象單獨使用,也可以只作為冷存讀寫數據,相比社區版本有針對性優化,後面會講。

具體,NameNode如何幫助管理冷存上的元數據,很簡單。ADFS在主存上創建同名索引文件,文件內容是索引指向冷存中對應的文件。實際數據在冷存中,所以冷存中的文件有沒有目錄結構無所謂,只有一級文件就行。我們再看下一rename操作過程,就明白了:

rename目錄的場景也同理,直接在NameNode中rename就行。對於熱文件,相當於全部代理HDFS操作即可,冷文件要在HDFS上創建索引文件,然後寫數據文件到OSS,然後關聯起來。

核心難點B

引入元數據管理解決方案,又會遇到新的問題:是索引文件和冷存中數據文件一致性問題。

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

主存索引文件存在,冷存數據文件不存在冷存數據文件存在,主存索引文件不存住主存索引文件信息不完整,無法定位冷存數據文件先排除BUG或者人為刪除數據文件因素,上訴3種情況都會由於程序crash產生。也就是說我們要想把法,把生成索引文件,寫入並生成冷數據文件,關聯,這3個操作放在一個事物裡。這樣才能具備原子性,才能保證要麼創建冷文件成功,那麼索引信息是完整的,也指向一個存在的數據文件。要麼創建冷文件失敗(包括中途程序crash),永遠也見不到這個冷文件。

解決核心難點B

核心思想是利用主存的rename操作,因為主存的rename是具備原子性的。我們先在主存的臨時目錄中生產索引文件,此時索引文件內容已經指向冷存中的一個路徑(但是實際上這個路徑的數據文件還沒開始寫入)。在冷存完成寫入,正確close後,那麼此時我們已經有完整且正確的索引文件&數據文件。然後通過rename一把將索引文件改到用戶實際需要寫入到目標路徑,即可。

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

為什麼我們需要先寫好路徑信息在索引文件裡?因為如果先寫數據文件,在這個過程中crash了,那我們是沒有索引信息指向這個數據文件的,從而造成類似「內存洩漏」的問題。

冷熱文件標記

對於主存,需要實現給文件冷熱標記的功能,通過標記判斷要打開怎樣的數據讀寫流。這點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對影響。所以最後我們得到下面一個環形緩衝的寫入模式:

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

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

性能對比2:熱表 vs 冷表

熱表數據在雲盤,冷表數據在OSS。

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

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

總結

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

相關焦點

  • HBase原理 | HBase Compaction介紹與參數調優
    (舊版本中該參數是hbase.hstore.compactionthreshold)2).hbase.hstore.compaction.max默認值 10,一次Minor Compaction最多合併的HFile文件數量,這個參數基本控制著一次壓縮即Compaction的耗時。
  • HBase調優 | HBase Compaction參數調優
    hbase.hstore.compaction.max一次最多可以合併多少個HFile,默認為 10 限制某個列族下面選擇最多可選擇多少個文件來進行合併 注意需要滿足條件hbase.hstore.compaction.max > hbase.hstore.compaction.minhbase.hstore.compaction.max.size
  • HBase調優|HBase + G1GC 性能調優
    先傳送門一下,之前在HBaseConAsia2017分享過一個G1GC調優的PPT: http://openinx.github.io/2012/01/01/my-share/首先,對G1算法不熟悉的同學,可以仔細讀一讀Oracle的G1算法教程,教程基本交代了G1的運行原理以及和CMS本質區別,如果對算法細節感興趣,可以讀一下Garbage-First
  • Flink SQL 實戰:HBase 的結合應用
    當然,本文假設用戶有一定的 HBase 知識基礎,不會詳細去介紹 HBase 的架構和原理,本文著重介紹 HBase 和 Flink 在實際場景中的結合使用。主要分為兩種場景,第一種場景:HBase 作為維表與 Flink Kafka table 做 temporal table join 的場景;第二種場景:Flink SQL 做計算之後的結果寫到 HBase 表,供其他用戶查詢的場景。
  • 關於Hbase的一些常見問題
    一、通常向HBase批量導入數據有三種常用方式1、使用HBase提供的TableOutputFormat,原理是通過一個Mapreduce作業將數據導入HBase2、還有一種方式就是使用HBase原生Client
  • 深入 HBase 架構解析
    這個架構圖比較清晰的表達了HMaster和NameNode都支持多個熱備份,使用ZooKeeper來做協調;ZooKeeper並不是雲般神秘,它一般由三臺機器組成一個集群,內部使用PAXOS算法支持三臺Server中的一臺宕機
  • HBase MOB特性介紹
    MOB壓縮的初始版本將當天的多個MOB文件重寫為較大的MOB文件。通過下面示例我們可以更清楚了解這一過程。表t1有兩個分區(r1,r2),一個列族f1,並且該表啟用了MOB屬性。CDH的CDH5.4.0+及以後的版本開始使用HBase MOB特性,其中從5.11.0開始使用HBASE-16981修復的版本。 本文雖多次斟酌,但由於譯者水平有限,有翻譯不當之處還請大家多多指出,互相學習。
  • Apache HBase 出現信息洩漏漏洞 - OSCHINA - 中文開源技術交流社區
    setAcl /hbase world:anyone:r,sasl:hbase:cdrwa    setAcl /hbase/backup-masters sasl:hbase:cdrwa    setAcl /hbase/draining sasl:hbase:cdrwa    setAcl /hbase/flush-table-proc sasl:hbase
  • HBase與mapreduce集成
    在公司中,大多數都是hbase和mapreduce共同進行業務操作,hbase多數都是讀寫操作,hbase和hadoop在內部已經封裝好了,我們要做的就是調用。常見的模式1、從hbase讀取數據將hbase的數據作為map的輸入2、將數據寫入hbase將hbase作為reduce輸出3、從hbase讀,再寫入hbase
  • Hbase命令大全
    集群(與exit不同)tools列出hbase所支持的工具exit退出hbase shell    HBase Shell 是官方提供的一組命令,用於操作HBase。默認為 『summary』hbase> statushbase> status 'simple'hbase> status 'summary'hbase> status 'detailed'hbase> status 'replication'hbase> status 'replication', 'source'hbase
  • 不拘一格降HBase,數據存儲的利器,學完摸清Google存儲套路——大數據課程更新09.01
    第七階段:分布式資料庫 HBase章節1:hbase第1章1:hbase介紹2:數據結構和存儲結構3:hbase架構014:hbase架構025:hbase高可用完全分布式搭建6:hbase客戶端常用操作7:hbase數據模型進階8:LSMTree9:大合併(major)和小合併(minor)10:hbase讀寫流程 章節2:hbase第2章11:創建表phone12:添加數據和根據
  • HBase學習之路 (四)HBase的API操作
    ;  6 import org.apache.hadoop.hbase.HColumnDescriptor;  7 import org.apache.hadoop.hbase.HTableDescriptor;  8 import org.apache.hadoop.hbase.TableName;  9 import org.apache.hadoop.hbase.client.Admin; 10
  • 冷熱衝擊箱冷卻水塔原理,溫度恢復時間檢驗
    冷熱衝擊箱用於測試材料結構或複合材料,在瞬間下經極高溫與極低溫連續環境下的忍受程度,得以在最短時間內檢測試樣因熱脹冷縮所引起的化學變化或物理傷害。它的工作原理是當循環水系統安裝冷卻水塔後,高溫水流經冷卻水塔內腔時,冷卻水塔通過將高溫水流以噴霧的方式,噴淋到內腔耐高溫的填料上(填料的作用是為了增大與高溫水的接觸面積,在空氣和水的不斷接觸循環下,以達到散熱降溫製冷的效果)。再有塔頂風機快速帶動塔內氣流的快速循環,將囤積在冷卻塔內部,與水換熱後的熱氣流不斷帶出,從而增強冷卻效果。
  • 雲存儲的技術原理及實現層次
    打開APP 雲存儲的技術原理及實現層次 博客園 發表於 2020-12-24 10:50:23 二、技術原理 雲存儲作為雲計算的一個核心組成部分,承擔著數據最底層數據存儲與信息收集的任務,他是整個雲平臺、雲服務的基礎。與傳統存儲設備相比,對它的定義不能簡單的理解為是一個單一的硬體設備,這個設備也可以理解為一個系統,這個系統一般都由伺服器、存儲、網絡及相關軟體等硬體環境構成。
  • Hive整合HBase完整筆記(親測)
    TBLPROPERTIES("hbase.table.name"= "hbase_testcourse"); 指定HBase表名內部表創建語句如下:create tablecourse.hbase_testcourse(cname string,score int) STORED BY 'org.apache.
  • HBase的讀寫和javaAPI的使用
    一、hbase系統管理表hbase:namespace,記錄了hbase中所有namespace的信息 ,當前系統下有哪些namespace信息scan 'hbase:namespace'hbase:meta,記錄了region信息scan 'hbase:meta'二、讀寫思想client(get、scan)rowkey條件(1)由於rowkey是存儲在region
  • HBase基礎環境搭建
    遠程工具連接關閉Selinux關閉防火牆chkconfig iptables off修改主機名第一個network,修改後,將主機命名為masterhbaseNETWORKING=yes#HOSTNAME=localhost.localdomainHOSTNAME=masterhbase
  • 讓餐廳放心的雲服務-雅座CRM技術解密
    本文來自雅座CTO對其CRM技術的解密分享。以下為原文:一. CRM雲服務的系統瓶頸雅座CRM歷經9年的成長,累計為超過15000家餐飲門店提供精準營銷服務,管理超過5000萬會員數據,日交易流水超百萬筆,年交易額達200億以上。雅座提供專業的企業級SaaS雲服務,對系統的安全性、穩定性、可靠性要求極高,這是企業的基本訴求。
  • HBase基礎學習之bulkload了解
    之前在學習importTSV我們準備兩份數據這兩份數據在導入hbase後,數據還是存在的,我們如果想要實現和hive中類似「剪切」的功能該怎麼辦?這種可以跨過先寫入memstore,直接將數據轉換為storefile文件。
  • 深入淺出HBase keyValue動態讀寫流程
    帶著這個問題,我們來一起學習下客戶端是如何讀寫HBase數據的,進而幫助大家理解HBase讀寫相關原理。-ROOT-表被去掉了,同時zk中的/hbase/root-region-server也被去掉了。還直接把.META.表所在的RegionServer信息存儲到了zk中的/hbase/meta-region-server去了。再後來引入了namesapce,.META.表被更名為hbase:meta。