1. 程式人生 > >HBase簡單介紹

HBase簡單介紹

概述

NoSQL

HBase是一種”NoSQL”資料庫。”NoSQL”是一個通用詞表示資料庫不是RDBMS(Relation Database Management System,關係型資料庫管理系統),後者支援SQL作為主要訪問手段。有許多種NoSQL資料庫:BerkeleyDB是本地NoSQL資料庫例子,而HBase是大型分散式資料庫。技術上來說,HBase更像是”資料儲存(Data Store)”多於”資料庫(Data Base)”。因為缺少很多RDBMS特性,如列型別,第二索引,觸發器,高階查詢語言等。
然而,HBase有許多特徵同時支援線性化和模組化擴充。HBase叢集通過增加RegionServers進行擴充。它可以放在普通的伺服器中。例如,如果叢集從10個擴充到20個RegionServer,儲存空間和處理容量都同時翻倍。RDBMS也能很好擴充,但僅對一個點,特別是對一個單獨資料庫伺服器的大小,同時,為了更好的效能,需要特殊的硬體和儲存裝置。HBase特性:

  • 強一致性讀寫:HBase不是”最終一致性(eventually consistent)”資料儲存。這讓它很適合高速計數聚合類任務。
  • 自動分片(Automatic sharding):HBase表通過region分佈在叢集中。資料增長時,region會自動分割並重新分佈。
  • RegionServer自動故障轉移
  • Hadoop/HDFS整合:HBase支援本機外HDFS作為它的分散式檔案系統。
  • MapReduce:HBase通過MapReduce支援大併發處理,HBase可以同時做源和目標。
  • Java客戶端API:HBase支援易於使用的Java API進行程式設計訪問。
  • Thrift/REST API:HBase也支援Thrift和REST作為非Java前端。
  • Block Cache和Bloom Filters:對於大容量查詢優化,HBase支援Block Cache和Bloom Filters。
  • 運維管理:HBase提供內建網頁用於運維視角和JMX度量。

什麼時候用HBase

HBase不適合所有問題。
首先,確信有足夠多資料,如果有上億或上千億行資料,HBase是很好的備選。如果只有上千或上百萬行,則用傳統的RDBMS可能是更好的選擇。因為所有資料可以在一兩個節點儲存,叢集其他節點可能閒置。
其次,確信可以不依賴所有RDBMS的額外特性(e.g.,列資料型別,第二索引,事務,高階查詢語言等。)一個建立在RDBMS上應用,如不能僅通過改變一個JDBC驅動移植到HBase。相對於移植,需考慮從RDBMS到HBase是一次完全的重新設計。
第三,確信你有足夠硬體。甚至HDFS在小於5個數據節點時,幹不好什麼事情(根據如HDFS塊複製具有預設值3),還要加上一個NameNode。
HBase能在單獨的筆記本上執行良好。但這應僅當成開發配置。

HBase和Hadoop/HDFS的區別

HDFS是分散式檔案系統,適合儲存大檔案。官方宣稱它並非普通用途檔案系統,不提供檔案的個別記錄的快速查詢。另一方面,HBase基於HDFS且提供大表的記錄快速查詢(和更新)。這有時可能引起概念混亂。HBase內部將資料放到索引好的”儲存檔案(StoreFiles)”,以便高速查詢。儲存檔案位於HDFS中。

Schema的設計

在HBase中,值是作為一個單元(Cell)儲存在系統中的,要定位一個單元,需要行,列名和時間戳。無論是列族,屬性和行鍵都會在資料中重複上億次。

  • 行鍵
    • 讓行鍵儘量短,但是需要保證他們依然對獲取資料有用(e.g. Get vs. Scan)。對訪問資料無用的短鍵,並不比帶有get/scan屬性的長鍵更好。行鍵的設計需要權衡。
    • 行鍵在列族範圍內。所以同樣的行鍵可以在同一個表的每個列族中存在而不會衝突。
    • 行鍵不能改變。唯一可以“改變”的方式是刪除然後再插入。這是一個網上常問問題,所以要注意開始就要讓行鍵正確(且/或在插入很多資料之前)。
  • 列族
    在HBase中列族是一些列的集合。一個列族所有列成員是有著相同的字首。比如,列courses:history和courses:math都是列族courses的成員,冒號(:)是列族的分隔符,用來區分字首和列名。column字首必須是可列印的字元,剩下的部分(稱為qualify),可以由任意位元組陣列組成。列族必須在表建立的時候宣告。column就不需要了,隨時可以新建。
    在物理上,一個的列族成員在檔案系統上都是儲存在一起。因為儲存優化都是針對列族級別的,這就意味著,一個column family的所有成員的是用相同的方式訪問的。
    • 儘量使列族名小,最好一個字元。(如”d”表示data/default)。
    • 儘管詳細屬性名(如,”myVeryImportantAttribute”)易讀,在HBase中最好使用短屬性名(e.g., “via”)儲存。
    • 列族可以設定TTL(Time To Live,存活時間)秒數,HBase在超時後將自動刪除資料。影響全部行的全部版本-甚至當前版本。HBase裡面TTL時間時區是UTC。
  • Cell
    A {row, column, version}元組就是HBase中的一個Cell。Cell的內容是不可分割的位元組陣列。
  • 位元組模式儲存
  • 倒序時間戳
    一個數據庫處理的通常問題是找到最近版本的值。採用倒序時間戳作為鍵的一部分可以對此特定情況有很大幫助。也在Tom White的Hadoop書籍的HBase章節能找到:The Definitive Guide(O’Reilly),該技術包含追加(Long.MAX_VALUE-timestamp)到key的後面,如[key][reverse_timestamp]
    表內[key]的最近的值可以用[key]進行Scan找到並獲取第一個記錄。由於HBase行鍵是排序的,該鍵排在任何比它老的行鍵的前面,所以必然是第一個。

資料模型

簡單來說,應用程式是以表的方式在HBase儲存資料的。表是由行和列構成的,所有的列是從屬於某一個列族的。行和列的交叉點稱之為cell,cell是版本化的。cell的內容是不可分割的位元組陣列。
表的行鍵也是一段位元組陣列,所以任何東西都可以儲存進去,不論是字串或者數字。HBase的表是按key排序的,排序方式只針對位元組的。所有的表都必須要有主鍵-key。

概念檢視

下面是根據BigTable論文稍加修改的例子。有一個名為webtable的表,包含兩個列族:contents和anchor。在這個例子裡面,anchor有兩個列(anchor:cssnsi.com, anchor:my.look.ca),contents僅有一列(contents:html)
列名
一個列名是由它的列族字首和修飾符(qualifier)連線而成。例如列contents:html是列族contents加冒號(:)加修飾符html組成的。
Table webtable

Row Key Time Stamp ColumnFamily contents ColumnFamily anchor
“com.cnn.www” t9 anchor:cnnsi.com = “CNN”
“com.cnn.www” t8 anchor:my.look.ca = “CNN.com”
“com.cnn.www” t6 contents:html = "<html>..."
“com.cnn.www” t5 contents:html = "<html>..."
“com.cnn.www” t3 contents:html = "<html>..."

物理檢視

儘管在概念視圖裡,表可以被看成是一個稀疏的行的集合。但在物理上,它的是區分列族儲存的。新的columns可以不經過宣告直接加入一個列族。
Table ColumnFamily anchor

Row Key Time Stamp Column Family anchor
“com.cnn.www” t9 anchor:cnnsi.com = “CNN”
“com.cnn.www” t8 anchor:my.look.ca = “CNN.com”

Table ColumnFamily contents

Row Key Time Stamp ColumnFamily “contents:”
“com.cnn.www” t6 contents:html = "<html>..."
“com.cnn.www” t5 contents:html = "<html>..."
“com.cnn.www” t3 contents:html = "<html>..."

值得注意的是在上面的概念檢視中空白cell在物理上是不儲存的,因為根本沒有必要儲存。因此若一個請求為要獲取t8時間的contents:html,他的結果就是空。相似的,若請求為獲取t9時間的anchor:my.look.ca,結果也是空。但是,如果不指明時間,將會返回最新時間的行,每個最新的都會返回。例如,如果請求為獲取行鍵為”com.cnn.www”,沒有指明時間戳的話,活動的結果是t6下的contents:html,t9下的anchor:cnnsi.com和t8下anchor:my.look.ca。
For more information about the internals of how HBase stores data, see Section 9.7, “Regions”.

資料模型操作

四個主要的資料模型操作是Get、Put、Scan和Delete,通過HTable例項進行操作。

  • Put
    要想覆蓋一個現有的值,就意味著你的row-key,column和版本必須完全相等。
  • Delete
    通過Table.delete,從一個表中刪除一行。
    HBase不會修改資料,所以刪除時通過建立稱之為墓碑(tombstones)標記。這些墓碑以及被刪除的值在執行主緊縮是被清理。有三種不同型別的內部刪除標記:
    1、Delete: 刪除列的指定版本。
    2、Delete column: 刪除列的所有版本。
    3、Delete family: 刪除特定列族所有列
    當刪除一行,HBase內部對每個列族建立墓碑(非每個單獨列)。
    刪除操作的實現是建立一個墓碑標記。例如,我們想要刪除一個版本,或者預設是currentTimeMillis。就意味著“刪除比這個版本更早的所有版本”。HBase不會去改那些資料,資料不會立即從檔案中刪除。他使用刪除標記來遮蔽掉這些值。

版本

一個{row, column, version}元組是HBase中的一個單元(Cell)。但是有可能會有很多單元的行和列是相同的,可以使用版本來區分不同的單元。
row key和column key是用位元組陣列表示的,version則是用一個長整型表示。這個long的值使用java.util.Date.getTime()或者System.currentTimeMillis()產生的。這就意味著他的含義是“當前時間和1970-01-01 UTC的時間差,單位毫秒。”
在HBase中,版本是按倒序排列的,因此當讀取這個檔案的時候,最先找到的是最近的版本。
有些人不是很理解HBase單元(cell)的意思。一個常見的問題是:
如果有多個包含版本寫操作同時發起,HBase會儲存全部還是會保持最新的一個?答:儲存全部,但是如果不指定版本獲取只會獲取到最新的那個。
可以發起包含版本的寫操作,但是他們的版本順序和操作順序相反是否可以?答:可以