Hbase簡介


1 HBase的特點

海量存儲、列式存儲、極易擴展、高並發、稀疏數據、准實時查詢(彌補MapReduce的離線延時)

2 邏輯結構和物理結構

2.1 邏輯結構


HBase表由行和列組成,每個行由行鍵(row key)來標識,列划分為若干列族,一個列族中可以包含任意多個列,同一個列族里面的數據存儲在一個文件中。當這個文件達到一定大小后,會進行分裂形成多個region。當一個行鍵在不同的列族中都有相應的列值的話,不同列族中的文件都會存儲這個行鍵的值。也就是說,一行可能包含多個列族,一個列族有多個列,對某一行而言,某列族文件中只存儲了這一行鍵在列族中有值的那些列(列族可能有上百個列),沒有不會存儲(不存null)。

  • RowKey
    與 nosql 數據庫們一樣,RowKey 是用來檢索記錄的主鍵。訪問 HBASE table 中的行,只有三種方式:
    1.通過單個 RowKey 訪問
    2.通過 RowKey 的 range(正則)
    3.全表掃描
    RowKey 行鍵 (RowKey)可以是任意字符串(最大長度是 64KB,實際應用中長度一般為 10-100bytes),在 HBASE 內部,RowKey 保存為字節數組。存儲時,數據按照 RowKey 的字典序(byte order)排序存儲。設計 RowKey 時,要充分排序存儲這個特性,將經常一起讀取的行存儲放到一起。(位置相關性)
  • Column Family
    列族:HBASE 表中的每個列,都歸屬於某個列族。列族是表的 schema 的一部分(而列不是),必須在使用表之前定義。列名都以列族作為前綴。例如 courses:history,courses:math都屬於 courses 這個列族。
  • Cell
    {rowkey, column Family:column, version} 唯一確定的單元。cell 中的數據是沒有類型的,全部是字節碼形式存貯。 關鍵字:無類型、字節碼
  • Time Stamp
    每個 cell 都保存着同一份數據的多個版本。版本通過時間戳來索引。時間戳的類型是 64 位整型。時間戳可以由 HBASE(在數據寫入時自動 )賦值,此時時間戳是精確到毫秒 的當前系統時間。時間戳也可以由客戶顯式賦值。如果應用程序要避免數據版本沖突,就必須自己生成具有唯一性的時間戳。每個 cell 中,不同版本的數據按照時間倒序排序,即最新的數據排在最前面。 為了避免數據存在過多版本造成的的管理 (包括存貯和索引)負擔,HBASE 提供 了兩種數據版本回收方式。一是保存數據的最后 n 個版本,二是保存最近一段 時間內的版本(比如最近七天)。用戶可以針對每個列族進行設置。在HBase中,timestamp是一個很重要的概念。它記錄着往HBase進行增刪改操作的時間(系統自動賦值),它的值越大,說明是這個操作就越新,通常我們從HBase得到的只是那個最新操作的結果,但是之前的操作(時間戳小的)會保留直到達到一定的版本數或者設定時間。例如:
#timestamp1<timestamp2<timestamp3
put 'student','1002','info:name','shane'#step1,timestamp1=1585836527749
put 'student','1002','info:name','shane'#step2,timestamp2=1585838153208
#那么get 'student','1002','info:name'只會得到最新的timestamp2=1585838153208的數據,即value=shane
#step1的數據在進行step2后並不會被立即刪除,通過scan 'student',{RAW=>TRUE,VERSIONS=>3}可以查看同一個cell的最近的三個版本
delete 'student','1002','info:name'#step3,timestamp3=1585838197596
put 'student','1002','info:name','shane',1585838166666#step4,指定timestamp4=1585838166666
#timestamp<timestamp3,timestamp3是最新的且是delete操作,所以在scan 'student'時並不會得到1002的info:name的信息。
#但是通過scan 'student',{RAW=>TRUE,VERSIONS=>5}可以看到之前插入的信息
123456789

  • 命名空間
    命名空間的結構:
  1. Table:表,所有的表都是命名空間的成員,即表必屬於某個命名空間,如果沒有指定,則在 default 默認的命名空間中。

  2. RegionServer group:一個命名空間包含了默認的 RegionServer Group。

  3. Permission:權限,命名空間能夠讓我們來定義訪問控制列表 ACL(Access Control List)。例如,創建表,讀取表,刪除,更新等等操作。

  4. Quota:限額,可以強制一個命名空間可包含的 region 的數量。

2.2 物理結構


當在t4時間put(插入)row_key1的phone數據時,原來t3的並不會馬上被覆蓋。當查詢row_key1的phone時會返回時間戳最大的t4那一個數據(最新的)。

3 系統架構


Hbase 是由 Client、Zookeeper、Master、HRegionServer、HDFS 等幾個組件組成,HBase依賴於ZooKeeper和HDFS。

  • Zookeeper :HBase 通過 Zookeeper 來做 master 的高可用(通過 Zoopkeeper 來保證集群中只有 1 個 master 在運行,如果 master 異常,會通過競爭機制產生新的 master 提供服務。)、RegionServer 的監控(通過 Zoopkeeper 來監控 RegionServer 的狀態,當 RegionSevrer 有異常的時候,通過回調的形式通知 Master RegionServer 上下線的信息)、元數據的入口以及集群配置的維護等工作。(DML的請求通過ZK分發到HRegionServer不通過HMaster,HMaster是處理DDL的請求。HMaster宕機不會影響客戶端的讀寫請求;但是取法進行create 'stu4','info'的DDL操作。當原有的Meta元數據信息改變時也無法維護。)

  • Hmaster監控 RegionServer為 RegionServer 分配 Region(維護整個集群的負載均衡,在空閑時間進行數據的負載均衡 ) ,維護集群的元數據信息處理 region 的分配或轉移(發現失效的 Region,並將失效的 Region 分配到正常的 RegionServer 上 ;當 RegionSever 失效的時候,協調對應 Hlog 的拆分)

  • HregionServer:HregionServer 直接對接用戶的讀寫請求,是真正的“干活”的節點。它的功能概括如下: 管理 master 為其分配的 Region處理來自客戶端的讀寫請求負責和底層 HDFS 的交互(存儲數據到 HDFS),負責 Region 變大以后的拆分負責 Storefile 的合並工作刷新緩存到HDFS維護Hlog

  • HDFS :為 Hbase 提供最終的底層數據存儲服務,同時為HBase 提供高可用(Hlog 存儲在HDFS)的支持,具體功能概括如下:提供元數據和表數據的底層分布式存儲服務保證的高可靠和高可用性 (數據多副本)

  • MemStore:內存緩存,達到一定緩存大小或者時間節點觸發一次 flush,文件系統中生成新的 HFile,每次 Flush 的最小單位是 Region。每個 Column family 維護一個 MemStore。

  • Write-Ahead logs(WAL,Hlog)用來容災。當對 HBase 寫數據的時候,數據會在內存MemStore中保留一段時間,MemStore達到一定的數據量(時間以及數據量閾值可以設定),數據再寫進磁盤。但把數據保存在內存中可能有更高的概率引起數據丟失,為了解決這個問題,數據會先寫在一個叫做 Write-Ahead logfile 的文件中,然后再寫入內存中,所以在系統出現故障的時候,數據可以通過這個日志文件重建。

  • Region:Hbase表的分片,HBase 表會根據 RowKey 值被切分成不同的 region 存儲在 RegionServer中,在一個 RegionServer 中可以有多個不同的 region。同一個行鍵的 Region 不會被拆分到多個 Region 服務器上。 一個HBase表被划分成多個Region,開始只有一個Region,后台不斷分裂。

    一個表中包含多個列族,一個列族一個文件存儲,region的切分是橫向切分的,那么包含了多個列族。

  • Meta表:描述HBase表的表,元數據表。有了 Region 標識符,就可以唯一標識每個 Region。為了定位每個 Region 所在的位置,可以構建一張映射表。映射表的每個條目包含兩項內容,一項是 Region 標識符,另一項是 Region 服務器標識。這個條目就表示 Region 和 Region 服務器之間的對應關系,從而就可以使用戶知道某個 Region 存儲在哪個 Region 服務器中。這個映射表包含了關於 Region 的元數據,因此也被稱為“元數據表”,又名“Meta表”。使用 scan 命令可查看 Meta 表的結構,如圖所示

    Meta 表中的每一行記錄了一個 Region 的信息。RowKey 包含表名、起始行鍵和時間戳信息,中間用逗號隔開,第一個 Region 的起始行鍵為空。時間戳之后用.隔開的為分區名稱的編碼字符串,該信息是由前面的表名、起始行鍵和時間戳進行字符串編碼后形成的。
    Meta 表里有一個列族 info。info 包含了三個列,分別為 Regioninfo、Server 和 Serverstartcode。Regionlnfo中記錄了 Region 的詳細信息,包括行鍵范圍 StartKey 和 EndKey、列族列表和屬性。
    Server 記錄了管理該 Region 的 Region 服務器的地址,如 localhost:16201。Serverstartcode 記錄了 Region 服務器開始托管該 Region 的時間。
    當用戶表特別大時,用戶表的 Region 也會非常多。Meta 表存儲了這些 Region 信息,也變得非常大。Meta 表也需要划分成多個 Region,每個 Meta 分區記錄一部分用戶表和分區管理的情況。(有了meta表,就可以得到region和HRegionServer的對應關系,可以進行Region定位:客戶端通過 ZooKeeper 獲取 Meta 表(分區表)存儲的地址,首先在對應的 Regionserver上獲取 Meta 表的信息(meta表存在Regionserver上),得到所需的Region對應的Regionserver的信息,然后從Region 服務器上找到所需的數據)

  • Store :HFile 存儲在 Store 中,一個 Store 對應 HBase 表中的一個列族。

  • HFile :這是在磁盤上保存原始數據的實際的物理文件,是實際的存儲文件。StoreFile 是以 Hfile的形式存儲在 HDFS 的。

  • Block Cache:見4.2

4 實現原理

4.1 寫數據流程

4.2 讀數據流程


1)Client 先訪問 zookeeper,從 meta 表讀取 region 的位置,然后讀取 meta 表中的數據。meta中又存儲了用戶表的 region 信息;
2)根據 namespace、表名和 rowkey 在 meta 表中找到對應的 region 信息;
3)找到這個 region 對應的 regionserver;
4)查找對應的 region;
5)先從 MemStore 找數據,如果沒有,再到 BlockCache 里面讀;
6)BlockCache 還沒有,再到 StoreFile 上讀(為了讀取的效率);
7)如果是從 StoreFile 里面讀取的數據,不是直接返回給客戶端,而是先寫入 BlockCache,再返回給客戶端。

Block Cache:緩存磁盤中的數據(磁盤慢)(僅僅放內存中的數據,不放內存中的數據)。當讀取stu3,1001,info:name的時候,如果Block Cache沒有,同時讀取內存和磁盤中的數據(將磁盤的數據放到block Cache,然后將merge(內存讀取,磁盤讀取)的結果返回。下圖中,zhangsan在磁盤中(手動刷入),時間戳t1;lisi在內存中(默認等到一定大小或時間),時間戳t2,且t1>t2。如果是讀取內存而不讀取磁盤,得到的應該是lisi。而HBase通過上述的方式返回時間戳最大的那一條數據,為zhangsan。(讀比寫慢)

4.3 數據 flush 過程

(上圖中,一個Region中有兩個store(兩個列族),在flush的時候會往hdfs的不同datanode中寫入。每一個列族中的列具有高的‘查詢同時性’,不同列族中的列再一次查詢中不同時查詢,所以可以存放在hdfs的不同DataNode節點上)
1)當 MemStore 數據達到閾值(默認是 128M,老版本是 64M),將數據刷到硬盤,將內存中的數據刪除,同時刪除 HLog 中的歷史數據;
2)並將數據存儲到 HDFS 中;
3)在 HLog 中做標記點。

4.4 數據合並拆分過程

1)當數據塊達到 4 塊,Hmaster 觸發合並操作,Region 將數據塊加載到本地,進行合並;
2)當合並的數據超過 256M,進行拆分,將拆分后的 Region 分配給不同的 HregionServer管理(一個表中的region就會被不同的HRegionServer管理,分布式存儲,高可用容災);
3)當 HregionServer 宕機后,將 HregionServer 上的 hlog 拆分,然后分配給不同的 HregionServer加載,修改.META.;
4)注意:HLog 會同步到 HDFS。


memstore每次刷寫都會生成一個新的HFile,且同一個數據({namespace:table,rowkey,column family:column}相同)的不同版本(timestamp)和不同類型的(put/delete)有可能會分布在不同的HFile中,所以查詢時需要遍歷所有的HFile。為了減少HFile的個數,以及清理掉過期和最后版本是(delete)的數據,會進行StoreFile Compaction合。StoreFile Compaction分為Minor CompactionMajor Compaction,前者Minor將鄰近的若干個HFile合並成一個較大的HFile,但不會清理過期和刪除的數據;后者Major將一個Store下的所有HFile合並成一個大的HFile,並且會清理掉過期和刪除的數據。

【附錄】
META是啥?
META是一種思想概念,一種抽象思維,用來描述數據的數據,比如有一張學生表,記錄着學生的基本信息,我們通過表可以獲取學生信息(數據),但是有時候也要得到表本身的信息數據(比如表結構信息:字段名稱,字段數據類型,長度等信息),對於這種基礎信息的描述,就會使用META的概念,使用META元數據來描述表本身。放到HTML中也是一樣的,HTML用來描述網頁信息,但是HTML自己也有一些信息(比如網頁標題,網頁描述,搜索關鍵字),這些信息也就稱之為HTML META信息,並且HTML也定義了專門的META標簽。

列族是如何進行動態擴展的?
一個列族中的所有列是保存在同一個文件的(多了會分region),當有新的列族時,在一個新的文件中存儲新的列族。某keyrow如果在這個列族中有相應的列的信息,則新文件中存儲rowkey和列信息,沒有的話不存儲(而不是null值)。

HBase的檢索支持3種方式:
(1) 通過單個Rowkey訪問,即按照某個Rowkey鍵值進行get操作,這樣獲取唯一一條記錄;
(2) 通過Rowkey的range進行scan,即通過設置startRowKey和endRowKey,在這個范圍內進行掃描。這樣可以按指定的條件獲取一批記錄;
(3) 全表掃描,即直接掃描整張表中所有行記錄。

  • 注:由於row key默認按照字典順序升序排序,按照row key檢索的效率很高

為什么不建議用多個列族?

一個列族就對應一個store,當一個表中有多個列族時,這個表拆分后的一個Region中就會有多個Store文件。如果在一些Region中有大量的數據(存着那個列族中的列的數據),而剩下的Region僅有少量的數據,那么就會生成多個的小文件。當查詢rowkey的數據時,會找到某個Region,然后在那個Region中需要掃描所有的Store中的文件(有多少個列族就有多少個Store)造成效率低。當使用多個列族時,需要每個列族中的列的數據的量差不多。


免責聲明!

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



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