溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

發(fā)布時間:2021-12-08 09:22:48 來源:億速云 閱讀:698 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么”,在日常操作中,相信很多人在HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1 HBase 淺析

1.1 HBase 是啥

HBase 是一款面向列存儲,用于存儲處理海量數(shù)據(jù)的 NoSQL 數(shù)據(jù)庫。它的理論原型是Google 的 BigTable 論文。你可以認為 HBase  是一個高可靠性、高性能、面向列、可伸縮的分布式存儲系統(tǒng)。

HBase 的存儲是基于HDFS的,HDFS 有著高容錯性的特點,被設(shè)計用來部署在低廉的硬件上,基于 Hadoop 意味著 HBase  與生俱來的超強的擴展性和吞吐量。

HBase 采用的時key/value的存儲方式,這意味著,即使隨著數(shù)據(jù)量的增大,也幾乎不會導(dǎo)致查詢性能的下降。HBase  又是一個面向列存儲的數(shù)據(jù)庫,當(dāng)表的字段很多時,可以把其中幾個字段獨立出來放在一部分機器上,而另外幾個字段放到另一部分機器上,充分分散了負載的壓力。如此復(fù)雜的存儲結(jié)構(gòu)和分布式的存儲方式,帶來的代價就是即便是存儲很少的數(shù)據(jù),也不會很快。

HBase 并不是足夠快,只是數(shù)據(jù)量很大的時候慢的不明顯。HBase主要用在以下兩種情況:

單表數(shù)據(jù)量超過千萬,而且并發(fā)量很大。

數(shù)據(jù)分析需求較弱,或者不需要那么實時靈活。

1.2 HBase 的由來

我們知道 Mysql 是一個關(guān)系型數(shù)據(jù)庫,學(xué)數(shù)據(jù)庫的時第一個接觸的就是 MySQL 了。但是 MySQL  的性能瓶頸是很大的,一般單個table行數(shù)不宜超過500萬行,大小不宜超過2G。

我們以互聯(lián)網(wǎng)公司最核心用戶表為例,當(dāng)數(shù)據(jù)量達到千萬甚至億級別時候,盡管你可以通過各種優(yōu)化來提速查詢,但是對單條數(shù)據(jù)的檢索耗時還是會超出你的預(yù)期!看下這個User表:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

假如查詢 id=1 這條數(shù)據(jù)對應(yīng)的用戶name,系統(tǒng)會給我們返回aa。但由于MySQL是以行為位單位存儲的,當(dāng)查 name 時卻需要查詢一整行的數(shù)據(jù),連  age 和 email 也會被查出來!如果列非常多,那么查詢效率可想而知了。

我們稱列過多的表為寬表,優(yōu)化方法一般就是對列進行豎直拆分:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

此時查找 name 時只需要查找 user_basic  表,沒有多余的字段,查詢效率就會很快。如果一張表的行過多,會影響查詢效率,我們將這樣的表稱之為高表,可以采用水平拆表的方式提高效率:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

這種水平拆分應(yīng)用比較多的 場景就是日志表,日志信息每天產(chǎn)生很多,可以按月/按日進行水平拆分,這樣就實現(xiàn)了高表變矮。

上述的拆分方式貌似可以解決寬表跟高表問題,但是如果有一天公司業(yè)務(wù)變更,比如原來沒有微信,現(xiàn)在需加入用戶的微信字段。這時候需要改變表的結(jié)構(gòu)信息,該怎么辦?最簡單的想法是多加一列,像這樣:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

但是你要知道不是所有用戶都要微信號的,微信號這一列是設(shè)置默認值還是采取其他的做法就得權(quán)衡一下了。如果需擴展很多列出來,但不是所有的用戶都有這些屬性,那么拓展起來就更加復(fù)雜了。這時可以用下JSON格式的字符串,將若干可選擇填寫信息匯總,而且屬性字段可以動態(tài)拓展,于是有了下邊做法:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

至此你可能認為這樣存儲數(shù)據(jù)它不挺好的嘛,用 HBase 出來干嘛?Mysql  有個致命缺點,就是當(dāng)數(shù)據(jù)達到一定的閾值,無論怎么優(yōu)化,它都無法達到高性能的發(fā)揮。而大數(shù)據(jù)領(lǐng)域的數(shù)據(jù),動輒 PB  級數(shù)據(jù)量,這種存儲應(yīng)用明顯是不能很好的滿足需求的!并且針對上邊的問題,HBase 都有很好的解決方案~~。

1.3 HBase 設(shè)計思路

接著上邊說到的幾個問題:高表、寬表、數(shù)據(jù)列動態(tài)擴展,把提到的幾個解決辦法:水平切分、垂直切分、列擴展方法 雜糅在一起。

有張表,你怕它又寬又高跟動態(tài)擴展列,那么在設(shè)計之初,就把這個表給拆開,為了列的動態(tài)拓展,直接存儲JSON格式:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

這樣就解決了寬表跟列擴展問題,高表怎么辦呢?一個表按行切分成partition,各存一部分行:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

解決了高表、寬表、動態(tài)擴展列  的問題后你會發(fā)現(xiàn)數(shù)據(jù)量大了速度不夠快咋辦?用緩存唄,查詢出的數(shù)據(jù)放緩存中,下次直接從緩存拿數(shù)據(jù)。插入數(shù)據(jù)怎么辦呢?也可以這樣理解,我把要插入的數(shù)據(jù)放進緩存中,再也不用管了,直接由數(shù)據(jù)庫從緩存拿數(shù)據(jù)插入到數(shù)據(jù)庫。此時程序不需要等待數(shù)據(jù)插入成功,提高了并行工作的效率。

你用緩存的考慮服務(wù)器宕機后緩存中數(shù)據(jù)沒來得及插入到數(shù)據(jù)庫中造成丟數(shù)據(jù)咋辦?參考 Redis  的持久化策略,可以插入數(shù)據(jù)這個操作添加一個操作日志,用于持久化插入操作,宕機重啟后從日志恢復(fù)。這樣設(shè)計架構(gòu)就變成了這個樣子:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

這就是 HBase 實現(xiàn)的大致思路。接下來正式進入 HBase 設(shè)計解析。

2 Hbase 簡介

Hbase 官網(wǎng):http://hbase.apache.org

2.1 HBase 特點

海量存儲

HBase適合存儲 PB 級別的海量數(shù)據(jù),能在幾十到百毫秒內(nèi)返回數(shù)據(jù)。

列式存儲

HBase是根據(jù)列族來存儲數(shù)據(jù)的。列族下面可以有非常多的列,在創(chuàng)建表的時候列族就必須指定。

高并發(fā)

在并發(fā)的情況下,HBase的單個IO延遲下降并不多,能獲得高并發(fā)、低延遲的服務(wù)。

稀疏性

HBase的列具有靈活性,在列族中,你可以指定任意多的列,在列數(shù)據(jù)為空的情況下,是不會占用存儲空間的。

極易擴展

基于 RegionServer 的擴展,通過橫向添加 RegionSever 的機器,進行水平擴展,提升 HBase  上層的處理能力,提升HBase服務(wù)更多 Region 的能力。

基于存儲的擴展(HDFS)。

2.2 HBase 邏輯結(jié)構(gòu)

邏輯思維層面 HBase的存儲模型如下:

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

Table(表):

表由一個或者多個列族構(gòu)成。數(shù)據(jù)的屬性如name、age、TTL(超時時間)等都在列族里邊定義。定義完列族的表是個空表,只有添加了數(shù)據(jù)行以后,表才有數(shù)據(jù)。

Column (列):

HBase 中的每個列都由 Column Family(列族) 和 Column Qualifier(列限定符)進行限定,例如  info:name、info:age。建表時只需指明列族,而列限定符無需預(yù)先定義。

Column Family(列族):

多個列組合成一個列族。建表時不用創(chuàng)建列,在 HBase  中列是可增減變化的!唯一要確定的是列族,表有幾個列族在開始創(chuàng)建時就定好的。表的很多屬性,比如數(shù)據(jù)過期時間、數(shù)據(jù)塊緩存以及是否使用壓縮等都是定義在列族上的。

HBase 會把相同列族的幾個列數(shù)據(jù)盡量放在同一臺機器上。

Row(行):

一行包含多個列,這些列通過列族來分類。行中的數(shù)據(jù)所屬的列族從該表所定義的列族中選取。由于HBase是一個面向列存儲的數(shù)據(jù)庫,所以一個行中的數(shù)據(jù)可以分布在不同的服務(wù)器上。

RowKey(行鍵):

RowKey 類似 MySQL 中的主鍵,在 HBase 中 RowKey 必須有且 RowKey 是按照字典排序的,如果用戶不指定 RowKey  系統(tǒng)會自動生成不重復(fù)字符串。查詢數(shù)據(jù)時只能根據(jù) RowKey 進行檢索,所以 Table 的 RowKey 設(shè)計十分重要。

Region(區(qū)域):

Region 就是若干行數(shù)據(jù)的集合。HBase 中的 Region  會根據(jù)數(shù)據(jù)量的大小動態(tài)分裂,Region是基于HDFS實現(xiàn)的,關(guān)于Region的存取操作都是調(diào)用HDFS客戶端完成的。同一個行鍵的 Region  不會被拆分到多個 Region 服務(wù)器上。

Region  有一點像關(guān)系型數(shù)據(jù)的分區(qū),數(shù)據(jù)存放在Region中,當(dāng)然Region下面還有很多結(jié)構(gòu),確切來說數(shù)據(jù)存放在MemStore和HFile中。訪問HBase  時先去HBase 系統(tǒng)表查找定位這條記錄屬于哪個Region ,然后定位到這個Region 屬于哪個服務(wù)器,然后就到哪個服務(wù)器里面查找對應(yīng)Region  中的數(shù)據(jù)。

RegionServer:

RegionServer 就是存放Region的容器,直觀上說就是服務(wù)器上的一個服務(wù)。負責(zé)管理維護 Region。

2.3 HBase 物理存儲

以上只是一個基本的邏輯結(jié)構(gòu),底層的物理存儲結(jié)構(gòu)才是重中之重的內(nèi)容,看下圖

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

NameSpace:

命名空間,類似關(guān)系型數(shù)據(jù)庫 DatabBase 概念,每個命名空間下有多個表。HBase有兩個自帶的命名空間,分別是hbase和default,hbase  中存放的是 HBase 內(nèi)置的表,default 表是用戶默認使用的命名空間。

TimeStamp:

時間戳,用于標識數(shù)據(jù)的不同版本(version),每條數(shù)據(jù)寫入時如果不指定時間戳,系統(tǒng)會自動添加為其寫入 HBase  的時間。并且讀取數(shù)據(jù)的時候一般只拿出數(shù)據(jù)的Type符合,時間戳最新的數(shù)據(jù)。之所以按照Type取數(shù)據(jù)是因為HBase的底層HDFS支持增刪查,但不支持改。

Cell:

單元格,由 {rowkey, column Family:column Qualifier, time Stamp} 唯一確定的單元。cell  中的數(shù)據(jù)是沒有類型的,全部是字節(jié)碼形式存儲。

3 HBase 底層架構(gòu)

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

3.1 Client

Client 包含了訪問 Hbase 的接口,另外 Client 還維護了對應(yīng)的 cache 來加速 Hbase 的訪問,比如緩存元數(shù)據(jù)的信息。

3.2 Zookeeper

HBase 通過 Zookeeper 來做 Master 的高可用、RegionServer  的監(jiān)控、元數(shù)據(jù)的入口以及集群配置的維護等工作。Zookeeper 職責(zé)如下:

通過Zoopkeeper來保證集群中只有1個Master 在運行,如果Master 發(fā)生異常會通過競爭機制產(chǎn)生新的Master 來提供服務(wù)。

通過 Zoopkeeper 來監(jiān)控 RegionServer  的狀態(tài),當(dāng)RegionSevrer有異常的時候,通過回調(diào)的形式通知MasterRegionServer上下線的信息。

通過 Zoopkeeper 存儲元數(shù)據(jù) hbase:meata 的統(tǒng)一入口地址。

3.3 Master

Master 在 HBase 中的地位比其他類型的集群弱很多!數(shù)據(jù)的讀寫操作與他沒有關(guān)系,它掛了之后,集群照樣運行。但是Master  也不能宕機太久,有很多必要的操作,比如創(chuàng)建表、修改列族配置等DDL跟Region的分割與合并都需要它的操作。

  1. 負責(zé)啟動的時候分配Region到具體的 RegionServer。

  2. 發(fā)現(xiàn)失效的 Region,并將失效的 Region 分配到正常的 RegionServer 上。

  3. 管理HRegion服務(wù)器的負載均衡,調(diào)整HRegion分布。

  4. 在HRegion分裂后,負責(zé)新HRegion的分配。

HBase 中可以啟動多個Master,通過 Zookeeper 的 Master Election 機制保證總有一個 Master 運行。

3.4 RegionServer

HregionServer 直接對接用戶的讀寫請求,是真正的干活的節(jié)點。它的功能概括如下:

  1. 管理Master為其分配的Region。

  2. 處理來自客戶端的讀寫請求。

  3. 負責(zé)和底層HDFS的交互,存儲數(shù)據(jù)到HDFS。

  4. 負責(zé)Region變大以后的拆分。

  5. 負責(zé)StoreFile的合并工作。

ZooKeeper 會監(jiān)控 RegionServer 的上下線情況,當(dāng) ZK 發(fā)現(xiàn)某個 HRegionServer 宕機之后會通知 Master  進行失效備援。下線的 RegionServer 所負責(zé)的 Region 暫時停止對外提供服務(wù),Master 會將該 RegionServer 所負責(zé)的  Region 轉(zhuǎn)移到其他 RegionServer 上,并且會對 下線RegionServer 上存在 MemStore 中還未持久化到磁盤中的數(shù)據(jù)由  WAL重播進行恢復(fù)。

3.5 WAL

WAL (Write-Ahead-Log) 預(yù)寫日志是 HBase 的 RegionServer  在處理數(shù)據(jù)插入和刪除的過程中用來記錄操作內(nèi)容的一種日志。每次Put、Delete等一條記錄時,首先將其數(shù)據(jù)寫入到 RegionServer  對應(yīng)的HLog文件中去。只有當(dāng)WAL日志寫入成功的時候,客戶端才會被告訴提交數(shù)據(jù)成功。如果寫WAL失敗會告知客戶端提交失敗,這其實就是數(shù)據(jù)落地的過程。

WAL是保存在HDFS上的持久化文件。數(shù)據(jù)到達 Region  時先寫入WAL,然后被加載到MemStore中。這樣就算Region宕機了,操作沒來得及執(zhí)行持久化,也可以再重啟的時候從WAL加載操作并執(zhí)行。跟Redis的AOF類似。

  1. 在一個 RegionServer 上的所有 Region 都共享一個  HLog,一次數(shù)據(jù)的提交先寫入WAL,寫入成功后,再寫入MenStore之中。當(dāng)MenStore的值達到一定的時候,就會形成一個個StoreFile。

  2. WAL 默認是開啟  的,也可以手動關(guān)閉它,這樣增刪改操作會快一點。但是這樣做犧牲的是數(shù)據(jù)的安全性。如果不想關(guān)閉WAL,又不想每次都耗費那么大的資源,每次改動都調(diào)用HDFS客戶端,可以選擇異步的方式寫入WAL(默認間隔1秒寫入)

  3. 如果你學(xué)過 Hadoop 中的 Shuffle(edits文件) 機制的就可以猜測到 HBase 中的 WAL  也是一個滾動的日志數(shù)據(jù)結(jié)構(gòu),一個WAL實例包含多個WAL文件,WAL被觸發(fā)滾動的條件如下。

  • WAL的大小超過了一定的閾值。

  • WAL文件所在的HDFS文件塊快要滿了。

  • WAL歸檔和刪除。

3.5 Region

每一個 Region 都有起始 RowKey 和結(jié)束  RowKey,代表了存儲的Row的范圍。從大圖中可知一個Region有多個Store,一個Store就是對應(yīng)一個列族的數(shù)據(jù),Store 由 MemStore 和  HFile 組成的。

3.6 Store

Store 由 MemStore 跟 HFile 兩個重要的部分。

3.6.1 MemStore

每個 Store 都有一個 MemStore 實例,數(shù)據(jù)寫入到 WAL 之后就會被放入 MemStore 中。MemStore是內(nèi)存的存儲對象,當(dāng)  MemStore 的大小達到一個閥值(默認64MB)時,MemStore 會被 flush到文件,即生成一個快照。目前HBase  會有一個線程來負責(zé)MemStore 的flush操作。

3.6.2 StoreFile

MemStore 內(nèi)存中的數(shù)據(jù)寫到文件后就是StoreFile,StoreFile底層是以 HFile  的格式保存。HBase以Store的大小來判斷是否需要切分Region。

3.6.3 HFile

在Store中有多個HFile,每次刷寫都會形成一個HFile文件落盤在HDFS上。HFile文件也會動態(tài)合并,它是數(shù)據(jù)存儲的實體。

這里提出一點疑問:操作到達Region時,數(shù)據(jù)進入HFile之前就已經(jīng)被持久化到WAL了,而WAL就是在HDFS上的,為什么還要從WAL加載到MemStore中,再刷寫成HFile呢?

由于HDFS支持文件創(chuàng)建、追加、刪除,但不能修改!但對數(shù)據(jù)庫來說,數(shù)據(jù)的順序非常重要!

第一次WAL的持久化是為了保證數(shù)據(jù)的安全性,無序的。

再讀取到MemStore中,是為了排序后存儲。

所以MemStore的意義在于維持數(shù)據(jù)按照RowKey的字典序排列,而不是做一個緩存提高寫入效率。

3.7 HDFS

HDFS 為 HBase 提供最終的底層數(shù)據(jù)存儲服務(wù),HBase 底層用HFile格式 (跟hadoop底層的數(shù)據(jù)存儲格式類似)  將數(shù)據(jù)存儲到HDFS中,同時為HBase提供高可用(Hlog存儲在HDFS)的支持,具體功能概括如下:

提供元數(shù)據(jù)和表數(shù)據(jù)的底層分布式存儲服務(wù)

數(shù)據(jù)多副本,保證的高可靠和高可用性

4 HBase 讀寫

在HBase集群中如果我們做 DML 操作是不需要關(guān)心 HMaster 的,只需要從 ZooKeeper 中獲得hbase:meta  數(shù)據(jù)地址,然后從RegionServer中增刪查數(shù)據(jù)即可。

4.1 HBase 寫流程

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

  1. Client 先訪問 zookeeper,訪問 /hbase/meta-region-server 獲取 hbase:meta 表位于哪個 Region  Server。

  2. 訪問對應(yīng)的 Region Server,獲取 hbase:meta 表,根據(jù)讀請求的 namespace:table/rowkey,查詢出目標數(shù)據(jù)位于哪個  Region Server 中的哪個 Region 中。并將該 table 的 Region 信息以及 meta 表的位置信息緩存在客戶端的 meta  cache,方便下次訪問。

  3. 與目標 Region Server 進行通訊。

  4. 將數(shù)據(jù)順序?qū)懭?追加)到 WAL。

  5. 將數(shù)據(jù)寫入對應(yīng)的 MemStore,數(shù)據(jù)會在 MemStore 進行排序。

  6. 向客戶端發(fā)送 ack,此處可看到數(shù)據(jù)不是必須落盤的。

  7. 等達到 MemStore 的刷寫時機后,將數(shù)據(jù)刷寫到 HFile

  8. 在web頁面查看的時候會隨機的給每一個Region生成一個隨機編號。

4.2 HBase 讀流程

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

  1. Client 先訪問 ZooKeeper,獲取 hbase:meta 表位于哪個 Region Server。

  2. 訪問對應(yīng)的 Region Server,獲取 hbase:meta 表,根據(jù)讀請求的 namespace:table/rowkey,  查詢出目標數(shù)據(jù)位于哪個 Region Server 中的哪個 Region 中。并將該 table 的 region 信息以 及 meta  表的位置信息緩存在客戶端的 meta cache,方便下次訪問。

  3. 與目標 Region Server 進行通訊。

  4. 分別在 Block Cache(讀緩存),MemStore 和 Store File(HFile)中查詢目標數(shù)據(jù),并將  查到的所有數(shù)據(jù)進行合并。此處所有數(shù)據(jù)是指同一條數(shù)據(jù)的不同版本(time stamp)或者不同的類型(Put/Delete)。

  5. 將從文件HFile中查詢到的數(shù)據(jù)塊(Block,HFile 數(shù)據(jù)存儲單元,默認大小為 64KB)緩存到 Block Cache。

  6. 將合并后的最終結(jié)果,然后返回時間最新的數(shù)據(jù)返回給客戶端。

4.2.1 Block Cache

HBase 在實現(xiàn)中提供了兩種緩存結(jié)構(gòu) MemStore(寫緩存) 和 BlockCache(讀緩存)。寫緩存前面說過不再重復(fù)。

HBase 會將一次文件查找的 Block塊 緩存到  Cache中,以便后續(xù)同一請求或者鄰近數(shù)據(jù)查找請求,可以直接從內(nèi)存中獲取,避免昂貴的IO操作。

BlockCache是Region Server級別的,

一個Region Server只有一個Block Cache,在 Region Server 啟動的時候完成 Block Cache  的初始化工作。

HBase對Block Cache的管理分為如下三種。

LRUBlockCache 是最初的實現(xiàn)方案,也是默認的實現(xiàn)方案,將所有數(shù)據(jù)都放入JVM Heap中,交給JVM進行管理。

SlabCache 實現(xiàn)的是堆外內(nèi)存存儲,不再由JVM管理數(shù)據(jù)內(nèi)存。一般跟第一個組合使用,單它沒有改善 GC 弊端,引入了堆外內(nèi)存利用率低。

BucketCache 緩存淘汰不再由 JVM 管理 降低了Full GC 發(fā)生的頻率。

重點:

讀數(shù)據(jù)時不要理解為先從 MemStore 中讀取,讀不到再讀 BlockCache 中,還讀不到再從HFile中讀取,然后將數(shù)據(jù)寫入到  BlockCache 中。因為如果人為設(shè)置導(dǎo)致磁盤數(shù)據(jù)new,內(nèi)存數(shù)據(jù)old。你讀取的時候會出錯的!

結(jié)論:

HBase 把磁盤跟內(nèi)存數(shù)據(jù)一起讀,然后把磁盤數(shù)據(jù)放到 BlockCache中,BlockCache 是磁盤數(shù)據(jù)的緩存。HBase  是個讀比寫慢的工具。

4.3 HBase 為什么寫比讀快

HBase 能提供實時計算服務(wù)主要原因是由其架構(gòu)和底層的數(shù)據(jù)結(jié)構(gòu)決定的,即由LSM-Tree(Log-Structured Merge-Tree) +  HTable(Region分區(qū)) + Cache決定的。

HBase 寫入速度快是因為數(shù)據(jù)并不是真的立即落盤,而是先寫入內(nèi)存,隨后異步刷入HFile。所以在客戶端看來,寫入速度很快。

HBase  存儲到內(nèi)存中的數(shù)據(jù)是有序的,內(nèi)存數(shù)據(jù)刷寫到HFile時也是有序的。并且多個有序的HFile還會進行歸并排序生成更大的有序HFile。性能測試發(fā)現(xiàn)順序讀寫磁盤速度比隨機讀寫磁盤快至少三個數(shù)量級!

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

讀取速度快是因為它使用了LSM樹型結(jié)構(gòu),因為磁盤尋址耗時遠遠大于磁盤順序讀取的時間,HBase的架構(gòu)設(shè)計導(dǎo)致我們可以將磁盤尋址次數(shù)控制在性能允許范圍內(nèi)。

LSM  樹原理把一棵大樹拆分成N棵小樹,它首先寫入內(nèi)存中,隨著小樹越來越大,內(nèi)存中的小樹會flush到磁盤中,磁盤中的樹定期可以做merge操作來合并成一棵大樹,以優(yōu)化讀性能。

4.3.1查詢舉例

  1. 根據(jù)RowKey能快速找到行所在的Region,假設(shè)有10億條記錄,占空間1TB。分列成了500個Region,那讀取2G的記錄,就能找到對應(yīng)記錄。

  2. 數(shù)據(jù)是按照列族存儲的,假設(shè)分為3個列族,每個列族就是666M, 如果要查詢的東西在其中1個列族上,1個列族包含1個或者多個  HStoreFile,假設(shè)一個HStoreFile是128M, 該列族包含5個HStoreFile在磁盤上. 剩下的在內(nèi)存中。

  3. 內(nèi)存跟磁盤中數(shù)據(jù)是排好序的,你要的記錄有可能在最前面,也有可能在最后面,假設(shè)在中間,我們只需遍歷2.5個HStoreFile共300M。

  4. 每個HStoreFile(HFile的封裝),是以鍵值對(KV)方式存儲,只要遍歷一個個數(shù)據(jù)塊中的key的位置,并判斷符合條件可以了。一般key是有限的長度,假設(shè)KV比是1:19,最終只需要15M就可獲取的對應(yīng)的記錄,按照磁盤的訪問100M/S,只需0.15秒。加上Block  Cache 會取得更高的效率。

  5. 大致理解讀寫思路后你會發(fā)現(xiàn)如果你在讀寫時設(shè)計的足夠巧妙當(dāng)然讀寫速度快的很咯。

5 HBase Flush

5.1 Flush

對于用戶來說數(shù)據(jù)寫到 MemStore  中就算OK,但對于底層代碼來說只有數(shù)據(jù)刷到硬盤中才算徹底搞定了!因為數(shù)據(jù)是要寫入到WAL(Hlog)中再寫入到MemStore中的,flush有如下幾個時機。

  1. 當(dāng) WAL 文件的數(shù)量超過設(shè)定值時 Region 會按照時間順序依次進行刷寫,直到 WAL 文件數(shù)量小于設(shè)定值。

  2. 當(dāng)Region Server 中 MemStore 的總大小達到堆內(nèi)存40%時,Region 會按照其所有 MemStore  的大小順序(由大到小)依次進行阻塞刷寫。直到Region Server中所有 MemStore  的總大小減小到上述值以下。當(dāng)阻塞刷寫到上個參數(shù)的0.95倍時,客戶端可以繼續(xù)寫。

  3. 當(dāng)某個 MemStore 的大小達到了128M時,其所在 Region 的所有 MemStore 都會阻塞刷寫。

  4. 到達自動刷寫的時間也會觸發(fā) MemStore 的 flush。自動刷新的時間間隔默認1小時。

5.2 StoreFile Compaction

由于 MemStore 每次刷寫都會生成一個新的 HFile,且同一個字段的不同版本(timestamp)  和不同類型(Put/Delete)有可能會分布在不同的 HFile 中,因此查詢時需要遍歷所有的 HFile。為了減少 HFile  的個數(shù)跟清理掉過期和刪除的數(shù)據(jù),會進行 StoreFile Compaction。

Compaction 分為兩種,分別是 Minor Compaction 和 Major Compaction。

  1. Minor Compaction會將臨近的若干個較小的 HFile 合并成一個較大的 HFile,但不會清理過期和刪除的數(shù)據(jù)。

  2. Major Compaction 會將一個 Store 下的所有的 HFile 合并成一個大 HFile,并且會清理掉過期和刪除的數(shù)據(jù)。

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

5.3 Region Split

每個 Table 起初只有一個 Region,隨著不斷寫數(shù)據(jù) Region 會自動進行拆分。剛拆分時,兩個子 Region 都位于當(dāng)前的 Region  Server,但出于負載均衡的考慮, HMaster 有可能會將某個 Region 轉(zhuǎn)移給其他的 Region Server。

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

Region Split 時機:

0.94 版本之前:

  • 當(dāng) 1 個 Region 中的某個 Store 下所有 StoreFile 的總大小超過  hbase.hregion.max.filesize(默認10G), 該 Region 就會進行拆分。

0.94 版本之后:

  • 當(dāng) 1 個 Region 中的某個 Store 下所有 StoreFile 的總大小超過 Min(R^2 *  “hbase.hregion.memstore.flush.size=128M”,hbase.hregion.max.filesize"),該 Region  就會進行拆分,其 中 R 為當(dāng)前 Region Server 中屬于該 Table 的個數(shù)。

舉例:

  • 第一次的閾值是128,切分后結(jié)果64 , 64。

  • 第二次閾值512M,64,512 ⇒ 54 + 256 + 256

  • 最后會形成一個 64M…10G 的這樣Region隊列,會產(chǎn)生數(shù)據(jù)傾斜問題。

  • 解決方法:提前做好Region組的規(guī)劃,0-1k,1k-2k,2k-3k這樣的。

官方不建議用多個列族,比如有CF1,CF2,CF3,但是  CF1數(shù)據(jù)很多而CF2跟CF3數(shù)據(jù)很少,那么當(dāng)觸發(fā)了region切分的時候,會把CF2跟CF3分成若干小份,不利于系統(tǒng)維護。

6 HBase 常見面試題

6.1 Hbase 中 RowKey 的設(shè)計原則

RowKey 長度原則

二進制碼流RowKey 最大長度 64Kb,實際應(yīng)用中一般為 10-100bytes,以 byte[]  形式保存,一般設(shè)計定長。建議越短越好,因為HFile是按照KV存儲的Key太大浪費空間。

RowKey 散列原則

RowKey 在設(shè)計時候要盡可能的實現(xiàn)可以將數(shù)據(jù)均衡的分布在每個 RegionServer 上。

RowKey 唯一原則

RowKey 必須在設(shè)計上保證其唯一性,RowKey 是按照字典順序排序存儲的,因此設(shè)計 RowKey 時可以將將經(jīng)常讀取的數(shù)據(jù)存儲到一塊。

6.2 HBase 在大數(shù)據(jù)體系位置

其實就簡單的把HBase當(dāng)成大數(shù)據(jù)體系下的DataBase來用就行,任何可以分析HBase的引擎比如MR、Hive、Spark等框架連接上HBase都可以實現(xiàn)控制。比如你可以把Hive跟HBase進行關(guān)聯(lián),Hive中數(shù)據(jù)不再由HDFS存儲而是存儲到HBase中,并且關(guān)聯(lián)后Hive中添加數(shù)據(jù)在HBase中可看到,HBase中添加數(shù)據(jù)Hive也可看到。

6.3 HBase 優(yōu)化方法

6.3.1 減少調(diào)整

HBase中有幾個內(nèi)容會動態(tài)調(diào)整,如Region(分區(qū))、HFile。通過一些方法可以減少這些會帶來I/O開銷的調(diào)整。

Region

沒有預(yù)建分區(qū)的話,隨著Region中條數(shù)的增加,Region會進行分裂,這將增加I/O開銷,所以解決方法就是根據(jù)你的RowKey設(shè)計來進行預(yù)建分區(qū),減少Region的動態(tài)分裂。

HFile

MemStore執(zhí)行flush會生成HFile,同時HFilewe年過多時候也會進行Merge,  為了減少這樣的無謂的I/O開銷,建議估計項目數(shù)據(jù)量大小,給HFile設(shè)定一個合適的值。

6.3.2 減少啟停

數(shù)據(jù)庫事務(wù)機制就是為了更好地實現(xiàn)批量寫入,較少數(shù)據(jù)庫的開啟關(guān)閉帶來的開銷,那么HBase中也存在頻繁開啟關(guān)閉帶來的問題。

關(guān)閉 Compaction。

HBase 中自動化的Minor Compaction和Major  Compaction會帶來極大的I/O開銷,為了避免這種不受控制的意外發(fā)生,建議關(guān)閉自動Compaction,在閑時進行compaction。

6.3.3 減少數(shù)據(jù)量

開啟過濾,提高查詢速度

開啟BloomFilter,BloomFilter是列族級別的過濾,在生成一個StoreFile同時會生成一個MetaBlock,用于查詢時過濾數(shù)據(jù)

使用壓縮

一般推薦使用Snappy和LZO壓縮

6.3.4 合理設(shè)計

HBase 表格中 RowKey 和 ColumnFamily 的設(shè)計是非常重要,好的設(shè)計能夠提高性能和保證數(shù)據(jù)的準確性。

RowKey設(shè)計

  • 散列性:散列性能夠保證相同相似的RowKey聚合,相異的RowKey分散,有利于查詢

  • 簡短性:RowKey作為key的一部分存儲在HFile中,如果為了可讀性將rowKey設(shè)計得過長,那么將會增加存儲壓力.

  • 唯一性:rowKey必須具備明顯的區(qū)別性。

  • 業(yè)務(wù)性:具體情況具體分析。

列族的設(shè)計

  • 優(yōu)勢:HBase中數(shù)據(jù)是按列進行存儲的,那么查詢某一列族的某一列時就不需要全盤掃描,只需要掃描某一列族,減少了讀I/O。

  • 劣勢:多列族意味這一個Region有多個Store,一個Store就有一個MemStore,當(dāng)MemStore進行flush時,屬于同一個Region的Store中的MemStore都會進行flush,增加I/O開銷。

6.4 HBase 跟關(guān)系型數(shù)據(jù)庫區(qū)別

指標傳統(tǒng)關(guān)系數(shù)據(jù)庫HBase
數(shù)據(jù)類型有豐富的數(shù)據(jù)類型字符串
數(shù)據(jù)操作豐富操作,復(fù)雜聯(lián)表查詢簡單CRUD
存儲模式基于行存儲基于列存儲
數(shù)據(jù)索引復(fù)雜的多個索引只有RowKey索引
數(shù)據(jù)維護新覆蓋舊多版本
可伸縮性難實現(xiàn)橫向擴展性能動態(tài)伸縮

6.5 HBase 批量導(dǎo)入

  1. 通過 HBase API進行批量寫入數(shù)據(jù)。

  2. 使用 Sqoop工具批量導(dǎo)數(shù)到HBase集群。

  3. 使用 MapReduce 批量導(dǎo)入。

  4. HBase BulkLoad的方式。

  5. HBase 通過 Hive 關(guān)聯(lián)導(dǎo)入數(shù)據(jù)。

大數(shù)據(jù)導(dǎo)入用 HBase API 跟 MapReduce 寫入效率會很低,因為請求RegionServer 將數(shù)據(jù)寫入,這期間數(shù)據(jù)會先寫入 WAL 跟  MemStore,MemStore 達到閾值后會刷寫到磁盤生成  HFile文件,HFile文件過多時會發(fā)生Compaction,如果Region大小過大時也會發(fā)生Split。

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

BulkLoad 適合初次數(shù)據(jù)導(dǎo)入,以及HBase與Hadoop為同一集群。BulkLoad 是使用 MapReduce 直接生成 HFile  格式文件后,Region Servers 再將 HFile 文件移動到相應(yīng)的Region目錄下。

HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么

到此,關(guān)于“HBase和關(guān)系型數(shù)據(jù)庫區(qū)別是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI