第五章:大數據 の HBase 進階


本課主題

  • HBase 讀寫數據的流程
  • HBase 性能優化和最住實踐
  • HBase 管理和集群操作
  • HBase 備份和復制

 

引言 

前一篇 HBase 基礎 (HBase 基礎) 簡單介紹了NoSQL是什么和重點討論 HBase 數據庫的特點,在這一篇會進一步介紹 HBase 的其他特性和機制,比如讀寫數據的流程,在讀寫過程中 WAL,MemStore 的作用,還會談談一些數據緩存機制,明白在什么場景下需要用那一種緩存策略?如何對頻繁使用的數據進行快速響應,從檢索上提升查詢效率和從內存層面上運用不同組合來優化。還會從 HBase 表設計、Scama 設計、索引選項、緩存設置、Region 的預拆分和數據傾斜的角度去了解 HBase 的性能優化和最佳實踐,最后會談談一些 HBase 維護的操作,比如備份和復制,希望讀者看完這篇文章可以了解以下幾點:

  • 了解 HBase 在讀寫數據時 WAL, MemStore 和 BlockCache 的作用;
  • 了解 HBase 的數據緩存機制和如何通過參數調優來達至最佳效果;
  • 了解如何對 HBase 進行性能調優
  • 了解 HBase 的備份和復制;

  

HBase 讀寫數據的流程

HBase 寫操作

MemStore 是數據塊中的一個內存區域,它可以提升寫出數據的效率,新增或更新的數據會寫入 MemStore,然后再由 MemStore 寫入磁盤。當客戶端收到一個 Put 請求時會先查詢 hbase:meta 元數據來定位將要寫入的數據的 Region 位置,具體操作細節會交給 Region 實體來完成;

[下圖是寫入數據的步驟]

  • 先寫入 WriteAheadLog (WAL) 日志中,它記錄數據操作整個流程,WAL 是寫入 HDFS 集群文件系統上,一旦寫入動作失敗,可以從 WAL 恢復過來。默認參數 writeToWAL 為 true,意思是數據會先寫入 WAL 日志;
  • 然后才寫入 MemStore 內存塊中。MemStore 內存塊如果滿了,才會刷新寫入本地磁盤的 StoreFile 上。刷新是由獨立的 RegionServer 線程來完成的。注意:MemStore 只會在內存區域存在的,如果數據寫入了 MemStore 但還沒來得寫入磁盤已經漰潰,此時,數據便會掉失。

HBase 文件類型

  • HLog 是 HBase 的日志文件,它使用了 WAL 的數據格式,它是一個標准的 Hadoop SequenceFile,存儲了 HLogKey 以及實際數據,HLogKey 用於服務器 Crash 后恢復那些未被永久存儲的數據;
  • HFile 用於存儲文件的格式,HFile 分解成更小的片段叫做塊。默認的塊大小是 64K,任何時候的操作都是整塊的讀取
  • 一個 HFile 是由多個塊組成的,在 HDFS 上一個 HFile 可以是 GB 大小,HBase 塊大小可以在列族級別進行配置,小塊可以增加隨機讀的速度,大塊可以提高掃描的性能

以下是MemStore 刷出 StoreFile 的條件

  • 達到 hbase.regionserver.global.MemStore.upperLimit,默認是 0.4 或者是 heapSize 的 40%;
  • 達到 hbase.hregion.MemStore.flush.size,默認是 128MB;
  • 達到 hbase.hregion.preclose.flush.size,默認是 5MB 並且 region 已經關閉;

以下是MemStore 刷新阻塞更新的條件

  • MemStore 大小達到 hbase.hregion.MemStore.flush.size (128MB) 和 hbase.hregion.MemStore.block.multiplier (2)

RegionServer 的 Crash 重啟流程,如果 RegionServer 崩潰了,由於 MemStore 在內存中,所以數據會掉失,但是,最近的更新也會在 WAL 日志里,存儲在 HDFS 上;Region 存儲文件 (HFile) 也會存儲在 HDFS 中,HDFS 默認復制存儲的塊,集群里所有節點能夠訪問在 HDFS 中的文件;Master 可以測出 RegionServer 的失敗,Master 協調處理日志所有分拆動作;WAL 分拆是由集群中 RegionServer 來完成,Master 可以指派 Region 到其他 RegionServer 上,當完成分拆之后,RegionServer 應用 WAL 相關的內容。

[下圖是寫入數據和讀取數據與 WAL 和 BlockCache 的關系]

HBase 讀操作

當客戶端發起 get 的請求,首先會查詢 RegionServer 來定位數據在那個 Region 上,然后同時讀取該 Region 上的 StoreFile 和 MemStore, 讀取數據后會緩存在一個 BlockCache,用於后續的查詢,這種緩存的方法可以加速后續頻繁訪問數據的速度。最后 RegionServer 按照客戶端發起請求的數據從 BlockCache 把相關的數據返回給客戶端。

[下圖是讀取數據的步驟]
 

HBase 數據塊緩存

HBase 的 BlockCache 可以通過緩存元數據 hbase:meta 列族數據信息來提升數據檢索速度,HBase 有兩種類型的緩存實現

  • 第一類是 LruBlockCache,它是最初的HBase 緩存機制,是將 onheap 內存 (JVM Heap) 用於緩存;
  • 第二類是 BucketCache,它是新的HBase 緩存機制,它不局限於 onheap 內存,可以將它配置為 offheap,這樣就可以使用 JVM 以外的內存;
  • 內存的清理策略是用最近使用原則 Least Recently Used (LRU); 

LruBlockCache 的特性

LruBlockCache 的默認的塊大小是 64KB,緩存信息類型包括提供 RegionServer 服務的具體 Region 信息、HFile 的索引信息,實現 HBase 在 HFile 里快速查找數據和 Bloom Filters 信息 (當啟用此功能時),實現縮短查找時間的目的;當 LruBlockCache 寫滿之后,最近最少使用的塊會依據訪問的優先級進行清理換出。LruBlockCache 的訪問優先級,訪問優先級分組用於緩存系統確定那些塊被清除掉,LruBlockCache 的緩存數據塊被按照訪問優先級被分成三組:

  • (優先級別 - 低) Single:當我們只有一次讀取的數據,這個級別的數據塊是第一時間就會被擠出去
  • (優先級別 - 中) Mutile:讀取多次數據的緩存,這個級別的數據塊是當塊中沒有 SINGLE 級別的數據才會被擠出去
  • (優先級別 - 高) n-Memory:對列族屬性中的 IN_MEMEORY 設置為 true,這個級別的數據塊是最后才會被擠出去,Catalog 表是默認啟動了 IN_MEMORY 表的特性;

Single > Mutile > In-Memory 愈容易從內存擠出

BucketCache 的特性

BucketCache 管理以 buckets 形式組織的內存區域,使用 BucketCache 可以減少垃圾回收,因為它會直接管理 BucketCache 分配,而不是由 GC 管理;如果 BucketCache 被部署為 OffHeap,則內存根本不受 GC 管理。OffHeap BucketCache 中狻取數據的速度比 OnHeap Cache 要慢,但空間會比較大,因為垃圾收集較少,所以在讀取數據時延達會較少。 

緩存的三個策略

使用緩存有以下三個策略,有多種配置緩存的機制:

  • LruBlockCache 緩存機制:把元數據和列族信息緩存起來,如果 BucketCache 機制沒有啟動時,默認是啟動 LruBlockCache 的;
  • 混合緩存機制,運用 LruBlockCache 和 BucketCache 兩個緩存:這個策略會在 LruBlockCache 層面上緩存元數據,在 BucketCache 層面上緩存列族信息,這時啟動 BucketCache 緩存機制后默認的操作;
  • 可以使用一級和二級緩存機制 (Raw L1+L2):這個機制把元數據和列族信息緩存在LruBlockCache (一級緩存),然后從 LruBlockCache 讀取數據緩存在 BucketCache (二級緩存),如果要啟動這個緩存機制,要先在 hbase-site.xml 中配置 hbase.bucketcache.combinedcache.enabled=false,這個參數默認是 true;

通過將列族的 IN_MEMORY 屬性設置為 true 可以確保該列族的數據只有在絕對必要的情況下才會從緩存中清除。

  • BLOCKCACHE = false 和 IN_MEMORY = false,這意味著沒有緩存;
  • BLOCKCACHE = true 和 IN_MEMORY = false,這意味著使用 最近使用原則 Least Recently Used (LRU) 緩存;
  • BLOCKCACHE = true 和 IN_MEMORY = true,這意味著緩存度是最長久的,有優先級別來緩存數據;

啟動 BucketCache

把參數 hbase.bucketcache.size 大於 0,BucketCache 默認部署在 OffHeap 上,如果要使用 onHeap 內存,需要將 hbase-site.xml 文件中的 hbase.bucketcahce.ioengine=heap,如果要使用 file-baed 緩存,則需要把 hbase.bucketcahce.ioengine=file:PATH_TO_FILE,使用 BucketCache 有助於減少 JVM 的垃圾收集,以便緩解 RegionServer 的歷力,這時因為 LruBlockCache 在 onHeap 上存儲較少的對象;在OffHeap 模式下,BucketCache 管理所有內存的分配 (沒有引入 GC)。BlockCache 可以通過 RegionServer 的網頁界面端口來查詢緩存的使用情況。

禁用緩存

可以在每一個列族上禁用讀取緩存,使用 HBase Shell 來將讀取時不需要緩存的列族 BLOCKCACHE 參數設置為 false,使用 Java APi 在 scan 和 get 操作時使用 setCacheBlocks(false) 方法來禁用緩存,但注意是的我們不能禁用 metadata 的緩存,因為元數據信息會頻繁地被使用,那應該在什么情況下可以禁用緩存,如果數據只是使用一次,不用反覆檢索或者查找就不需要使用緩存。

BlockCache 報告

可以通過 RegionServer 網頁界面的端口 60030 會顯示塊緩存的詳細情況,信息包含當前的配置,當前使用情況,Time-in-the-cache,塊數量和塊類型

 

HBase 性能優化和最住實踐

ColumnFamily 的優化策略

列族的名稱必須是可打印字符;列族的名稱和列的描述命名盡量簡短,因為 HFile 中的每一行都會包含這些信息,過長的命名會浪費存儲空間;不經常使用的數據分開設計和使用不同列族存儲設置時分開設計;每張表不超過三個列族;列族允許數據分離,設計列族時,確保同時訪問的數據盡量存儲在同一個列族中,常用的信息放在同一個列族中;刷新 (Flush) 和 緊縮 (Compact) 操作是以 Region 為單位的,Compact 操作是以每個列族中 StoreFile 的數量觸發的,如果某個列族非常大,在進行 Flush 時,其他列族的數據可能會被刷新出去,導致數據掉失,所以如果列族愈多,I/O 負載會愈大;Compresison、Bloom filter 和 replication 都是以列族為單位進行設置的;

[下圖是列族常用的屬性]

大多數列族都可以壓縮,但不建議對存放 JPEG 和 PNG 等已經壓縮的文件再進行壓縮,壓縮解碼器有 GZIP、LZO、SNAPPY,選擇壓縮解碼器需要權限壓縮后的大小以及壓縮時間兩個因素。

alter 'movie', {NAME => 'desc', COMPRESSION => 'SNAPPY'}

BlockSize 大小的優化策略

BlockSize 塊尺寸用於每次讀請求讀取的最小數據量,大值可以提高掃描的性能,小值可以增加隨機讀的速度

 

BloomFilter 的優化策略

Bloom Filter 是由 Howard Bloom 在1970年提出的二進制向量數據結構,它具有很好的空間和時間效率,能檢測一個元素是否屬於某個集合。Bloom Filter 是一個數據結構,它可以檢測某個數據片是否存在,存在的檢測結果是"no" 或者是"maybe",結果 no 表示一定不存在,結果 maybe 不表示數據一定存在HBase 支持使用 Bloom Filter 改進讀取性能,Bloom Filter 的好處是無需讀取每個存儲文件,讓 RegionServer 可以忽略掉不包含某些行 (Row) 或者是行和列 (RowCol) 的文件

alter 'movie', {NAME => 'desc', BLOOMFILTER => 'ROW'} 

Bloom Filter 的最佳埸景是如果有大量的文件是無需讀取的,因為它的目的是通過減少大量讀取文件的數量來提升讀取性能;批量更新數據,這樣行 (Row) 分布在少數的存儲文件中,Bloom Filter 不適合用於所有行 (Row) 都需耍定期更新,並且這些行分布在不同的存儲文件中。雖然 Bloom Fiilter 存放在 StoreFile 中,但它不會給存儲帶來太大的額外負擔。

 

Schema 的優化策略

設計模型的基本原理包含 Schama 設計X總了 HBase 設計的所有基本方面,其中要思考的是設計行鍵和列族、將數據隔離開到不同的列族、選擇合適的壓縮機制和塊大小等,通用的設計技巧有優化索引、數據分區和一致性的 Hash 值,在設計時要充分考慮 HBase 體系結構的限制,因為在 HBase 上關聯表的開銷會非常大,所以應該盡可能避免 Join 操作,數據應該是反規范化設計以避免連接操作,其次行鍵 (RowKey) 必須更智能,以便利用排序來優代讀取。在表的設計有 Tall-Narrow 和 Wide-Flat,它們兩者占用的存儲空間都是相同的:

  • Tall-Narrow (高瘦型),這是一種 "列很少行很多" 的設計,它的原子性更弱,因為所有數據在不同行,all-Narrow (高瘦型) 通常會把更多的細節放在行鍵設計上,如果你進行 scan 操作,建議使用高瘦型
  • Wide-Flat (矮胖型),這是一種 "列只有一行但有多個列" 的設計,表的行是不可以拆分,如果行非常寬,那么你可以讓每個 Region 只有一行,如果你需要每一次查詢多種屬性的話,可以使用矮胖型

索引的選項

如果執行許多實時查詢 (Ad-Hoc Query),有可能需要使用 RDBMS 系統,如果在 HBase 上要進行關聯操作都需要額外的空間和運算,在關系型數據庫中的索引管理是更成熟更先進,但 HBase 在大數據情況下擴展會更好,如果必須在 HBase 上進行二次索引,可以有以下方法:

  • 使用 API 運行過濾查詢,但這不利於一張大表進行全表掃苗;
  • 創建一個第二索引,可以通過一個 MapReduce 作業定期更新表,或者在數據發布到集群時雙寫 (Dual-Write);
  • 創建匯總表 (Aggregrate Table),這適用於時間跨度大的數據,通常通過 MapReduce 作業生成,用於預先計算實時查詢的數據,例如:計算表中某個值不同實例的數目,並將這些匯總的計數寫入另一張表中;

 

緩存的優化策略

在 HBase 中如何配置緩存,LruBlockCache 是用於讀取 OnHeap,是基於內存的緩存,當緩存達到上限時會使用 LRU (Least Recently Used) 算法來清除數據;新 BucketCache 特性允許一級(L1) 和二級(L2) 緩存,BucketCache是默認啟動的;如果你是數據使用率很低或者是只用一次,可以通過手動修改列族的 BLOCKCACHE 屬性為 false 來禁用數據緩存,這樣可以避免很少訪問的列族數據污染了緩存區。

如何配置一級和二級緩存

  1. BucketCache 特性允許設置一級緩存和二級緩存,BucketCache 緩存機制在新 HBase 版本之后是一個默認選項,一級緩存僅存儲元數據信息,二級緩存僅存儲列族數據;
  2. 通過設置 CACHE_DATA_IN_L1=true 來對某特定列族的數據設定為一級緩存;
  3. 通過設置 BUCKET_CACHE_COMBINED_KEY=false,可以將 BucketCache 作為一級緩存和二級緩存使用;

在配置緩存時我們需要考慮是否調用 OnHeap 或者是 OffHeap 的內存,還有使用的應用類型是 Read-Heavy 類型或者是 Write-Heavy 類型,可以通過調整緩存配置來實現性能要求。 在生產環境下建議給 HBase Master JVM 分配 1G 的內存,給 HBase Region Server JVM 分配 12G~16G 的內存, 如果較大的 Heap 尺寸會導致較長時間的 GC 垃圾回收時間,剩餘的系統內存用於 Kernel 的緩存,可以在 hbase-env.sh 里進行內存設置配置

export HBASE_REGIONSERVER OPTS="-Xmx12g -Xms12g -Xmn128m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70"
export HBASE_MASTER_OPTS="-Xmx1000m"

 

數據傾斜導致的熱點問題以及優化策略

當只有很少的 RegionServer 處理絕大多數工作負載時就會發生熱點問題,因為這會導致集群資源使用不均,行鍵如果順序或者是時間序列就有可能導致熱點,因為這會導致寫出數據都是在同一個 Region 中,如果能夠把數據傾斜的數據打散就有可能解決熱點問題,以下是幾個解決數據傾斜的熱點方案:

  • 加 salt:在真正的數據前面放一個較小的 Hash 計算后的值,以便將行鍵 RowKey 隨機打散,e.g. <salt><timestamp> 
  • 字段前置:將行鍵 RowKey 后面的內容移到遞增或者是時間戳字段之前,e.g. <sourceid><timestamp>
  • 偽隨機數:使用 MD5 之類的單向 HASH 值對數據進行處理:<md5(timestamp)>

 

Region 預拆分的優化策略

在實際生產環境下是不建議 Region 的數量過少,RegionServer 建議為 20 到小幾百個 Region 服務,因為一個 RegionServer 上如果有過大的 Region 會導致擴展問題。每個 RegionServer 服務的 Region 並不是顯式配置的,這是由數據量和最大 Region 的大小所決定的。公式是:Region 拆分大小等於該服務器上同一張表的 Region 個數的平方乘以 Region Flush Size 或者設置的最大 Region 拆分大小,取兩者之中較小的值。可以修改 hbase.hregion.max.filesize 來決定 Region 的拆分大小,建議 10GB。

Region 預拆分的效果

通過 Region 預拆分來提高 HBase 的性能,預拆分后數據量加載效率更高,以下是創建預拆分 Region 的例子:

CREATE 'myTable', 'cf1', 'cf2', {SPLIT => ['A','M','Z']}

例如向一個新表中的批量加載 100GB 的數據,filsize 初始值為 10GB,當進行預拆分 Region 后,這樣每個 Region 都可以得到10GB數據,如果要增加更多數據,可以預拆分成 10-20 個 Region,這樣可以避免隨著數據的增加而出現自動拆分。預拆分 Region 是離線處理過程,Region 會在拆分的過程中短暫離線,手工拆分 Region 可以減少表的熱點問題,如果想停用預拆分 Region 功能,可以對參數 hbase.hregion.max.filesize 設置一個較大的值,比如 100GB,但要注意后續要繼續啟用拆分,Region 是可以合並在一起,可以利用 HBase Shell 的 merge_region 命令在線完成合並。

  

HBase 管理和集群操作

HBase Master 的工作

HBase Master 處理 HBase 集群下很多核心功能,包括協調 RegionServer 並管理故障轉移,負責將 Region 重分配到其他 RegionServer 上;處理表和列族的修改和增加,同時更新 hbase:meta 數據,也會管理 Region 變化,例如 Region 分裂或分配的收尾工作,多個 Master 可以在同一時間運行,但只有一個 Master 是 Active 狀態,當 Master 失敗后,其他 Master 竟爭成為 Active 狀態。

HBase Master 后台進程

HBase 的 LoadBalancer 進程用來將一個表的多個 Region 分發到多個 RegionServer 上;Catalog Janitor 進程檢查不可用的 Region 進行垃圾回收 ;Log Cleaner 進程用於刪除陳舊的 WAL 文件。

 

HBase RegionServer 的工作

RegionServer 處理數據的移動,通過 get 和 scan 讀取數據然后將數據回傳給客戶端,存儲所有客戶端 put 進來的數據和標記所有客戶端 delete 的數據;處理所有緊縮動作包括小緊縮 (minor compaction) 和主緊縮 (major compaction);處理所有 Region 的分裂;維護 BlockCache (其中包括 Catalog table、索引、Bloom filter 和數據塊都在 BlockCache 中);管理 MemStore 和 WAL,Put 和 Delete 的操作會先寫入 WAL 然后才寫入 MemStore;MemStore 會不定期刷出,接收來自 Master 的新 Region,為其提供服務,必要時重演 (Replay) WAL。

HBase RegionServer 后台進程

RegionServer 有一個 CompactSplitThread 進程來查找需要拆分的 Region (大於最大 FileSize 的 Region) 和處理小緊縮;MajorCompactionChecker 進程是檢查是否需要進行主緊縮;MemstoreFlusher 進程檢查 MemStore 是否過滿需要被刷出到磁盤;LogRoller 進程用於關閉 WAL 並創建一個新文件。RegionServer 和 DataNode 必須在同一個 節點上,因為可以實現 RegionSever 在讀取數據時達到數據本地化的效果

 

HBase 與 ZooKeeper 和高可用機制

ZooKeeper 是一個分布式協調工作,一組 ZooKeeper 節點配置在一起工作叫做 Quorum,在 Quorum 中,所有數據在所有節點上間保持同步,多個節點同時運行確保 ZooKeeper 的高可用性,HBase 大量使用 ZooKeeper 來維護狀態和配置信息,ZooKeepr 的 Quorum 允許多個 HBase Master 同時運行,每一個 HBase Master 競爭 ZooKeeper 管理的一個鎖來爭取成為 Active Master,如果某個 Master 在一定時間內無法獲取鎖,那么其他 HBase Master 將競爭這個鎖

  • ZooKeeper 對延達和時鍾的偏移非常敏感,需要有充足的帶寬和不堵的網絡,需要配置 NTP 來確保集群的時鍾是同步的;
  • 如果同時部署 HBase 的守護進程和 ZooKeeper,那么請將 ZooKeeper 部署到另外的磁盤上,這樣做可以減少 I/O 爭用和提升 ZooKeeper 的性能,任何共享資源都需要達到高性能。

HBase 使用 ZooKeeper 來檢測 HBase Master 和 RegionServer 的故障,因為 JVM GC 會導致長時間暫停,因為在暫停的過程中,JVM 什么都不能執行,這些暫停會導致 RegionServer 的超時,系統會以為 RegionServer 出現故障,所以目的是要盡量降低垃圾回收的時間。HBase 默認超時時間是 90 秒,RegionServer 必須在這個時間內與 ZooKeeper 進行通訊,否則系統會認為 RegionServer 已經崩潰,建議把超時時間降低為 60 秒。

在生產環境下不建議 ZooKeeper Quorum 和 DataNodes、RegionServers 部署在一起;可以創建獨立的 ZooKeeper Quorum,所有節點和客戶端必須能夠訪問 ZooKeeper 集合體;Quorum 有3個節點時備高可用性。

 

HBase 集群部署方案

用於概念驗證 (Proof of Concept) 的集群可以讓所有 Master 節點共同於一個節點上,包括 HBase Master、ZooKeeper、NameNode、Secondary NameNode,小型生產環境集群應該讓 HBase Master 和 ZooKeeper 在獨立的節點上部署,與集群中的其他 Master 節點分開,生產環境下,需要考慮引入備用的 HBase Master 部署高可用集群。無論多大的傑群 RegionServer 和 DataNode 必須位於同一個節點上,以便實現 RegionServer 讀取數據的本地化。

 

HBase 均衡器

HBase 和 HDFS 都有均衡器,HBase 使用均衡器來均衡 RegionServer 所服務的 Region;HDFS 的均衡器通過移動 HDFS 上的數據塊到不同節點上的 DataNode 實現數據均衡。HDFS 的均衡器對 HBase 是無法感知的,當添加新的節點時需要運行 HDFS 均衡器,不過 HDFS 均衡器會破壞 HBase 的數據本地性,因為原本有一個 RegionServer 的數據會被移動到另一個 RegionServer,但會在主緊縮操作完畢或者 Flush 刷新后,慢慢地實現數據本地化

如何使用均衡器 

HBase 有一個負載均衡器進程,基於 RegionServer 所服務的 Region 數量來進行均衡,均衡器是表感知的,它可以將一個表的 Region 分散到多個 RegionServer 上,均衡器默認每 5 分鍾執行一次,均衡器在移動期間,表會暫時的離線,在主緊縮實現之前,移動的 Region 會暫時失去了數據本地性。

 

HBase 相關錯誤

HBase 對數據服務信息有嚴格的要求,每個 Region 必須分配和部署到一個 RegionServer,每個表的行鍵必須只包含在一個 Region 里,HBase 數據會寫出到 HDFS 和 HBase 的 Catalog 表,HBase 能通過 HDFS 上的數據進行自我修復然后更新 Catalog 表以保持匹配。

修復 HBase

有些問題可以在線,但有些問題不得不通過離線進行修復,離線檢測的是指 HBase 正在運行,但是集群處於未被激活的狀態;一些不一致可能是暫時的,有些錯誤會在過度期顯示出來,但是再檢查又不會顯示出來,在升級到下一個版本需要執行一次檢查,每一個修復操作的嚴重程度和修復難度都不一樣;修復離線問題是最復雜的,不一致可能發生有表和 Region 級別,例如:

  • Region 的元數據信息沒有存放到 HDFS 上 (離線);
  • 一個 Region 與另一個 Region 部分重復 (離線);
  • 一個 Region 沒有分配給 RegionServer (在線);
  • 超過一個 RegionServer 為一個 Region 提供服務 (在線);
  • 表的部份行鍵沒有包含在一個 Region 里 (在線);
  • hbase:meta 顯示 Region 分配不正確 (在線);

建議使用一個單獨的集群來試驗可能的解決方案並進行驗證,拷貝表到一個獨立的集群后,測試修復並解決任何問題,修復測試完畢后再應用到集群中

用 hbck 修復 HBase

HBase 有一致性檢查工具叫 hbck,這類似於文件系統的檢查工具,它會檢查所有表和 Region 是否合符 HBase 要求,但不會做仕何的修改,以 hbase 用戶身份運行 hbck 需要有文件訪問權限

sudo -u hbase hbase hbck

如果 HBase 沒有問題,最終的結果會顯示 Status: OK;如果 HBase 有問題,最終的結果會顯示 inconsistencies detected. Status: INCONSISTENT,常規的 HBase 操作可能會導致暫時的不一致,過一會兒再進行檢查來確認;運行 hbck,選擇修復模式能修復不一致問題 (僅在所有其他方式都無效才嘗試 hbck -repair)

sudo -u hbase hbase hbck -repair

運行修復后,hbck 會運行另一個一致性檢查,驗證所有問題是否已經修復,成功修復后的輸出結果是 0 inconsistencies detected. Status: OK,如果修復后還是顯示不一致,運行另一個 hbck 檢查校驗來查看異常錯誤。

 

HBase 安全

HBase 有內置的安全功能可以限制訪問和權限,需要在啟動 Kerberos 的 Hadoop 集群中啟動安全,用戶被受於特定的權限,可以受於的權限級別有全局或者 namespace、表、列族、列描述符或者每個 Cell,用戶被受於的權限有 Read、Write、Execute 或者 Admin;啟動安全可能會將最大的吞吐能力降低 5~10%。

如何配置 HBase 安全

  • 必須配置 HBase 使用安全的 RPC 引擎;
  • Kerberos 必須被加到 HBase 配置中;
  • HBase Master、RegionServer 和客戶端必須用安全的 ZooKeeper 進行連接;
  • 必須啟用控制訪問的 HBase 協處理器;
  • 訪問 HBase 必須授於訪問權限;

在 HBase Shell 中授於權限例子 e.g. grant 'username', 'permissions', <table>,<colfam>,<coldesc> R=讀取表、W=寫出表,X=在表上執行協處理器, C=Create,Alter,Delete 表,A=管理表

授於 create、delete 和 alter 給所有表

hbase> grant 'enmoedu', 'C'

授於 read、write 給所有表

hbase> grant 'enmoedu', 'RW', 'movie'

授於 read 給一個特定的列描述符

hbase> grant 'enmoedu', 'R', 'movie', 'desc', 'title'

從一個用戶回收一個權限

hbase> revoke 'enmoedu', 'RW'

 

HBase 備份和復制

HBase 復制

HBase 有多種備份方法,可以對所有表進行 put 和 delete 操作,使用 HBase 的內置復制或者在集群之間手工拷貝表,HBase 集群支持之間的復制,新添加或刪除的數據會自動添加到其他集群,復制是基於每一個列族完成的。

HBase 復制的規則

HBase 通過傳輸 WAL 日志來復制數據,雖然復制是異步的,但最終也會一致的,只有寫入WAL的操作才會被復制,沒有寫 WAL 的 put 操作是不會被復制,批量導入是不會被復制 (因為該操作禁用了 WAL),更新操作是原子性的,它們至少會被傅輸一次。HBase 會使用 ZooKeeper 來維護復制狀態,e.g. 要復制的集群列表、要復制的 WAL 日志列表和已經復制完畢的日志位置。

HBase 復制警告

集群間通常相差1~2秒,這是假定了有充份的寬帶,如果寬帶不足,集群備份會滯后;命令執行的同時,復制就開始了;列族的設置調整不會被復制;停止復制要慎用,因為復制停止期間對數據的寫入不會被復制;如果集群間的網絡中斷了,復制會在網絡修復后自動恢復。

[下圖是單向復制]

如何設置復制

所有要復制的列族必須配置,相同的表和列族必須在目標集群中存在,但並不是所有的列族都需要被復制,創建一個列族,把 REPLICATION_SCOPE 設置成 1 或 0,這是用於開啟或關閉復制,默認是 0 (關閉狀態)。

hbase> create 't1', {NAME => 'colfam1', REPLICATION_SCOPE => '1' }

HBase 必須配置啟用復制和知道要復制給那個集群,在 Production Cluster 中輸入以下復制語句,第一個參數是 peer_id 是標示集群的唯一 ID,第二個參數是 ZooKeeper 的 Quorum,中間以逗號分隔,后面是 HBase 的 root znode,Peer 不是配置文件中設置的,它是保存在 ZooKeeper 中。

hbase> add_peer '2', "bi1,bi2,bi3:2181:/hbase"

復制類型有以下三種略

  • Master-Worker 復制是從 Master 到 Worker 的單向復制;
  • Master-Master 是集群間的雙向復制:兩個集群同時開啟復制,在生產環境下,增加 DR 集群作為一個 Peer;然后在 DR 集群中添加生產集群作為 Peer;

    hbase> add_peer '2', "dr1,dr2,dr3:2181:/hbase"
    hbase> add_peer '1', "prod1,prod2,prod3:2181:/hbase"
  • 循環復制用於有兩個集群以上的集群間復制;

驗證復制 

檢查所有 peer 都設置正確,hbase> list_peers,驗證 peer 都指向正確的集群 ID,驗證所有要復制的 peer,運行 VerifyReplication 驗證每一步都是正確的。

 

HBase 備份 

一些備份方法只是保存數據,而表、列族和設置必須手工方式重建,其他備份基於 PIT (基於時間點的),注意,備份時間點之后的內容不會被保存,一些備份方法可以在集群在線的狀態下完成,其他的備份方法要求所有 HBase 進程都要停下來之后才能進行操作。CopyTable 可以在集群內拷貝也可以拷貝到另外的集群,比如在同一個集群內,生成一個表的拷貝,首先需要劍建一個和原始表含有相同列族的目標表,然后運行

hbase org.apache.hadoop.hbase.mapreduce.CopyTable --new.name=targettable originaltable

HBase 有內置程序來完成導入和導出表,導出表到 HDFS 的動作只備份數據,而不包括元數據信息

hbase org.apache.hadoop.hbase.mapreduce.Export table hdfspath

從 HDFS 中導入一張表 ,創建 HBase 目錄表,然后運行

hbase org.apache.hadoop.hbase.mapreduce.Import table hdfspath

ImportTSV 實現更高級的數據導入,導入的數據必須是帶分隔符的文本文件,列族和每一個列的列描述符必須通過 importtsv.columns 進行配置,如果給出的是錯誤的列數,作業會報錯失敗。 

hbase org.apache.hadoop.hbase.mapreduce.ImportTsv \
-Dimporttsv.columns=HBASE_ROW_KEY,fam1:col table hdfspath

 如果有分隔符 e.g. Tab,可以通過 importtsv.separator 進行配置

hbase org.apache.hadoop.hbase.mapreduce.ImportTsv \
-Dimporttsv.columns=HBASE_ROW_KEY,fam1:col \
'-Dimporttsv.separator=|' table hdfspath

ImportTSV 是按行進行 put 操作,可以輸出到一個 HFile 中實現批量加載,使用 importtsv.bul.output 並提供用於寫出的 HDFS 路徑和表名

hbase org.apache.hadoop.hbase.mapreduce.ImportTsv \
-Dimporttsv.columns=HBASE_ROW_KEY,fam1:col \
-Dimporttsv.bulk.output=/path/for/output table hdfspath

LoadIncrementalHFiles 用於導入 ImportTSV 創建的 HFile, 批量加載實現了高效地數據加載,對於時間序列以及順序數據的加載幫助尤其大,這個批量我動作不會運行單行的 put,通過一次性加載所有數據避免了熱點問題,批量加載執行過程中,表仍然是在線狀態,但這只能用於批處理或者加載增量的數據。

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /path/for/output table

可以進行全備動作,全備可以通過拷貝 HBase 目錄到 HDFS 的方式來完成,只能通過離線拷貝的方式來完成,所有 HBase 的守護進程必須停止,防止拷貝期間出現變化,可以使用 HDFS 的 distcp 命令來完成,distcp 命令使用 MapReduce 執行幾個節點上的1拷貝動作,也可以通過修改 hbase.rootdir 備份目錄的方式來完成恢復備份。

hadoop distcp /hbase /hbasebackup

快照是一個元數據的集合,允許管理員恢復到表的先前狀態,快照創建 HBase 表的元數據備份,快照是對包含表數據的文件目錄的引用,不拷貝任何數據,快照存儲在 HDFS 上,快照不會刪除,當不需要的時候通過手工方式刪除,快照可以在集群在線狀態下完成。

  • 創建快照 e.g. hbase> snapshot 'table', 'snapshotName'
  • 通過快照創建一個新表 e.g. hbase> clone_snapshot 'snapshotName','newtablename'
  • 通過快照還原表到生成快照的那個時刻,表必須先禁用。e.g. hbase> restore_snapshot 'snapshotName'
  • 查看已經存在的快照列表 e.g. hbase> list_snapshots
  • 導出快照到其他集群上,導出快照操作會同時績貝數據和元數據到目標集群,數據和元數據都是直接從 HDFS 到 HDFS 的拷貝,不會同到 RegionServer,
  • 構成快照的文件不會默認被刪除,必須確認有足夠的存儲空間來存放在生成快照期間的整個表,合並快照引用的區域會引起快照和克隆表中數據的丟失,復制啟動時還原一個表會導致兩個集群不同步,復制集群中的表沒有還原
    hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot \
    -snapshot 'snapshotName' -copt-to hdfs://binamenode:8082/hbase
  • 快照上的 MapReduce,HBase 可以在快照上執行 MapReduce 作業,對於運行資源密集型 MapReduce 作業非常有用,快照能拷貝到不同集群,避免了主生產集群的負載,將文件導出 HBase 要注意的安全問題,繞過了 ACL、標簽可見性、HBase 集群的加密,底層文件系統和服務器的權張控制著對快照的訪問權限。

4 種備份方法包含 Snapshot、CopyTable、Export 和 distcp。Snapshot、CopyTable、Export 方法提供了基於時間點 (PIT) 的一致備份,distcp 提供了全部的一致性,為了實現完整的一致性,distcp 要求集群在離線狀態下執行拷貝操作。備份和復制功能是不相同的,備份包含完整的數據集,支持數據的全部恢復,包含一個具體時間點的數據集;復制接近實時的集群復制,一個集群上的用戶錯誤將會立刻復制到其他集群上!

hbase> set_quota TYPE=>THROTTLE, TABLE=>'movies', LIMIT=>'100req/sec'
hbase> set_quota TYPE=>THROTTLE, USER=>'jim', TABLE=>'hits', LIMIT=>'2M/sec'

  

 

參考資料

[1] 第四章:大數據 の HBase 基礎

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM