Hbase學習總結
1.HBase概述及部分存儲知識概述:
架構簡介:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmL3YzMxYTNwADNwYDMyEDMy8CXxkDO5czLcJTMwIzLcNXZnFWbp9CXt92YuM3ZvxmYuNmLyADMjlGcvw1LcpDc0RHaiojIsJye.jpg)
簡述: Hbase基于hadoop的HDFS系統,其檔案存儲都是存儲在HDFS上的。由上圖看到HBase主要處理兩種檔案:一種是預寫日志(Write-Ahead Log,WAL)即圖中的HLog。另一種檔案是實際的資料檔案HFile(HFile本事就是HDFS的檔案,檔案格式遵循HBase可導入的格式)。預寫日志WAL是可開關的,器主要保障資料的穩定性。當機器結點挂掉,可以通過回放日志達到資料恢複的目的。
HBase中最核心的HRegion子產品如下圖:
簡述:上圖就是HRegionServer的具體的系統的架構。具體的關系一目了然。各個部件的主要功能如下: HMaster:
HMaster沒有單點問題,HBase中可以啟動多個HMaster,通過Zookeeper的Master Election機制保證總有一個Master在運作,主要負責Table和Region的管理工作:
(1)管理使用者對表的增删改查操作
(2)管理HRegionServer的負載均衡,調整Region分布
(3)Region Split後,負責新Region的分布
(4)在HRegionServer停機後,負責失效HRegionServer上Region遷移
Client:
(1)使用HBase RPC機制與HMaster和HRegionServer進行通信
(2)Client與HMaster進行通信進行管理類操作
(3)Client與HRegionServer進行資料讀寫類操作
Zookeeper:
(1)Zookeeper Quorum存儲-ROOT-表位址、HMaster位址
(2)HRegionServer把自己以Ephedral方式注冊到Zookeeper中,HMaster随時感覺各個HRegionServer的健康狀況
(4)Zookeeper避免HMaster單點問題 ps:HRegionServer管理一些列HRegion對象;每個HRegion對應的Table中一個Region,HRegion有多個HStore組成;每個HStore對應Table中一個Column Family的存儲;
2.存儲架構:
HBase的存儲系統簡單描述一下,HBase和BigTable(BigTable的論文如下:http://box.cloud.taobao.com/file/downloadFile.htm?shareLink=1G0bDlGn)一樣,都是基于LSM樹的系統。
下面簡述一下LSM樹:
在LSM樹系統中:輸入資料首先被存儲在日志檔案,這些檔案内的資料完全有序。當有日志檔案被修改時,對應的更新會被儲存在記憶體中來加速查詢。從宏觀上來說,LSM樹原理是把一個大樹拆分成N棵小樹,它首先寫入記憶體中,對着小樹越來越大,記憶體中的小樹會flush到磁盤中,磁盤定期可以做merge操作,合并成一棵大樹,以優化讀性能。
附稿:
BigTable論文中關鍵資訊總結:
2.1 Bigtable是一個分布式的結構化資料存儲系統,他被設計用來處理海量資料:通常是分布在數千台普通伺服器上的PB級資料。<br>
2.2 列族:列關鍵字組成的集合叫做“列族”,列族是通路控制的基本機關。存放在同一列族下的所有資料通常都屬于同一個類型(我們可以把同一個列族下的資料壓縮在一起)。<br>
2.3 列族建立後,其中的任何一個列關鍵字都可以存放資料。根據我們的設計意圖,一張表中的列族不能太多(最多幾百個),并且列族在運作期間很少改變。與之對應的,一張表可以由無限多個列。<br>
2.4 時間戳:在BigTable中,表的每個資料項都可以包含同一份資料的不同版本;不同版本的資料通過時間戳來索引。BigTable時間戳的類型是64位整型。BigTable可以給時間戳指派,用來表示精确到毫秒的“實時”時間;使用者程式也可以給時間指派。如果應用程式需要避免資料版本沖突,那麼必須自己生成具有唯一性的時間戳。資料項中,不同版本的資料按照時間戳倒叙排序,及最新的資料排在最前面。<br>
2.5 BigTable支援單行上的事物處理,利用這個功能,使用者可以對存在一個行關鍵字下的資料進行原子性的讀-寫-更新 操作。雖然BigTable提供了一個允許使用者跨行批量寫入的資料的接口,但是,BigTable目前還不支援通用的跨行事物處理。<br>
2.6 BigTable是建立在其他的幾個Google基礎構件上的。BigTable使用Google的分布式檔案系統(GFS)存儲日志檔案和資料檔案。<br>
2.7 BigTable内部存儲資料的檔案是Google SSTable格式的。SSTable是一個持久化的、排序的、不可更改的Map結構,而Map是一個key-value映射資料結構,key和value的值都是任意的Byte串。
2.8 BigTable還依賴一個高可用的,序列化的分布式鎖元件,叫做Chubby。(對應apache的zookeeper)。<br>
2.9 Bigtable包括了三個主要的元件:連結到客戶程式中的庫、一個Master伺服器和多個Tablet伺服器。針對系統工作負載的變化情況,BigTable可以動态的向叢集中添加(或者删除)Tablet伺服器。<br>
2.10 Bloom過濾器(又叫:布隆過濾器):它實際上是一個很長的二進制矢量和随機映射函數。布隆過濾器可以用于檢索一個元素是否在一個集合中。它的有點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識别率和删除困難。<br>
3.WAL:WAL是标準的Hadoop SequenceFile,并且存儲了HLogKey執行個體。這些鍵包括序列号和實際資料,是以在伺服器崩潰時可以復原還沒有持久化的資料。
ps:一旦資料被寫入WAL中,資料就會被放到MemStore中。同時還會檢查Memstore是否已經滿了,如果滿了,就會被請求刷寫到磁盤中去。
4.Table&Region:(1)Table随着記錄增多不斷變大,會自動分裂成多份Splits,成為Regions。(2)一個region由[startkey,endkey)表示。(3)不同region會被Master配置設定給相應的RegionServer進行管理。
5.資料通路結構:
首先會有zookeeperfile擷取-ROOT-結點的位址,-ROOT-是一張特殊的表,并且隻會存在一個Region上,記錄着.META.表的位置,.META.使用者表的region資訊,.META.本身可以橫跨多個Region。客戶請求擷取位址資訊的過程,就是這樣一個樹狀結構,逐級請求。
6.HBase的一個特殊的功能是,能為一個單元格(一個特定列的值)存儲多個版本的資料。這是通過每個版本使用一個時間戳。并且按照降序存儲來實作的。每個時間戳是一個長整型值,以毫秒為機關。
2.用戶端API:
-
Hbase用戶端簡單的CRUD操作:
(1) put方法,一類作用于單行,另一類作用于多行。 ps:當每一次不指定時間戳調用Put類的add方法時,Put執行個體會使用來自構造函數的可選的時間戳參數(也稱作ts),如果使用者在構造Put執行個體時也沒有時間指定時間戳,則時間戳将會有Region伺服器設定。
(2) 原子性的put操作(compare-and-set):
接口執行個體: boolean checkAndPut(byte[] row,byte[] family,byte[] qualifier,byte[] value,Put put) throws IOException
(3) get方法:
I.get方法分為兩類,一類是一次擷取一行資料;另一類是一次擷取多行資料。擷取資料時可以擷取一個或多個列族的資料,也可以指定擷取的列族内資料的特定的列。或者指定時間戳範圍或者版本數目進行查詢。
II.擷取多行資料get方法的方法簽名如下:
Result[] get(List<Get> gets) throws IOException
ps:使用者可以一次請求擷取多行資料。它允許使用者快速高效地從遠端伺服器擷取相關的或完全随機的多行資料。
(4) exists方法通過RPC驗證請求的資料是否存在,但不會從遠端伺服器傳回請求的資料,隻傳回一個布爾值表示這個結果。
方法簽名如下: boolean exists(Get get) throws IOException
ps:使用者通過這種方法隻能避免網絡資料傳輸的開銷,不過需要檢查或頻繁檢查一個比較大的列時,這種方法還是十分實用的。 (5) Delete 方法:
Delete方法可以删除一列中特定的版本,一列中全部版本,給定版本或更舊的版本,删除整個列族,或者删除列族中所有列的給定版本或更舊的版本。
另外和Put方法類似,也可以删除一個Delete清單對象:
接口如下:
void delete(List<Delete> deletes) throws IOException
(5) 原子性操作 compare-and-delete:
方法簽名如下:
boolean checkAndDelete(byte[] row,byte[] family,byte[] qualifier,byte[] value,Delete delete) throws IOException
(6) 批量操作:
上面總結了對Hbase單行的操作,Hbase還提供了批量操作的接口,可以對多行進行操作,并且可以實作多行的Put,Get或Delete操作。
方法簽名如下:
void batch(List<Row> actions,Object[] results) throws IOException,InterruptedException Object[] batch(List<Row> actions) throws IOException,InterruptedException
(7) 資料掃描 Scan:
顧名思義Scan操作能掃描周遊Hbase資料庫中的資料,掃描器的擷取通過 HTable.getScanner()擷取,此方法傳回真正的掃描器執行個體的同時,使用者也可以使用它疊代擷取資料,方法簽名如下:
同時Scan類擁有以下構造器:ResultScanner getScanner(Scan scan) throws IOException ResultScanner getScanner(byte[] family) throws IOException ResultScanner getScanner(byte[] family,byte[] qualifier) throws IOException
Scan() Scan(byte[] startRow,Filter filter) Scan(byte[] startRow) Scan(byte[] startRow,byte[] stopRow)
(8) ResultScanner:
掃描操作一次可能請求大量的行,如果全部傳回可能占用大量的記憶體和帶寬,ResultScanner把掃描操作轉換為類似get操作,将每一行資料封裝成一個Result執行個體。
ResultScanner的一些方法如下:
Result next() throws IOException Result[] next(int nbRows) throws IOException void close()
2.過濾器:
Hbase過濾器(filter)提供了非常強大的特性來幫助使用者提高其處理表中資料的效率。使用者不僅可以使用Hbase中預定義好的過濾器,而且可以實作自定義的過濾器。
Get和Scan兩個類都支援過濾器,理由如下:這類對象不能對行鍵、列名或列值進行過濾,但是通過過濾器可以達到這個目的。除了Hbase内置的filter外,使用者可以實作Filter接口來自定義需求。所有過濾器都在伺服器端生效,叫做謂詞下推。
(1)比較過濾器 CompareFilter:
方法簽名:
CompareFilter(CompareOp valueCompareOp,WritableByteArrayComparable valueComparator)
使用者使用時需要傳入操作符,和待比較的值,比如大于或小于多少才從伺服器端傳回資料。
(2)行過濾器 RowFilter:
方法簽名:
RowFilter(CompareOp valueCompareOp,BinaryComparator rowkey)
可以過濾大于、小于或等于指定行鍵的資料。
(3)列族過濾器(FamilyFilter):
方法簽名和行過濾器類似:
FamilyFilter(CompareOp valueCompareOp,BinaryComparator rowkey)
用來過濾滿足條件的列族。
(4)值過濾器(ValueFilter):
方法簽名:
ValueFilter(CompareOp valueCompareOp,BinaryComparator value)
用來過濾滿足條件的列值。
(5)參考過濾器(DependentColumnFilter):
簡述:這個是一種特殊的過濾器,這個過濾器的比較傳入的參考值不再是指定的常量,而是相對于Hbase自身的某一行做比較。
方法簽名如下:
DependentColumnFilter(byte[] family,byte[] qualifiter)
方法參數分别是參考列的列族和列名,如果某列和該列含有不同的時間戳,則被丢棄掉。
+++ DependentColumnFilter(byte[] family,byte[] qualifiter,boolean dropDependentColumn) 這個方法和上面的方法類似,隻不過增加了一個布爾值定義是否包含參考咧。 +++
DependentColumnFilter(byte[] family,byte[] qualifiter,boolean dropDependentColumn,CompareOp valueCompareOp,WritableByteArrayComparable valueComparator)
這個方法定義了所有列和指定列的值的比較。 這個過濾器從參數名稱上不太好了解,可以參考官網的wiki(http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/DependentColumnFilter.html)
(6)單列值過濾器(SingleColumnValueFilter):
簡述:使用者針對如下情況是可以使用該過濾器:用一列的值決定是否一行資料被過濾。首先設定待檢查的列,然後設定待檢查的列的對應值。方法簽名如下:
SingleColumnValueFilter(byte[] family,byte[] qualifiter,CompareOp compareOp,byte[] byte[] value)
(7)單列值排除過濾器(SingleColumnValueExcludeFilter):
簡述:單列值排除過濾器內建自SingleColumnValueFilter,經過拓展後提供一種略微不同的語意:參考列不被包括在結果中。
(8)字首過濾器(PrefixFilter):
簡述:當構造目前過濾器時傳入一個字首,所有與字首比對的行都會被傳回用戶端。構造函數如下:
public PrefixFilter(byte[] prefix)
(9)分頁過濾器(PageFilter):
簡述:使用者可以使用這個過濾器對結果按行分頁。當使用者建立目前過濾器執行個體時需要指定pagesize參數,這個參數可以控制每頁傳回的行數。
執行個體代碼如下:
Filter filter = new PageFilter(15)
int totalRows = 0;
byte[] lastRow = null;
while(true) {
Scan scan = new Scan();
scan.setFilter(filter);
if(lastRow != null) {
byte[] startRow = Bytes.add(lastRow,POSTFIX);
scan.setStartRow(startRow);
}
ResultScanner scanner = table.getScanner(scan);
int localRows = 0;
Result result;
while((result = scanner.next()) != null) {
totalRows++;
lastRow = result.getRow();
}
scanner.close();
if(localRows == 0) {
break;
}
}
ps:Hbase中的行鍵是按字典序排列的,是以傳回的結果也是如此排序的,并且起始行是被包括在結果中的。
(10)行鍵過濾器(KeyOnlyFilter):
簡述:在一些應用中隻需要将結果中的KeyValue中的鍵傳回,而不需要傳回實際的資料。利用這個過濾器可以實作這個目的。
(11)首次行鍵過濾器(FirstKeyOnlyFilter):
簡述:這個類使用了過濾器架構提供的另一個優化特性:他在檢查完第一列之後會通知region伺服器結束對目前列的掃描,并跳到下一行,與全表掃描相比,其性能得到了提升。
這種過濾器通常在行數統計(row counter)的應用場景中使用。具體使用參考blog:http://blog.csdn.net/liuxiaochen123/article/details/7878580
(12)包含結束過濾器(InclusiveStopFilter):
簡述:掃描操作中的開始行被包含在結果中,但終止行被排除在外。使用這個過濾器是,使用者也可以将結束行包含到結果中。
(13)時間戳過濾器(TimeStampsFilter):
簡述:當使用者需要在掃描結果中對版本進行細粒度的控制時,這個過濾器可以滿足需求。使用者需要傳入一個裝載了時間戳list執行個體。
(14)列計數過濾器(ColumnCountGetFilter):
簡述:使用者可以使用這個過濾器來限制每行最多取回多少列。當一行列的列數達到設定的最大值時,這個過濾器會停止這個掃描操作,是以它不太适合掃描操作,反而比較适合在get()方法中使用。
(15)列字首過濾器(ColumnPrefixFilter):
簡述:類似于PrefixFilter,這個過濾器通過列名稱進行字首比對過濾。使用者需要指定一個字首來建立過濾器。所有與設定字首比對的列都會包含在結果中。
(16)随機行過濾器(RandomRowFilter):
簡述:這個過濾器可以讓結果中包含随機的行。構造函數需要傳入參數chance,chance取值區間在0.0和1.0之間。其内部實作原理用到了java 的 Random.nextFloat,當chance取負數時,将包含排除所有的行,但取值大于1.0時,将包含所有的行。
(17)跳轉過濾器(SkipFilter):
簡述:這個過濾器包裝了一個使用者提供的過濾器,當被包裝的過濾器遇到一個需要過濾的KeyValue執行個體時,使用者可以拓展并過濾掉整行資料。換句話說,當過濾器發現某一行中的一列需要過濾時,那麼整行資料将被過濾掉。
(18)全比對過濾器(WhileMatchFilter):
簡述:當被過濾的資料中,遇到一行不比對時,則放棄整個過濾操作。即列比對才會繼續執行,遇到不比對的列則中斷執行(估計也是性能優化點)。
(19)FilterList:
簡述:實際應用中,使用者可能需要多個過濾器共同限制傳回到用戶端的結果,FilterList(過濾器清單)提供了這項功能。
(20)自定義過濾器:
簡述:最後,使用者可能需要按各自的需求實作自定義過濾器。使用者可以實作Filter接口或者直接繼承FilterBase類,後者已經為接口中所有成員方法提供了預設實作。
ps:過濾器設在在Scan和Get對象當中,具體過濾器的執行全部多事在服務端執行,用以減少服務端和用戶端的網絡IO。
3.計數器:
Hbase内部提供了計數器,可以用來統計Hbase表的一些資訊,例如:用于記錄某個列值的個數。
4.用戶端管理API:
除了進行資料處理的用戶端API,HBase還提供了資料描述的API,類似于傳統RDBMS中的DDL和DML。因為生産環境,作為基于Hbase的開發人員基本無法擷取HBaseAdmin的管理權限,針對DDL和DML的API就不詳細介紹了,這部分内容了解一下就可以了。
3.HBase涉及的技術亮點:
- Hbase的一個特殊功能是,能為一個單元格(一個特定列的值)存儲多個版本的資料。這是通過每個版本使用一個時間戳。并且按照降序存儲來實作的。每個時間戳是一個長整型值,以毫秒為機關。
- KeyValue執行個體代表了一個唯一的資料單元格,類似于一個協調系統,該系統使用行鍵、列族、列限定符、時間戳指向一個單元格的值。KeyValue是Hbase在存儲架構中最低層的類。
- 行鎖:像put(),delete(),checkAndPut()這樣的修改操作是獨立執行的,這意味着在一個串行的方式的執行中,對于每一行必須保證行級别的操作是原子性的。region提供了一個行鎖(row lock)的特性,這個特性保證了隻有一個用戶端能擷取一行資料相應的鎖,同時對改行進行修改。
- Hbase作為KeyValue的結構存儲,以rowkey的字典序進行排序。
- Hbase作為一個列資料庫,其也和其他資料庫一樣,為了提高性能,再起服務端提供了一個連接配接池HTablePool來管理連接配接。
-
事物:HBase本身也提供了事物的支援,有如下幾個項目用來支援HBase的事物:
(1)事物型HBase:帶索引的事物型HBase項目有一些取代預設用戶端類和服務端類的擴充類,它們增加了跨行跨表的事物支援。在Region伺服器中,更準确的說,每個Region都保持了一個事物的清單。該清單是有beginTransaction()調用初始化,并且相應的commit()調用結束。每次讀寫操作都有一個事物ID,以保護調用不受其他事物影響。
(2)用Zookeeper來維持事物:Zookeeper也提供了一個能夠被用于實作兩階段送出的事務鎖解決方案。
7.布隆過濾器(Bloom Filter):布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識别率和删除困難。布隆過濾器的原理是Hash表,其用Hash函數将某個元素映射成位列陣中的某個點,用以高效的識别集合是否包含這個元素。而HBase中也内置了布隆過濾器的功能,例如可以快速的判斷某個列簇檔案中是否包含某個值。
8.Bulkload資料導入,HBase提供了Bulkload資料導入的方式,可以通過Hbase自帶的工具和利用其API自己寫MR的方式将HDFS檔案轉換成HFILE的檔案格式,其實其還是HDFS檔案,不過檔案格式變成了HBase的存儲檔案,然後通過其load API就能導入到資料庫中。
Hfile檔案格式如下圖:
ps:可見其存儲都是keyvalue的形式,還沒完全包明白暫時不詳細總結了。
HBase内置的用于生成HFILE的API是:org.apache.hadoop.hbase.mapreduce.ImportTsv
具體的調用方式如下:
$HBASE_HOME/bin/hbase org.apache.hadoop.hbase.mapreduce.ImportTsv \
-Dimporttsv.bulk.output=$HFILE_PATH \
-Dimporttsv.separator=$SEPARATER \
-Dimporttsv.columns=$COLUMNS $TABLE_NAME $HDFS_PATH
ps: HFILEPATH:就是生成的Hfile的存儲路徑。SEPATATER就是資料行的分隔符。COLUMNS就是需要導入的列名,這個比較講究,這個是根據HDFS的列的資料來定義的,比如寫成:HBASEROW_KEY,cf:value1,cf:value2 就表示HDFS的第一列作為ROWKEY,這個HBASEROWKEY是約定好的關鍵字,這個關鍵字放在什麼位置就表示HDFS的第幾列作為rowkey,同時也就要求被轉換的HDFS檔案必須某一列可以作為rowkey(可能需要預處理)。然後cf就是列族,value就是對應的列名。