HBase回顧
(一)HBase的曆史

HBase是一個分布式的、面向列的開源資料庫,該技術來源于 Fay Chang 所撰寫的Google論文“Bigtable:一個結構化資料的分布式存儲系統”。就像Bigtable利用了Google檔案系統(File System)所提供的分布式資料存儲一樣,HBase 在Hadoop之上提供了類似于Bigtable的能力。HBase是Apache的Hadoop項目的子項目。HBase不同于一般的關系資料庫,它是一個适合于非結構化資料存儲的資料庫。另一個不同的是HBase基于列的而不是基于行的模式。
Google三駕馬車:分布式檔案系統GFS、分布式計算架構MapReduce、分布式列式NoSQL資料庫BigTable; (2003~2006)
開源Hadoop三件套:分布式檔案系統HDFS、分布式計算架構MapReduce、分布式列式NoSQL資料庫HBase; (2006~2009)
HBase:高可靠、高性能、高擴充性的分布式存儲系統。可承載PB級的資料存儲,億次/每秒的讀寫請求。
(二)HBase應用場景
HBase應用的場景與行業非常的廣泛,主要側重于大資料量場景。
HBase與大資料量場景如此契合的原因有許多,首先,HBase存儲成本低,海量資料存儲的成本相對較低,所需機器也非常少。
其次,HBase擴充性非常好,随着資料量的增加,隻要簡單地擴機器即可,HBase單個表的通路可以橫向擴充到多個機器上進行通路。
此外,HBase是Schema Free,它不像關系資料庫一樣事先定義好表的結構,它隻需要建立表的時候,指定表和列名字就可以,列是動态生成的。
HBase有很好的容錯恢複能力,比方這麼多的分布式節點,單個節點當機之後,它可以快速地将計算的資源遷移到其他節點上繼續提供服務,做到使用者無感覺的自動恢複。
同時它還支援TTL與多版本特性,比如淘汰海量資料下的一些曆史資料,可以直接使用TTL操作。當遇到一個業務場景中單個列有多個版本,可以使用多版本的特性存儲多個版本的資料。
HBase查詢原理
(一)HBase資料模型
1.基本概念
Table:表名。
Rowkey:行唯一鍵,也叫主鍵Primary Key,字典序排序存儲。
Column Family:列族,同一列族的資料集中存儲,單個表可包含多列族,TTL、高效壓縮。
Column:列名。動态列,Schema Free,底層統一byte[ ]存儲。
Timestamp:每個列的時間戳。多版本,按照時間戳最新原則排序。
2.常見查詢
主鍵查詢:Rowkey Get
範圍查詢:Rowkey Scan
條件過濾:Rowkey Get/Scan+Filter
多語言通路:Java/Python/C++/Go/PHP/node.js等。
3.範例
上方為一個普通的結構化表,ID也就是主鍵Rowkey,用數字表示,按順序存儲的,即使1001在1002和1003之後寫入,寫入後仍會按照數字順序排在最前面。
Info和Date是兩個不同列族(Cloumn Family)的名字,兩個列族裡包含許多列。Value表示每個列對應的值,比如小王是姓名列的值。在列族裡,列的個數不是固定的,假如想在Info列組裡面再加一個列,直接在列族裡添加即可,這就是動态列的特點。
還有一個特性是時間戳,例子中定義了城市列和三個時間戳,杭州時間戳2019,中原標準時間戳2016,廈門時間戳2012,使用者可以在寫入值的時候填入時間戳,否則系統會自動按照目前時間設定時間戳。這三個版本的值會同時存在列裡,如果檢索1001的城市值,預設傳回最新的版本。如果想把多版本都傳回,則需要在檢索的時候告訴系統需要幾個版本,則系統會根據要求傳回相應版本的資料,這就是HBase基本的資料模型。
通過這個資料模型可以看到,首先是按字典序排序存儲,就可以很友善地進行範圍查詢,比如檢索ID 1001~1003的資料,用一個Scan語句就可以把這幾條資料全部傳回。同時,資料是按行存儲,比如指定ID 1001,可以快速地把這整行資料都取出。
HBase中有幾個常見的查詢場景,第一個是主鍵查詢,基于Rowkey值,可以快速拿到某一行資料。 第二個是範圍查詢,可以指定Rowkey的範圍,把符合條件的資料全部取出來。
第三個是條件過濾,在Get/Scan資料的時候,還想指定某個列值等于某個條件的,比方說檢索範圍是1001~1003,年齡等于20的資料,則系統隻會把1001的資料給檢測出來。
Filter相當于是過濾條件。除了指定 Rowkey的範圍之外,可以指定一個單獨的條件,把滿足條件的資料檢索出來。 HBase支援使用多語言查詢,除了HBase原生支援的語言以外,還支援多種語言通路。
(二)HBase資料查詢
1. HBase Shell
下面介紹如何通過HBase的Shell建立一個表并寫入資料,以及通過Shell把資料檢索出來。 表的名字為“myTable”,列族為“f”,執行建表指令create 'myTable','f’即可成功建立。
建表時還需注意以下幾點:
1)建表時必需的參數:表名和列族名
2)表預分區:建表時設定分區個數、分區範圍,預分區是防止資料出現熱點的最佳實踐。
3)列族屬性:TTL、多版本、壓縮、編碼屬性等。
建表完成後可以開始寫資料。
·寫資料: put 'myTable','1001','f:name','alice’
·表名:myTable
·RowKey:1001
·列族+列名:f:name
·值:alice
這條指令相當于把資料alice寫入Rowkey等于1001,列族等于f,列名等于name的地方。
這裡需要注意的地方是,HBase在寫入資料時,無法通過單獨的列名确定寫入的地方,需要列族+列名。這是由于表中可能存在不同的列族中有相同的列名,是以無法單獨通過列名來确定列。
2.查詢
在寫入資料之後,需要做資料查詢,主要有以下三種方法。
主鍵查詢:get 'myTable','1002’
範圍查詢:scan 'myTable',{STARTROW => '1002', STOPROW => '1004’}
條件過濾:scan 'myTable',{STARTROW => '1002', STOPROW => '1004', FILTER=>"SingleColumnValueFilter('f', 'name',=,'binary:bob')"}
這裡需要注意的一點是,範圍查詢裡的STARTROW => '1002'是個閉區間,STOPROW => '1004’是個開區間,相當于取出的資料是1002和1003的資料。假設表中有1004的資料,這個資料是不會被檢測出來的。
條件過濾相當于指定了一個範圍外加一個條件,例如1002和1004,範圍内的資料有很多,但是符合條件的資料非常少,後面跟一個過濾條件Filter,過濾的條件是'name',=,'binary:bob'的一行資料。
以上是HBase Shell的用法,使用者可以通過輸入 List Filters得到目前支援的所有filter。
3. Java API通路
除了HBase Shell這種查詢的文法之外, HBase原生支援的就是 Java API通路。通過Java API我們可以快速取到某一行資料或者Scan某些資料。
上圖為一個簡單的Demo。
首先指定一個表名,然後new Put一個對象,相當于要寫一行資料,這一行資料在new Put的時候會指定Rowkey是1001。接着指定列族、列的名字,以及列的值,然後就可以完成資料寫入。
接下來可以直接執行get方法,比如指定Rowkey就可以拿到相應資料。如果想範圍查詢,就通過Scan指定一個範圍,也可以拿到相應資料。
Phoenix入門
SQL是大部分資料庫通用的語言,HBase通過Phoenix元件支援SQL操作。接下來闡述除了通過Shell與Java API之外, 如何通過SQL操作HBase。
(一)Phoenix介紹
Phoenix:OLTP and operational analytics for Apache Hadoop.
Phoenix是Salesforce公司主導的Apache開源項目,緻力于“put the SQL back in NoSQL”,提升HBase的使用體驗,賦予HBase OLTP和輕量級OLAP的能力。
Phoenix遵循ANSI SQL-92标準,支援JDBC API、Transactions、UDF、Secondary Indexes、Salt Tables等。 Phoenix文法豐富,支援group by/order by/join/subquery/function等(Phoenix Grammar)。
Phoenix具備毫秒級互動式體驗,MPP并行執行,充分利用HBase Coprocessor實作計算下推。
(二)Phoenix SQL基本使用
1. Phoenix Sqlline
下面介紹Phoenix的SQL如何操作HBase。
Phoenix有專門的Sqlline,下載下傳之後也是一個用戶端的程式,通過Sqlline連接配接到Phoenix叢集,就可以在上面直接建立表,然後讀寫資料。
下面舉例說明。
建表: create table myTable(id VARCHAR primary key, name CHAR(20), age INTEGER, sex CHAR(10));’
表名:myTable
列名和列類型:id 主鍵,name 字元串類型,age 整數類型,sex 字元串類型
寫資料:upsert into myTable values('1001','alice',18,'male');
2. Phoenix Sqlline查詢
前面介紹了HBase通過Shell檢索某行資料或範圍查詢,Phoenix Sqlline也可以擷取某行資料與簡單的範圍查詢,如下所示。
主鍵查詢:select * from myTable where id='1002';
範圍查詢:select * from myTable where id>='1002' and id<='1004' limit 10;
過濾查詢:select * from myTable where id>='1002' and id<='1004' and name='bob' limit 10;
可以看到,通過SQL語句操作HBase會更加地簡單,對于開發人員而言也是更加簡單易用。
3. 豐富的文法支援
Phoenix的文法非常豐富,在官網可以看到它文法的清單,它基本涵蓋類似于SQL92的所有文法,可以看到詳盡的文法使用方法。
豐富的文法
上方為線上的一個查詢場景,它也可以做到兩個不同表的查詢,這也是非常常見的一種文法。
查詢加速
(一)多樣化的查詢
在HBase的使用過程中,除了上文講到的HBase支援的查詢之外,随着資料量的增加,業務的查詢場景會更加多樣化,下面簡單介紹了幾個來源于業務的真實需求。
多元查詢:即席查詢,一般是不固定的列随機組合。
count計數:擷取資料表的總行數,或者傳回一次查詢命中的資料條數。
指定列排序:按照指定列降序或升序,比方說按照訂單時間降序輸出結果。
分詞檢索:支援文本字段的分詞檢索,傳回相關性較高的結果資料。
統計聚合:按照某個字段進行聚類統計,求取sum/max/min/avg等,或者傳回去重後的結果集。
模糊查詢:查詢以“中國”開頭的資料,可以比對出“中國人民”的結果集,類似MySQL的like文法。
通用解決方案
1. 協處理器:計算下推,服務端執行邏輯。
2. 二級索引:變換資料存儲格式,加速非主鍵查詢。
3. 全文索引:引入搜尋引擎解決查詢難題。
(二)協處理器
HBase原生協處理器Coprocessor,邏輯在服務端運作,避免移動資料,加速處理。
協處理器Coprocessor有兩種模式:
1. Observer
與資料庫的觸發器類似,在一些特定事件發生時執行回調函數。HBase服務端的核心邏輯已經在固定的流程中埋點,例如在put寫資料前執行一段函數prePut,put寫資料後執行一段函數postPut。
2. Endpoint
與資料庫的存儲過程類似,用戶端遠端調用服務端的代碼,例如HBase原生支援的聚合Aggregate,求max/min/avg。
(三)二級索引 - 非主鍵索引
前文主要闡述了主鍵Rowkey的查詢,如果檢索條件是指定一個列去查詢,其實就沒有指定主鍵了,需要通過二級索引的非主鍵索引解決,下面舉例說明。
如上方所示,掃描表myTable,檢索條件是'name',=,'binary:bob'。
如果表的資料非常大,需要把所有的資料都掃描出來,這種查詢非常消耗資源,并且由于逐漸掃描,可能會逾時。
面對這種場景,最通用的解決方案就是用HBase的二級索引,下圖為HBase二級索引的查詢模型。
如上圖所示,右邊是主表的查詢,包含按順序存儲的Rowkey與幾個列。 如果檢索條件隻有Col2,就可以建一個二級索引。
左邊是一個二級索引表,它是一個單獨的表,表的主鍵由Col2和Rowkey組成,唯一确定了索引表的一行資料,可以快速檢測出符合條件的資料。
(四)二級索引的實作
Phoenix基于協處理器實作二級索引。
上方為是基于Observer實作二級索引的一個例子。
在Put/Delete流程中解析寫入的資料,構造索引資料,寫入到索引表中。在Scan流程中解析查詢文法,命中索引,則查詢索引表,沒有命中索引,則查詢原表。
(五)全文索引(HBase+Elasticsearch)
還有一種通用的解決方案是全文索引(HBase+Elasticsearch),通過HBase的高效查詢與Elasticsearch的全文索引, 可以滿足多樣化的查詢場景。
全文索引(HBase+Elasticsearch)有許多方案,如業務雙寫、資料自動同步、Observer觸發器等。
1.業務雙寫
·簡單,業務快速落地。
·開發成本高:應用同時與HBase和 Elasticsearch互動。
·維護複雜:熟悉HBase和Elasticsearch 技術棧。
·資料不一緻。
2.資料自動同步
·無需雙寫,隻需雙讀,開發成本降低。
·資料最終一緻。
·維護複雜:熟悉HBase和Elasticsearch 技術棧、資料同步服務。
3. Observer觸發器
·僅與HBase互動,應用開發成本進一步 降低,但要額外開發Observer程式。
·維護複雜:熟悉HBase和Elasticsearch 技術棧,Observer容易引起系統不穩定。
·寫入延遲:Elasticsearch寫入阻塞全局。