HBase學習的第五天--HBase進階結尾和phoenix開頭

shmil發表於2024-08-17

HBase進階下

一、HBase的讀寫流程

1.1 HBase讀流程

Hbase讀取資料的流程:
1)是由客戶端發起讀取資料的請求,首先會與zookeeper建立連線
2)從zookeeper中獲取一個hbase:meta表位置資訊,被哪一個regionserver所管理著
     hbase:meta表:hbase的後設資料表,在這個表中儲存了自定義表相關的後設資料,包括表名,表有哪些列簇,表有哪些region,每個region儲存的位置,每個region被哪個regionserver所管理,這個表也是儲存在某一個region上的,並且這個meta表只會被一個regionserver所管理。這個表的位置資訊只有zookeeper知道。
3)連線這個meta表對應的regionserver,從meta表中獲取當前你要讀取的這個表對應的regionsever是誰。
     當一個表多個region怎麼辦呢?
     如果我們獲取資料是以get的方式,只會返回一個regionserver
     如果我們獲取資料是以scan的方式,會將所有的region對應的regionserver的地址全部返回。
4)連線要讀取表的對應的regionserver,從regionserver上的開始讀取資料:
       讀取順序:memstore-->blockcache-->storefile-->Hfile中
       			storefile和Hfile對應的是一個檔案
       注意:如果是scan操作,就不僅僅去blockcache了,而是所有都會去找。

1.2 HBase寫流程

--------------------------1-4步是客戶端寫入資料的流程-----------------

Hbase的寫入資料流程:
1)由客戶端發起寫資料請求,首先會與zookeeper建立連線
2)從zookeeper中獲取hbase:meta表被哪一個regionserver所管理
3)連線hbase:meta表中獲取對應的regionserver地址 (從meta表中獲取當前要寫入資料的表對應的region所管理的regionserver) 只會返回一個regionserver地址
4)與要寫入資料的regionserver建立連線,然後開始寫入資料,將資料首先會寫入到HLog,然後將資料寫入到對應store模組中的memstore中
(可能會寫多個),當這兩個地方都寫入完成之後,表示資料寫入完成。


-------------------------後面的步驟是伺服器內部的操作-----------------
非同步操作
5)隨著客戶端不斷地寫入資料,memstore中的資料會越來多,當記憶體中的資料達到閾值(128M/1h)的時候,放入到blockchache中,生成新的memstore接收使用者過來的資料,然後當blockcache的大小達到一定閾值(0.85)的時候,開始觸發flush機制,將資料最終重新整理到HDFS中形成小的Hfile檔案。

6)隨著不斷地重新整理,storefile不斷地在HDFS上生成小HFIle檔案,當小的HFile檔案達到閾值的時候(3個及3個以上),就會觸發Compaction機制,將小的HFile合併成一個大的HFile.

7)隨著不斷地合併,大的HFile檔案會越來越大,當達到一定閾值(2.0版本之後最終10G)的時候,會觸發分裂機制(split),將大的HFile檔案進行一分為二,同時管理這個大的HFile的region也會被一分為二,形成兩個新的region和兩個新的HFile檔案,一對一的進行管理,將原來舊的region和分裂之前大的HFile檔案慢慢地就會下線處理。

HBase寫流程的簡單概況

  • 開始使用者先往HLOG(主要起到恢復資料的作用,如果資料已經落地到磁碟上,WAL中的資料就會被刪除)中寫日誌

  • memstore相當於記憶體,當其達到128M(閾值)或者一個小時,會將資料放到佇列中,這個佇列所在的容器叫做blockcache

  • 在blockcache達到85%或者一個小時的時候,達到閾值,開始往外溢寫,該溢寫檔案在hbase中叫做storefile,但是在HDFS中叫做Hfile

  • 在HDFS中隨著溢寫檔案越來越多會生成大的Hfile檔案,條件是三個或者三個以上的小檔案合併成一個大檔案

  • 當這個大檔案達到128M時,又開始進行分裂成小檔案,接著小檔案數量增多,又會合併成新的大檔案,此時這個大檔案的閾值則是10G

二、Region的分裂策略

region中儲存的是一張表的資料,當region中的資料條數過多的時候,會直接影響查詢效率。當region過大的時候,region會被拆分為兩個region,HMaster會將分裂的region分配到不同的regionserver上,這樣可以讓請求分散到不同的RegionServer上,已達到負載均衡 , 這也是HBase的一個優點 。

  • ConstantSizeRegionSplitPolicy

    0.94版本前,HBase region的預設切分策略

    當region中最大的store大小超過某個閾值(hbase.hregion.max.filesize=10G)之後就會觸發切分,一個region等分為2個region。

    但是在生產線上這種切分策略卻有相當大的弊端(切分策略對於大表和小表沒有明顯的區分):

    • 閾值(hbase.hregion.max.filesize)設定較大對大表比較友好,但是小表就有可能不會觸發分裂,極端情況下可能就1個,形成熱點,這對業務來說並不是什麼好事。
    • 如果設定較小則對小表友好,但一個大表就會在整個叢集產生大量的region,這對於叢集的管理、資源使用、failover來說都不是一件好事。
  • IncreasingToUpperBoundRegionSplitPolicy

    0.94版本~2.0版本預設切分策略

    ​ 總體看和ConstantSizeRegionSplitPolicy思路相同,一個region中最大的store大小大於設定閾值就會觸發切分。
    但是這個閾值並不像ConstantSizeRegionSplitPolicy是一個固定的值,而是會在一定條件下不斷調整,調整規則和region所屬表在當前regionserver上的region個數有關係.

    region split閾值的計算公式是:

    • 設regioncount:是region所屬表在當前regionserver上的region的個數

    • 閾值 = regioncount^3 * 128M * 2,當然閾值並不會無限增長,最大不超過MaxRegionFileSize(10G),當region中最大的store的大小達到該閾值的時候進行region split

    例如:

    • 第一次split閾值 = 1^3 * 256 = 256MB
    • 第二次split閾值 = 2^3 * 256 = 2048MB
    • 第三次split閾值 = 3^3 * 256 = 6912MB
    • 第四次split閾值 = 4^3 * 256 = 16384MB > 10GB,因此取較小的值10GB
    • 後面每次split的size都是10GB了

    特點

    • 相比ConstantSizeRegionSplitPolicy,可以自適應大表、小表;
    • 在叢集規模比較大的情況下,對大表的表現比較優秀
    • 對小表不友好,小表可能產生大量的小region,分散在各regionserver上
    • 小表達不到多次切分條件,導致每個split都很小,所以分散在各個regionServer上
  • SteppingSplitPolicy

    2.0版本預設切分策略

    ​ 相比 IncreasingToUpperBoundRegionSplitPolicy 簡單了一些
    ​ region切分的閾值依然和待分裂region所屬表在當前regionserver上的region個數有關係

    • 如果region個數等於1,切分閾值為flush size 128M
    • 否則為MaxRegionFileSize。

    這種切分策略對於大叢集中的大表、小表會比 IncreasingToUpperBoundRegionSplitPolicy 更加友好,小表不會再產生大量的小region,而是適可而止。

  • KeyPrefixRegionSplitPolicy

    根據rowKey的字首對資料進行分割槽,這裡是指定rowKey的前多少位作為字首,比如rowKey都是16位的,指定前5位是字首,那麼前5位相同的rowKey在相同的region中。

  • DelimitedKeyPrefixRegionSplitPolicy

    保證相同字首的資料在同一個region中,例如rowKey的格式為:userid_eventtype_eventid,指定的delimiter為 _ ,則split的的時候會確保userid相同的資料在同一個region中。
    按照分隔符進行切分,而KeyPrefixRegionSplitPolicy是按照指定位數切分。

  • BusyRegionSplitPolicy

    按照一定的策略判斷Region是不是Busy狀態,如果是即進行切分

    如果你的系統常常會出現熱點Region,而你對效能有很高的追求,那麼這種策略可能會比較適合你。它會透過拆分熱點Region來緩解熱點Region的壓力,但是根據熱點來拆分Region也會帶來很多不確定性因素,因為你也不知道下一個被拆分的Region是哪個。

  • DisabledRegionSplitPolicy

    不啟用自動拆分, 需要指定手動拆分

三、Compaction操作

注意:在合併的過程中,客戶端是不會進行任何操作的,即使用者是無法對HBase進行增刪改操作的

Minor Compaction:

  • 指選取一些小的、相鄰的StoreFile將他們合併成一個更大的StoreFile,在這個過程中不會處理已經Deleted或Expired的Cell。一次 Minor Compaction 的結果是更少並且更大的StoreFile。

Major Compaction:

  • 指將所有的StoreFile合併成一個StoreFile,這個過程會清理三類沒有意義的資料:被刪除的資料TTL過期資料版本號超過設定版本號的資料。另外,一般情況下,major compaction時間會持續比較長,整個過程會消耗大量系統資源,對上層業務有比較大的影響。因此線上業務都會將關閉自動觸發major compaction功能,改為手動在業務低峰期觸發。

參考文件:https://cloud.tencent.com/developer/article/1488439

同時,HBase是一個面向列儲存的資料庫(列簇機制),當表欄位非常多時,可以把其中一些欄位獨立出來放在一部分機器上,而另外一些欄位放到另一部分機器上,分散儲存,分雜湊查詢。

正由於這樣複雜的儲存結構和分散式的儲存方式,保證了HBase海量資料下的查詢效率。

五、HBase與Hive的整合

HBase與Hive的對比

HBase和Hive的資料最終都儲存在HDFS上,只不過是儲存形式不太一樣。

  • Hbase和Hive整合就要求兩者是同一個叢集

hive:

資料倉儲建模工具之一:Hive的本質其實就相當於將HDFS中已經儲存的檔案在Mysql中做了一個雙射關係,以方便使用HQL去管理查詢。

用於資料分析、清洗:Hive適用於離線的資料分析和清洗,延遲較高。

基於HDFS、MapReduce:Hive儲存的資料依舊在DataNode上,編寫的HQL語句終將是轉換為MapReduce程式碼執行。

HBase

  • HBase是一種nosql資料庫,它是基於Hadoop分散式檔案系統HDFS構建的分散式資料庫。
  • HBase是一種列式資料庫,它以列簇作為儲存單位儲存資料。

資料庫:是一種面向列族儲存的非關係型資料庫。

用於儲存結構化和非結構化的資料:適用於單表非關係型資料的儲存,不適合做關聯查詢,類似JOIN等操作。

基於HDFS:資料持久化儲存的體現形式是HFile,存放於DataNode中,被ResionServer以region的形式進行管理。

延遲較低,接入線上業務使用:面對大量的企業資料,HBase可以直線單表大量資料的儲存,同時提供了高效的資料訪問速度。

hive-site.xml中新增zookeeper的屬性

	<property>
        <name>hive.zookeeper.quorum</name>
        <value>master,node1,node2</value>
    </property>

    <property>
        <name>hive.zookeeper.client.port</name>
        <value>2181</value>
    </property>

HBase中已經儲存了某一張表,在Hive中建立一個外部表來關聯HBase中的這張表

建立外部表的欄位名要和hbase中的列名一致

前提是hbase中已經有表了

create external table students_hbase
(
id string,
name string,
age string,
gender string, 
clazz string
)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties ("hbase.columns.mapping" = "
:key,
info:name,
info:age,
info:gender,
info:clazz
")
tblproperties("hbase.table.name" = "default:students");

create external table score_hbase2
(
id string,
score_dan string
)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties ("hbase.columns.mapping" = "
:key,
info:subject_score
")
tblproperties("hbase.table.name" = "default:scores");

關聯後就可以使用Hive函式進行一些分析操作了

六、Phoenix

Hbase適合儲存大量的對關係運算要求低的NOSQL資料,受Hbase 設計上的限制不能直接使用原生的API執行在關聯式資料庫中普遍使用的條件判斷和聚合等操作。Hbase很優秀,一些團隊尋求在Hbase之上提供一種更面向普通開發人員的操作方式,Apache Phoenix即是。

Phoenix 基於Hbase給面向業務的開發人員提供了以標準SQL的方式對Hbase進行查詢操作,並支援標準SQL中大部分特性:條件運算,分組,分頁,等高階查詢語法。

1、Phoenix搭建

Phoenix 5.1.0 HBase 2.2.7 hadoop 3.1.1

1、關閉hbase叢集,在master中執行

stop-hbase.sh

2、上傳解壓配置環境變數

解壓

tar -xvf apache-phoenix-4.15.0-HBase-1.4-bin.tar.gz -C /usr/local/soft/

改名

mv apache-phoenix-4.15.0-HBase-1.4-bin phoenix-4.15.0

3、將phoenix-4.15.0-HBase-1.4-server.jar複製到所有節點的hbase lib目錄下

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar master:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node1:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node2:/usr/local/soft/hbase-1.4.6/lib/

4、啟動hbase , 在master中執行

start-hbase.sh

5、配置環境變數

vim /etc/profile

2、Phoenix使用

1、連線sqlline

sqlline.py master,node1,node2

# 出現
163/163 (100%) Done
Done
sqlline version 1.5.0
0: jdbc:phoenix:master,node1,node2> 


2、常用命令

phoneix使用語法注意事項

# 使用注意事項
	1、在phoneix內部建立表的時候,表名最後可以使用!table或者show tables命令檢視,並且以大寫的形式展示給我們,但是我們在使用sql語句查詢的時候既可以用大寫也可以用小寫。(列名和表名大小寫無所謂)
	
	2、直接在phoneix內部建立的表,在hbase中可以以大寫的方式檢視到,但是在hbase中建的表,在phoneix中看不到。
	
	3、如何在phoneix中使用hbase原本的資料表呢?
		檢視對映:檢視並不是真正意義上的表,而是在phoneix建立一個對映關係,以表的形式將hbase中原本資料對映過來,可以在基礎之上編寫sql語句進行分析,需要注意的是,我們在檢視上sql分析的時候,表名和列名需要加雙引號。刪除檢視不會影響原本hbase中的資料,檢視無法做修改,只能查詢,檢視在phoneix中被看作成一個只讀表。
		表對映:建表的語法來說與檢視對映相差一個單詞,其他的沒啥區別。使用上,表對映可以直接在phoneix中對錶資料進行增刪改查。將phoneix中表對映刪了,原來hbase中的表也對應刪除。
		
	4、對映查詢的時候,主鍵可以不用加雙引號,非主鍵的列必須加雙引號

在HBase中建立一張表,在phoenix中是看不到的

但是在phoenix中建立的表可以在HBase中看到

  • 注意:
    • 在phoenix對錶進行操作,儘管表名是大寫的,在實現對錶的操作時,表名也可以小寫
    • 但是在hbase中如果表名時大寫,操作表時表名就必須大寫
# 1、建立表

CREATE TABLE IF NOT EXISTS students_p1 (
 id VARCHAR NOT NULL PRIMARY KEY, 
 name VARCHAR,
 age BIGINT, 
 gender VARCHAR ,
 clazz VARCHAR
);

# 2、顯示所有表
 !table

# 3、插入資料
upsert into students_p1 values('1500101004','小虎',22,'男','理科一班');
upsert into students_p1 values('1500100005','宣谷芹',24,'男','理科六班');
upsert into students_p1 values('1500100006','羿彥昌',24,'女','理科三班');
upsert into students_p1 values('1500100007','zhangsan',24,'女','理科一班');


# 4、查詢資料,支援大部分sql語法,
select * from STUDENT ;
select * from STUDENT where age=24;
select gender ,count(*) from STUDENT group by gender;
select * from student order by gender;

# 5、刪除資料
delete from STUDENT where id='1500100004';


# 6、刪除表
drop table STUDENT;
 
 
# 7、退出命令列
!quit

更多語法參照官網
https://phoenix.apache.org/language/index.html#upsert_select

相關文章