1. 程式人生 > 實用技巧 >HBase基本概念與基本使用

HBase基本概念與基本使用

1. HBase簡介

1.1 什麼是HBase

  HBASE是一個高可靠性、高效能、面向列、可伸縮的分散式儲存系統,利用HBASE技術可在廉價PC Server上搭建起大規模結構化儲存叢集。

  HBASE的目標是儲存並處理大型的資料,更具體來說是僅需使用普通的硬體配置,就能夠處理由成千上萬的行和列所組成的大型資料。

  HBASE是Google Bigtable的開源實現,但是也有很多不同之處。比如:Google Bigtable使用GFS作為其檔案儲存系統,HBASE利用Hadoop HDFS作為其檔案儲存系統;Google執行MAPREDUCE來處理Bigtable中的海量資料,HBASE同樣利用Hadoop MapReduce來處理HBASE中的海量資料;Google Bigtable利用Chubby作為協同服務,HBASE利用Zookeeper作為協同服務。

1.2 與傳統資料庫的對比

1、傳統資料庫遇到的問題:

  1)資料量很大的時候無法儲存;
  2)沒有很好的備份機制;
  3)資料達到一定數量開始緩慢,很大的話基本無法支撐;

2、HBASE優勢:

  1)線性擴充套件,隨著資料量增多可以通過節點擴充套件進行支撐;
  2)資料儲存在hdfs上,備份機制健全;
  3)通過zookeeper協調查詢資料,訪問速度快。

1.3 HBase叢集中的角色

  1. 一個或者多個主節點,Hmaster;
  2. 多個從節點,HregionServer;
  3. HBase依賴項,zookeeper;

2. HBase資料模型

  

2.1 HBase的儲存機制

  HBase是一個面向列的資料庫,在表中它由行排序。表模式定義只能列族,也就是鍵值對。一個表有多個列族以及每一個列族可以有任意數量的列。後續列的值連續儲存在磁碟上。表中的每個單元格值都具有時間戳。總之,在一個HBase:

    • 表是行的集合。
    • 行是列族的集合。
    • 列族是列的集合。
    • 列是鍵值對的集合。

  這裡的列式儲存或者說面向列,其實說的是列族儲存,HBase是根據列族來儲存資料的。列族下面可以有非常多的列,列族在建立表的時候就必須指定。

HBase 和 RDBMS的比較

  

RDBMS的表:

  

HBase的表:

  

2.2 Row Key 行鍵

  與nosql資料庫一樣,row key是用來表示唯一一行記錄的主鍵,HBase的資料時按照RowKey的字典順序進行全域性排序的,所有的查詢都只能依賴於這一個排序維度。訪問HBASE table中的行,只有三種方式:

    1. 通過單個row key訪問;
    2. 通過row key的range(正則)
    3. 全表掃描

  Row key 行鍵(Row key)可以是任意字串(最大長度是64KB,實際應用中長度一般為10-1000bytes),在HBASE內部,row key儲存為位元組陣列。儲存時,資料按照Row key的字典序(byte order)排序儲存。設計key時,要充分排序儲存這個特性,將經常一起讀取的行儲存放到一起。(位置相關性)

2.3 Columns Family 列族

  列簇:HBASE表中的每個列,都歸屬於某個列族。列族是表的schema的一部分(而列不是),必須在使用表之前定義。列名都以列族作為字首。例如courses:history,courses:math 都屬於courses這個列族。

2.4 Cell

  由{row key,columnFamily,version} 唯一確定的單元。cell中的資料是沒有型別的,全部是位元組碼形式儲存。

2.5 Time Stamp 時間戳

  HBASE中通過rowkey和columns確定的為一個儲存單元稱為cell。每個cell都儲存著同一份資料的多個版本。版本通過時間戳來索引。時間戳的型別是64位整型。時間戳可以由HBASE(在資料寫入時自動)賦值,此時時間戳是精確到毫秒的當前系統時間。時間戳也可以由客戶顯示賦值。如果應用程式要避免資料版本衝突,就必須自己生成具有唯一性的時間戳。每個cell中,不同版本的資料按照時間倒序排序,即最新的資料排在最前面。

  為了避免資料存在過多版本造成的管理(包括儲存和索引)負擔,HBASE提供了兩種資料版本回收方式。一是儲存資料的最後n個版本,而是儲存最近一段時間內的版本(比如最近7天)。使用者可以針對每個列族進行設定。

3. HBase原理

HBase系統架構體系圖

  

組成部件說明:

Client:

  使用HBase RPC機制與HMaster和HRegionServer進行通訊
  Client與HMaster進行管理類操作
  Client與HRegionServer進行資料讀寫類操作

Zookeeper:

  Zookeeper Quorum儲存-ROOT-表地址、HMaster地址
  HRegionServer把自己以Ephemeral方式註冊到Zookeeper中,HMaster隨時感知各個HRegionServer的健康狀況
  Zookeeper避免HMaster單點問題

  Zookeeper的主要作用:客戶端首先聯絡ZooKeeper子叢集(quorum)(一個由ZooKeeper節點組成的單獨叢集)查詢行健。上述過程是通過ZooKeeper獲取含有-ROOT-的region伺服器名(主機名)來完成的。通過含有-ROOT-的region伺服器可以查詢到含有.META.表中對應的region伺服器名,其中包含請求的行健資訊。這兩處的主要內容都被快取下來了,並且都只查詢一次。最終,通過查詢.META伺服器來獲取客戶端查詢的行健資料所在region的伺服器名。一旦知道了資料的實際位置,即region的位置,HBase會快取這次查詢的資訊,同時直接聯絡管理實際資料的HRegionServer。所以,之後客戶端可以通過快取資訊很好地定位所需的資料位置,而不用再次查詢.META.表。

HMaster:

  HMaster沒有單點問題,HBase可以啟動多個HMaster,通過Zookeeper的Master Election機制保證總有一個Master在執行
  主要負責Table和Region的管理工作:

    1. 管理使用者對錶的增刪改查操作
    2. 管理HRegionServer的負載均衡,調整Region分佈
    3. Region Split後,負責新Region的分佈
    4. 在HRegionServer停機後,負責失效HRegionServer上Region遷移

HRegionServer:

  HBase中最核心的模組,主要負責響應使用者I/O請求,向HDFS檔案系統中讀寫

  

  HRegionServer管理一系列HRegion物件;
  每個HRegion對應Table中一個Region,HRegion由多個HStore組成;
  每個HStore對應Table中一個Column Family的儲存;
  Column Family就是一個集中的儲存單元,故將具有相同IO特性的Column放在一個Column Family會更高效。

  可以看到,client訪問hbase上的資料並不需要master參與(定址訪問zookeeper和region server,資料讀寫訪問region server),master僅僅維護table和region的元資料資訊(table的元資料資訊儲存在zookeeper上),負載很低。HRegionServer存取一個子表時,會建立一個HRegion物件,然後對錶的每個列族建立一個Store例項,每個Store都會有一個MemStore和0個或多個StoreFile與之對應,每個StoreFile都會對應一個HFile,HFile就是實際的儲存檔案。因此,一個HRegion(表)有多少個列族就有多少個Store。一個HRegionServer會有多個HRegion和一個HLog。

HRegion:

  table在行的方向上分隔為多個Region。Region是HBase中分散式儲存和負載均衡的最小單元,即不同的region可以分別在不同的RegionServer上,但同一個Region是不會拆分到多個server上。

  Region按大小分隔,每個表一般是隻有一個region。隨著資料不斷插入表,region不斷增大,當region的某個列族達到一個閥值(預設256M)時就會分成兩個新的region。

  每個region由以下資訊標識:

    1. <表名,startRowKey,建立時間>
    2. 由目錄表(-ROOT-和.META.)記錄該region的endRowKey

  HRegion定位:Region被分配給哪個RegionServer是完全動態的,所以需要機制來定位Region具體在哪個region server。

  HBase使用三層結構來定位region:

    1. 通過zookeeper裡的檔案/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一個region。
    2. 通過-ROOT-表查詢.META.表的第一個表中相應的region的位置。.META.表中的每一個region在-ROOT-表中都是一行記錄。
    3. 通過.META.表找到所要的使用者表region的位置。使用者表中的每個region在.META表中都是一行記錄。

  這個查詢過程就像一個3層分散式B+樹(見下圖),-ROOT-表是B+樹的-ROOT-節點。.META.region是-ROOT-節點(-ROOT-region)的葉子,使用者表的region是.META.region的葉子。

  

  注意:

  -ROOT-表永遠不會被分隔為多個region,保證了最多需要三次跳轉,就能定位到任意的region。client會將查詢的位置資訊快取起來,快取不會主動失效,因此如果client上的快取全部失效,則需要進行6次網路來回,才能定位到正確的region,其中三次用來發現快取失效,另外三次用來獲取位置資訊。

  table和region的關係:

  table預設最初只有一個region,隨著記錄數的不斷增加而變大,起初的region會逐漸分裂成多個region,一個region有【startKey, endKey】表示,不同的region會被master分配給相應的regionserver管理。region是hbase分散式儲存和負載均衡的最小單元,不同的region分不到不同的regionServer。region雖然是分散式儲存的最小單元,但並不是儲存的最小單元。region是由一個或者多個store組成的,每個store就是一個column family。每個store又由memStore和1至多個store file組成(memstore到一個閥值會重新整理,寫入到storefile,有hlog來保證資料的安全性,一個regionServer有且只有一個hlog)                                     

HStore:

  HBase儲存的核心。由MemStore和StoreFile組成。MemStore是Stored Memory Buffer。
HLog:

  引入HLog原因:在分散式系統環境中,無法避免系統出錯或者宕機,一旦HRegionServer意外退出,MemStore中的記憶體資料就會丟失,引入HLog就是防止這種情況。

  工作機制:
  每個HRegionServer中都會有一個HLog物件,HLog是一個實現Write Ahead Log的類,每次使用者操作寫入MemStore的同時,也會寫一份資料到HLog檔案,HLog檔案定期會滾動出新,並刪除舊的檔案(已持久化到StoreFile中的資料)。當HRegionServer意外終止後,HMaster會通過Zookeeper感知,HMaster首先處理遺留的HLog檔案,將不同region的log資料拆分,分別放到相應region目錄下,然後再將失效的region重新分配,領取到這些region的HRegionServer在Load Region的過程中,會發現有歷史HLog需要處理,因此會Replay HLog中的資料到MemStore中,然後flush到StoreFiles,完成資料恢復。

3.1 HBase的儲存格式

  HBase中的所有資料檔案都儲存在Hadoop HDFS檔案系統上,格式主要有兩種:

    1. HFile,HBase中Key-Value資料的儲存格式,HFile是Hadoop的二進位制格式檔案,實際上StoreFile就是對HFile做了輕量級包裝,即StoreFile底層就是HFile。
    2. HLog File,HBase中WAL(Write Ahead Log)的儲存格式,物理上是Hadoop的Sequence File

HFile

  

  解析:

  HFile檔案不定長,長度固定的塊只有兩個:Trailer和FileInfo

  Trailer中指標指向其他資料塊的起始點

  File Info中記錄了檔案的一些Meta資訊,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等

  Data Index和Meta Index塊記錄了每個Data塊和Meta塊的起始點

  Data Block是HBase I/O的基本單元,為了提高效率,HRegionServer中有基於LRU的Block Cache機制

  每個Data塊的大小可以在建立一個Table的時候通過引數指定,大號的Block有利於順序Scan,小號Block利於隨機查詢

  每個Data塊除了開頭的Magic以外就是一個個KeyValue對拼接而成, Magic內容就是一些隨機數字,目的是防止資料損壞

  HFile裡面的每個KeyValue對就是一個簡單的byte陣列。這個byte數組裡麵包含了很多項,並且有固定的結構。

  

  KeyLength和ValueLength:兩個固定的長度,分別代表Key和Value的長度

  Key部分:Row Length是固定長度的數值,表示RowKey的長度,Row 就是RowKey

  Column Family Length是固定長度的數值,表示Family的長度

  接著就是Column Family,再接著是Qualifier,然後是兩個固定長度的數值,表示Time Stamp和Key Type(Put/Delete)

  Value部分沒有這麼複雜的結構,就是純粹的二進位制資料

HLog File

  

  HLog檔案就是一個普通的Hadoop Sequence File,Sequence File 的Key是HLogKey物件,HLogKey中記錄了寫入資料的歸屬資訊,除了table和region名字外,同時還包括 sequence number和timestamp,timestamp是“寫入時間”,sequence number的起始值為0,或者是最近一次存入檔案系統中sequence number。

  HLog Sequece File的Value是HBase的KeyValue物件,即對應HFile中的KeyValue

3.2 寫流程

  

  1) Client通過Zookeeper的排程,向RegionServer發出寫資料請求,在Region中寫資料;

  2) 資料被寫入Region的MemStore,知道MemStore達到預設閥值(即MemStore滿);

  3) MemStore中的資料被Flush成一個StoreFile;

  4) 隨著StoreFile檔案的不斷增多,當其數量增長到一定閥值後,觸發Compact合併操作,將多個StoreFile合併成一個StoreFile,同時進行版本合併和資料刪除;

  5) StoreFiles通過不斷的Compact合併操作,逐步形成越來越大的StoreFile;

  6) 單個StoreFile大小超過一定閥值後,觸發Split操作,把當前Region Split成2個新的Region。父Region會下線,新Split出的2個子Region會被HMaster分配到相應的RegionServer上,使得原先1個Region的壓力得以分流到2個Region上。

  可以看出HBase只有增添資料,所有的更新和刪除操作都是在後續的Compact歷程中舉行的,使得使用者的寫操作只要進入記憶體就可以立刻返回,實現了HBase I/O的高效能。

3.3 讀流程

  1) Client訪問Zookeeper,查詢-ROOT-表,獲取.META.表資訊;

  2) 從.META.表查詢,獲取存放目標資料的Region資訊,從而找到對應的RegionServer;

  3) 通過RegionServer獲取需要查詢的資料;

  4) RegionServer的記憶體分為MemStore和BlockCache兩部分,MemStore主要用於寫資料,BlockCache主要用於讀資料。讀請求先到MemStore中查資料,查不到就到BlockCache中查,再查不到就會到StoreFile上讀,並把讀的結果放入BlockCache。

  定址過程:client—>Zookeeper—>ROOT表—>.META.表—>RegionServer—>Region—>client

4. HBASE命令

4.1namespace概述

  在HBase中,namespace名稱空間指對一組表的邏輯分組,類似RDBMS中的database,方便對錶在業務上劃分。Apache HBase從0.98.0,0.95.2兩個版本開始支援namespace級別的授權操作,HBase全域性管理員可以建立、修改和回收namespace的授權。

  HBase系統預設定義了兩個預設的namespace:

  • hbase:系統內建表,包括namespace和meta表
  • default:使用者建表時未指定namespace的表都建立在此  

4.2 命令的進退

1、hbase提供了一個shell的終端給使用者互動

hbase shell

2、如果退出執行quit命令

4.3基本操作命令

名稱 命令表示式
檢視hbase狀態 status
建立namespace create_namespace '名稱空間名稱'
刪除namespace drop_namespace '名稱空間名稱'
檢視namespace describe_namespace '名稱空間名稱'
列出所有namespace list_namespace
在namespace下建立表 create '名稱空間名稱:表名', '列族名1'
檢視namespace下的表 list_namespace_tables '名稱空間名稱'
建立表,預設名稱空間為default create '表名','列族名1','列族名2','列族名N'
檢視所有表 list
描述表 describe '表名'
判斷表存在 exists '表名'
判斷是否禁用啟用表

is_enabled '表名'
is_disabled '表名'

新增記錄 put '表名','rowkey','列族:列','值'
檢視記錄rowkey下的所有資料 get '表名','rowkey'
檢視所有記錄 scan '表名'
查看錶中的記錄總數 count '表名'
獲取某個列族 get '表名','rowkey','列族:列'
獲取某個列族的某個列 get '表名','rowkey','列族:列'
計算表的行數量 count '表名'
刪除記錄 delete '表名','行名','列族:列'
刪除整行 deleteall '表名','rowkey'
刪除一張表

先要遮蔽該表,才能對該表進行刪除
第一步 disable '表名',第二步 drop '表名'

清空表 truncate '表名'
檢視某個表某個列中所有資料 scan '表名',{COLUMNS=>'列族名:列名'}
更新記錄 就是重新一遍,進行覆蓋,hbase沒有修改,都是追加

具體例項:

1、檢視HBase執行狀態 status

2、建立表create <table>,{NAME => <family>, VERSIONS => <VERSIONS>}

建立一個User表,並且有一個info列族

3、檢視所有表 list

4、描述表詳情 describe 'User'

5、判斷表是否存在 exists 'User'

6、啟用或禁用表 is_disabled 'User' is_enabled 'User'

7、新增記錄,即插入資料,語法:put <table>,<rowkey>,<family:column>,<value>

8、根據rowKey查詢某個記錄,語法:get <table>,<rowkey>,[<family:column>, ...]

9、查詢所有記錄,語法:scan <table>,{COLUMNS => [family:column, ...], LIMIT => num}

掃描所有記錄

掃描前2條

範圍查詢

另外,還可以新增TIMERANGE和FILTER等高階功能,STARTROW、ENDROW必須大寫,否則報錯,查詢結果不包含等於ENDROW的結果集。

10、統計表記錄數,語法:count <table>, {INTERVAL => intervalNum,CACHE => cacheNum}

INTERVAL設定多少行顯示一次及對應的rowkey,預設1000;CACHE每次去取的快取區大小,預設是10,調整該引數可提高查詢速度。

11、刪除

刪除列

刪除整行

刪除表中所有資料

12、禁用或啟用表

禁用表

啟用表

12、刪除表

刪除前,必須先disable

4.4 批量命令

4.4.1 bulkload

bulkload為hbase的批量插入命令,應用於大資料量的插入,沒有效能問題

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles \ 
      -Dhbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily=1024 \
      hdfs:///hfile_path \
      hbase_namespace:table_name

4.4.2 bulkload應用

業務場景:Hive離線計算好的資料,需要同步到HBase供線上業務查詢,思路是用HBase自帶的ImportTsv工具。

Hive跑批:

  建表語句,要用文字格式,即Tsv格式,分割符可以自己定義:

CREATE TABLE IF NOT EXISTS tableA(
    rowkey STRING,
    ...
)
PARTITIONED BY (dt STRING)  -- format: 2020-07-28
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;

  跑批語句,注意設定不要compress,否則ImportTsv工具無法識別

SET hive.exec.compress.output=false;
INSERT OVERWRITE TABLE tableA
PARTITION( tx_date = \"$CALC_DATE\" )
SELECT ..

生成中間的HFile

hbase --config config_dir org.apache.hadoop.hbase.mapreduce.ImportTsv \
    -Dmapreduce.job.queuename=queue \
    -Dimporttsv.bulk.output=hdfs:///hfile_path \
    -Dimporttsv.columns="HBASE_ROW_KEY,column_family:column_name.." \
    hbase_namespace:table_name \
    hdfs://hive_table_dir

說明:config_dir是hbase的配置目錄,裡面包含hbase-site.xml,這個步驟ImportTsv會去讀取hive_table_dir中的檔案,並分析hbase table的region分佈,生成對應region的hfile,放到hfile_path中

bulkload

hbase --config config_dir org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles \
    hdfs:///hfile_path \
    hbase_namespace:table_name

說明:

  • Hive表必須是帶分隔符的文字格式,而且不能壓縮(比如啟用了mapreduce的output snappy壓縮也不行)
  • ImportTsv可以直接一條條插入hbase,這時mapper解析一條,就插入一條,沒有reduce階段;相比bulkload,大批量資料效能不好
  • bulkload的優點是快,生成的hfile直接註冊到region server,資料對應用立即可見,沒有wal log,沒有flush;  

總結

【參考資料】

https://www.cnblogs.com/cenyuhai/p/3708135.html

https://blog.csdn.net/liutong123987/article/details/79377327

https://www.cnblogs.com/Richardzhu/p/3435568.html單獨啟動secondarynamenode,輔助namenode的元資料合併

https://blog.csdn.net/maligebazi/article/details/79952459hbase 命令詳解之namespace與table

https://segmentfault.com/a/1190000011616473?utm_source=tag-newestHive 資料匯入 HBase