1. 程式人生 > >Hbase原始碼解析和開發實戰筆記

Hbase原始碼解析和開發實戰筆記

Hbase筆記
HBase基礎
1)HBase簡介
2)HBase特點
3)HBase資料模型
4)HBase體系結構
5)HBase儲存模型
6)HBase應用




簡介
1)HBase是一個分散式的、多版本的、面向列的開源資料庫
2)HBase利用Hadoop HDFS作為其檔案儲存系統,提供高可靠性、高效能、列儲存、可伸縮、實時讀寫、適用於非結構化資料儲存的資料庫系統
3)HBase利用Hadoop MapReduce來處理HBase中的海量資料
4)HBase利用Zookeeper作為分散式協同服務


特點:
1)資料量大:一個表可以有上億行,上百萬列(列多時,插入變慢)
2)面向列:面向列(族)的儲存和許可權控制,列(族)獨立檢索
3)稀疏:對於為空(null)的列,並不佔用儲存空間,因此,表可以設計的非常稀疏
4)多版本:每個cell中的資料可以有多個版本,預設情況下版本號自動分配,是單元格插入時的時間戳
5)無型別:HBase中的資料都是字串,沒有型別
6)強一致性:同一行資料的讀寫只在同一臺Region Server上進行
7)有限查詢方式:僅支援三種查詢方式(單個rowkey查詢,通過rowkey的range查詢,全表掃描)
8)高效能隨機讀寫


資料模型
1)行:同一個key對應的所有資料
2)列族:相似的列資料通常被劃分成一個列族,建表時確定
3)列:列名在寫入時確定
4)Cell及時間戳(版本):
每個cell有任意多的版本
建表時設定每個列族可以保留多少個版本
5)三維有序
SortedMap(RowKey,List(SortedMap(Column,List(Value,TimeStamp))))


rowkey(ASC)+columnLabel(ASC)+Version(DESC)->value
|------------|--------------|--------------------|----------------------------|---------------|
|Row key     |Time Stamp    | Column "contents:" | Column "anchor:"           | Column "mime:"|
|------------|--------------|--------------------|------------------|---------|               |
|com.cnn.www |t9   |                    | anchor:cnnsi.com |CNN      |               |
|------------|--------------|--------------------|------------------|---------|---------------|
|            |t8            |                    | achor:my.look.ca |CNN.com  |               |
|------------|--------------|--------------------|------------------|---------|---------------|
|    |t6            | "<html>..."        |                            | "text/html"   |
|------------|--------------|--------------------|----------------------------|---------------|
|    |t5            | "<html>..."        |                            |               |
|------------|--------------|--------------------|----------------------------|---------------|
|    |t3            | "<html>..."        |                            |               |
|------------|--------------|--------------------|----------------------------|---------------|
--------------------------------------------------
1)面向列的儲存
2)一張表可以被劃分成若干個region
3)行按照rowkey進行字典序排序
4)支援隨機讀寫
5)region是負載均衡排程的最小單位
------------------------------------------------------------------------------
體系結構
1)Client
包含訪問HBase的介面並維護cache來加快對HBase的訪問
2)Zookeeper
保證任何時候,叢集中只有一個master
儲存所有Region的定址入口:
實時監控Region server的上線和下線資訊,並實時通知給Master;
儲存HBase的schema和table元資料
3)Master
為Region server分配region;
負責Region server的負載均衡
發現失效的Region server並重新分配其上的region
管理使用者對table的增刪改查操作
4)Region Server
負責維護region,處理對這些region的IO請求
負責切分在執行過程中變得過大的region
5)ROOT表
記錄META表中的每個region的位置,ROOT表最多隻有一個region Zookeeper中記錄了ROOT表的location
6)META表
記錄各個表每個region所在的region server,META表可能包含多個region
------------------------------------------------------------------------------------------
HBase操作
1)flush
記憶體容量有限,需要定期將記憶體中的資料flush到磁碟
每次flush,每個region的每個column family都會產生一個HFile
讀取操作,region server會把多個HFile資料歸併到一起


2)compaction
flush操作產生的HFile會越來越低,需要歸併來減少HFile的數量
舊資料會被清理


3)split
HFile大小增長到某個閥值就會split,同時把Region split成兩個region,這兩個region被分發到其他不同的region server上


4)scan
hbase原生提供的方法,順序掃庫;當然可以使用MapReduce併發掃庫的方法


5)Bulk Load
快速匯入大批量資料的方法
-------------------------------------------------------------------------------------------
儲存模型
1)一個table中的一個region會被隨機分配給一個region server
2)region是分散式儲存和負載均衡的最小單位
------------------------------------------------------
最開始table只有一個region,但是隨著資料的put,到達某個閥值的時候,一個大的region會split成幾個小region,被分配到其他region server
------------------------------------------------
HFile結構
1)基於Block的儲存結構
2)Block的索引駐留記憶體
---------------------------------
HBase應用
1)HBase環境搭建
配置hbase-env.sh
hbase-site.xml
regionservers
執行start-hbase.sh
啟動後執行hbase shell進入互動式命令列


2)HBase API使用舉例
Put/Get
Scan
.....


-----------------------------------------------------------------------------------------------------------
Hbase_test.java
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;




public class Hbase_test {
public static void main(String[] args){
Configuration conf = new Configuration();
HBaseConfiguration hbconf = new HBaseConfiguration(conf);

/*try {
HBaseAdmin admin = new HBaseAdmin(hbconf);
HTableDescriptor tableDesc = new HTableDescriptor("test");
tableDesc.addFamily(new HColumnDescriptor("info"));
admin.createTable(tableDesc);

} catch (MasterNotRunningException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ZooKeeperConnectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/

try {
HTable table = new HTable(hbconf,"test");
/*Put put = new Put("row1".getBytes());
put.add("info".getBytes(),"A".getBytes(),"1".getBytes());
table.put(put);
table.close();*/

Scan scan = new Scan();
ResultScanner res = table.getScanner(scan);
for(Result r:res){
for(KeyValue kv: r.raw()){
System.out.println("rowkey=> " + new String(r.getRow())
                  + " family=> " + new String(kv.getFamily())
                  + " qualifier=> " + new String(kv.getQualifier())
                  + " timestamp=> " + kv.getTimestamp()
                  + " value=> " + new String(kv.getValue()));
}


}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
----------------------------------------------------------------------------------------------------------------------
HBase系統搭建與部署
1)開源社群版本下載
-http://hbase.apache.org/
2)Cloudera發行版下載
-http://archive-primary.cloudera.com/cdh5/cdh/5/


Hadoop2.0部署
1)配置hosts 確保涉及的主機名均可以解析
2)編輯hadoop-env.sh,mapred-env.sh,yarn-env.sh
3)編輯core-site.xml,hdfs-site.xml,yam-site.xml
5)編輯slaves檔案
6)把Hadoop複製到其他節點
7)啟動Hadoop
8)驗證啟動


Hadoop2.0 HA部署
採用QJM方案
1、啟動JN
./sbin/hadoop-daemon.sh start jourmalnode
./sbin/hadoop-daemons.sh start journalnode
hdfs namenode -initialize SharedEdits


2、啟動Active NN
hdfs namenode -format
bin/hadoop-daemon.sh start namenode


3、啟動Standby NN
hdfs namenode -bootstrap Standby
./sbin/hadoop-daemon.sh start namenode


4、啟動Automatic Failover
hdfs zkfc -formatZK
./sbin/hadoop-daemon.sh start zkfc


hdfs haadmin -transitionToStandby nn1


hdfs haadmin -failovernn1 nn2


hdfs haadmin -getServiceState nn1
-----------------------------------------------------------------------------------------------------------------------------
HBase Shell 操作
(1)建立一個表scores,有兩個列族grad和courese
>>create 'scores','grade','course'
(2)檢視Hbase中的所有表
>>list
(3)查看錶結構
>>describe 'scores'


Shell操作
4、按設計的表結構插入值
put 'scores','Tom','grade:','5'
put 'scores','Tom','course:math','97'
put 'scores','Tom','course:art','87'
put 'scores','Jim','grade:','4'
put 'scores','Jim','course:','89'
put 'scores','Jim','course:','80'


put命令比較簡單,只有這一種用法:
put 't1','r1','c1','value',ts1
t1指表名,r1指定鍵名,c1指列名,value指單元格值。ts1指時間戳,一般都省略掉了。


5、根據鍵值查詢資料
>>get 'scores','Jim'
>>get 'scores','Jim','grade'
get 't1','r1'
get 't1','r1',{TIMERANGE=>[ts1,ts2]}
get 't1','r1',{COLUMN=>'c1'}
get 't1','r1',{COLUMN=>['c1','c2','c3']}
get 't1','r1',{COLUMN=>'c1',TIMESTAMP=>ts1}
get 't1','r1',{COLUMN=>'c1',TIMERANGE=>[ts1,ts2],VERSIONS=>4}
get 't1','r1',{COLUMN=>'c1',TIMESTAMP=>ts1,VERSION=>4}
get 't1','r1','c1'
get 't1','r1','c1','c2'
get 't1','r1',['c1','c2']


6、掃描所有資料
scan 'scores'
也可以指定一些修飾詞:TIMERANGE,FILTER,LIMIT,STARTROW,STOPROW,TIMESTAMP,MAXLENGTH,or COLUMNS.沒任何修飾詞,就是上邊例句,就會顯示所有資料行


scan '.META.'
scan '.META.',{COLUMNS=>'info:regioninfo'}
scan 't1',{COLUMNS=>['c1','c2'],LIMIT=>10,STARTROW=>'xyz'}
scan 't1',{COLUMNS=>'c1',TIMERANGE=>[1303668804,1303668904]}
scan 't1',{FILTER=>"(PrefixFilter('row2')AND(QualifierFilter(>=,'binary:xyz')))AND(TimestampsFilter(123,456))"}
scan 't1',{FILTER=>org.apache,hadoop,hbase.filter,ColumnPaginationFilter.new(1,0)}


7、刪除指定資料
delete 'scores','Jim','grade'
delete 'scores','JIm'
刪除資料命令也沒太多變化,只有一個:
delete 't1','r1','c1','ts1'
另外有一個deleteall命令,可以進行整行的範圍的刪除操作,慎用!
如果需要進行全表刪除操作,就使用truncate命令,其實沒有直接的全表刪除命令,這個命令也是disable,drop,create三個命令組合出來的。


8、修改表結構
disable 'scores'
alter 'scores',NAME=>'info'
enable 'scores'
alter命令使用如下(如果無法成功的版本,需要先通過表disable):
a、改變或新增一個列族
alter 't1',NAME=>'f1',VERSIONS=>5
b、刪除一個列族:
alter 't1',NAME=>'f1',METHOD=>'delete'
alter 't1','delete'=>'f1'


9、統計行數
>>count 't1'
>>count 't1',INTERVAL=>100000
>>count 't1',CACHE=>1000
>>count 't1',INTERVAL=>10,CACHE=>1000


count一般會比較耗時,使用MapReduce進行統計,統計結果會快取,預設是10行。統計間隔預設的是1000行(INTERVAL)


10、表的刪除
先禁用表 distable 'table'
刪除表 drop 'table'
------------------------
   客戶端API使用操作


|--------------------|--------------------------------|
|Java類              |    HBase資料模型               |
|--------------------|--------------------------------|
|HBaseAdmin          |    資料庫(DataBase)          |
|HBaseConfiguration  |                                |
|--------------------|--------------------------------|
|HTable              |    表(Table)                 |
|--------------------|--------------------------------|
|HTableDescriptor    |    列族(Column Family)       |
|--------------------|--------------------------------|
|Put                 |                                |
|Get                 |    列修飾符(Column Qualifier)|
|Scanner             |                                |
|--------------------|--------------------------------|


HBaseConfiguration
包名:org.apache.hadoop.hbase.HBaseConfiguration
作用: 對HBase進行配置
用法示例:
HBaseConfiguration hconfig = new HBaseConfiguration();
hconfig.set("hbase.zookeeper.property.clientPort","2181");
|--------|-----------------------------------------|------------------------------------------------------------------------|
|返回值  |  函式                                   |               描述                                                     |
|--------|-----------------------------------------|------------------------------------------------------------------------|
|void    |  addResource(Path file)                 |通過給定的路徑所指的檔案來新增資源                                      |
|--------|-----------------------------------------|------------------------------------------------------------------------|
|void    |  deal()                                 |清空所有設定的屬性                                                      | 
|--------|-----------------------------------------|------------------------------------------------------------------------|
|string  |  get(String name)                       |獲取屬性名對應的值                                                      |
|--------|-----------------------------------------|------------------------------------------------------------------------|
|String  |  getBoolean                             |獲取為boolean型別的屬性值,如果其屬性值型別部位boolean,則返回預設屬性值|
|--------|-----------------------------------------|------------------------------------------------------------------------|
|void    |  set(String name,String value)          |通過屬性名來設定值                                                      |
|--------|-----------------------------------------|------------------------------------------------------------------------|
|void    |  setBoolean(String name,boolean value)  |設定boolean型別的屬性值                                                 |
|--------|-----------------------------------------|------------------------------------------------------------------------|


HBaseAdmin
包名:org.apache.hadoop.hbase.client.HBaseAdmin
作用:提供了一個介面來管理HBase資料庫的表資訊。它提供的方法包括:建立表,刪除表,列出表項,使表有效或無效,以及新增或刪除表列族成員等。
用法示例:
HbaseAdmin admin = new HBaseAdmin(config);
admin.disableTable("tablename")


|------------------------|--------------------------------------------------------|-----------------------------------------------------|
|返回值                  |     函式                                               |  描述                                               |
|------------------------|--------------------------------------------------------|-----------------------------------------------------|
|void                    |  addColumn(String tableName,HColumnDescriptor column)  |  向一個已經存在的表新增列                           |
|                        |--------------------------------------------------------|-----------------------------------------------------|
|                        |  checkHBaseAvailable(HBaseConfiguration conf)          |  靜態函式,檢視HBase是否處於執行狀態|               |
|                        |--------------------------------------------------------|-----------------------------------------------------|
|| create Table(HTableDescriptor desc)                    | 建立一個表,同步操作                                |
|                        |--------------------------------------------------------|-----------------------------------------------------|
|| delete Table(byte[] tableName)                         | 刪除一個已經存在的表                                |
|                        |--------------------------------------------------------|-----------------------------------------------------|
|| enable Table(byte[] tableName)                         | 是表處於有效狀態                                    |
|                        |--------------------------------------------------------|-----------------------------------------------------|
|| disable Table(byte[] tableName)                        | 使表處於無效狀態                                    |
|------------------------|--------------------------------------------------------|-----------------------------------------------------|
|HTableDescription[]     |  list Tables()                                         |  列出所有使用者控制元件表項                               |
|------------------------|--------------------------------------------------------|-----------------------------------------------------|
|void                    |  modify Table(byte[] tableName,HTableDescriptor htd)   |  修改表的模式,是非同步的操作,可能需要花費一定的時間 |
|------------------------|--------------------------------------------------------|-----------------------------------------------------|
|boolean                 |  tableExists(String tableName)                         |  檢查表是否存在                                     |  
|------------------------|--------------------------------------------------------|-----------------------------------------------------|


HTableDescriptor
包名:org.apache.hadoop.hbase.HTableDescriptor
作用:包含了表的名字極其對應表的列族
用法示例:
HTableDescriptor htd = new HTableDescrptor(table);
htd.addFamily(new HcolumnDescriptor("family"));
|------------------|-----------------------------------|--------------|
|返回值            | 函式                              |  描述        |
|------------------|-----------------------------------|--------------|
|void              | addFamily(HColumnDescriptor)      | 新增一個列族 |
|------------------|-----------------------------------|--------------|
|HColumnDescriptor | removeFamily(byte[] column)       | 移除一個列族 |
|------------------|-----------------------------------|--------------|
|byte[]            | getName()                         | 獲取表的名字 |
|------------------|-----------------------------------|--------------|
|byte[]            | getValue(byte[] key)              | 獲取屬性的值 |
|------------------|-----------------------------------|--------------|
|void              | setValue(String key,String value) | 設定屬性的值 |
|------------------|-----------------------------------|--------------|


HColumnDescriptor
包名:org.apache.hadoop.hbase.HColumnDescriptor
作用:維護著關於列族的資訊,例如版本號,壓縮設定等。它通常在建立表或者為表新增列族的時候使用。列族被建立後不能直接修改,只能通過刪除然後重新建立的方式。列族被刪除的時候,列族裡面的資料也會同時被刪除。
用法示例:
HTableDescriptor htd = new HTableDescriptor(tablename);
HColumnDescriptor col = new HColumnDescriptor("content");
htd.addFamily(col);


|-------|-----------------------------------|------------------------|
|返回值 |  函式                             |        描述            |
|-------|-----------------------------------|------------------------|
|byte[] |  getName()                        |  獲取列族的名字        |
|-------|-----------------------------------|------------------------|
|byte[] |  getValue(byte[] key)             |  獲取對應的屬性的值    |
|-------|-----------------------------------|------------------------|
|void   |  setValue(String key,String value)|  設定對應屬性的值      |
|-------|-----------------------------------|------------------------|


HTable
包名:org.apache.hadoop.hbase.client.HTable
作用:可以用來和HBase表直接通訊。此方法對於更新操作來說是非執行緒安全的
用法示例:
HTable table = new HTable(conf,Bytes.toBytes(tablename));
ResultScanner scanner = table.getScanner(family);
|------------------|----------------------------------------------------------------------------|--------------------------------------------------| 
|返回值            |   函式                                                                     |        描述                                      |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|void              | checkAdnPut(byte[] row,byte[] family,byte[] qualifier,byte[] value,Put put)| 自動的檢查row/family/qualifier是否與給定值匹配   |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|void              | close()                                                                    | 釋放所有的資源或掛起內部緩衝中的更新             | 
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|Boolean           | exists(Get get)                                                            | 檢查Get例項所指定的值是否存在於HTable的列中      |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|Result            | get(Get get)                                                               | 獲取指定行的某些單元格所對應的值                 |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|byte[][]          | getEndKeys()                                                               | 獲取當前一開啟的表每個區域的結束鍵值             |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|ResultScanner     | getScanner(byte[] family)                                                  | 獲取當前給定列族的scanner例項                    |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|HtableDescriptor  | getTableDescriptor()                                                       | 獲取當前表的HTableDescriptor例項                 |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|byte[]            | getTableName()                                                             | 獲取表名                                         |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|
|static boolean    | isTableEnabled(HBaseConfiguration conf,String tableName)                   | 檢查表是否有效                                   |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------| 
|void              | put(Put put)                                                               | 向表中新增值                                     |
|------------------|----------------------------------------------------------------------------|--------------------------------------------------|


Put
包名:org.apache.hadoop.hbase.client.Put
作用:用來對單個行執行新增操作
用法示例:
Htable table = new HTable(conf.Bytes.toBytes(tablename));
Put p = new Put(brow);//為指定行建立一個Put操作
p.add(family.qualifier.value);
table.put(p);


|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|返回值              |         函式                                                                            |                  描述                               |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|void                |         checkAndPut(byte[] row,byte[] family,byte[] qualifier,byte[] value,Put put)     |自動的檢查row/family/qualifier是否與給定的值匹配     |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|void                |         close()                                                                         |釋放所有的資源或掛起內部緩衝區中的更新               |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|Boolean             |         exists(Get get)      exists(Get get)                                            |檢查Get例項所指定的值是否存在於HTable的列中          |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|Result              |         get(Get get)                                                                    |獲取指定行的某些單元格所對應的值                     |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|byte[][]            |         getEndKeys()                                                                    |獲取當前一開啟的表每個區域的結束鍵值                 |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|ResultScanner       |         getScanner(byte[] family)                                                       |獲取當前給定列族的scanner例項                        |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|HTableDescriptor    |         getTableDescriptor()                                                            |獲取當前表的HTableDescription例項                    |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|byte[]              |         getTableName()                                                                  |獲取表名                                             |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|static boolean      |         is TableEnabled(HBaseConfiguration conf,String tableName)                       |檢查表是否有效                                       |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|
|void                |         put(Put put)                                                                    |向表中新增值                                         |
|--------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------|


Get
包名:org.apache.hadoop.hbase.client.Get
作用:用來獲取單個行的相關資訊
用法示例:
HTable table = new HTable(conf,Bytes.toBytes(tablename));
Get g = new Get(Bytes.toBytes(row));
table.get(g);


|--------|-------------------------------------------|-----------------------------------|
|返回值  |函式                                       | 描述                              |
|--------|-------------------------------------------|-----------------------------------|
|Get     |addColumn(byte[] family,byte[] qualifier)  |獲取指定列族和列修飾符對應的列     |
|--------|-------------------------------------------|-----------------------------------|
|Get     |addFamily(byte[] family)                   |通過指定的列族獲取對應的所有列     |
|--------|-------------------------------------------|-----------------------------------|
|Get     |setTimeRange(long minStamp,long maxStamp)  |獲取指定取件的列的版本號           |
|--------|-------------------------------------------|-----------------------------------|
|Get     |setFilter(Filter filter)                   |當執行Get操作時設定伺服器端的過濾器|
|--------|-------------------------------------------|-----------------------------------|


Result
包名:org.apache.hadoop.hbase.client.Result
作用:儲存Get或者Scan操作後獲取表的單行值。使用此類提供的方法可以直接獲取值或者各種Map結構(key-value對)


|----------------------------|------------------------------------------------|-----------------------------------------------|
|返回值                      | 函式                                           |  描述                                         |
|----------------------------|------------------------------------------------|-----------------------------------------------|
|boolean                     | containsColumn(byte[] family,byte[] qualifier) |  檢查指定的列是否存在                         |
|----------------------------|------------------------------------------------|-----------------------------------------------|
|NavigableMap<byte[],byte[]> | getFamilyMap(byte[] family)                    |  獲取對應列族所包含的修飾符與值的鍵值對       |
|----------------------------|------------------------------------------------|-----------------------------------------------|
|byte[]                      | getValue(byte[] family,byte[] qualifier)       |  獲取對應列的最新值                           |
|----------------------------|------------------------------------------------|-----------------------------------------------|


ResultScanner
包名:org.apache.hadoop.hbase.client.ResultScanner
作用:儲存Get或者Scan操作後獲取表的單行值。使用此類提供的方法可以直接獲取值或者各種Map結構(key-value對)


|--------|---------|----------------------------------|
|返回值  |函式     |      描述                        |
|--------|---------|----------------------------------|
|void    |close()  |   關閉scanner並釋放分配給它的資源|
|--------|---------|----------------------------------|
|Result  |next()   |   獲取下一行的值                 |
|--------|---------|----------------------------------|


HTablePool
包名:org.apache.hadoop.hbase.client.HTablePool
作用:可以解決HTable存在的執行緒不安全問題,同時通過維護固定數量的HTable物件,能夠在程式執行期間複用這些HTable資源物件
說明:
1、HTablePool可以自動建立HTable物件,而且對客戶端來說使用上是完全透明的,可以避免多執行緒間資料併發修改問題。
2、HTablePool中的HTable物件之間是公用Configuration連線的,能夠可以減少網路開銷。
HTablePool的使用很簡單:每次進行操作前,通過HTablePool的getTable方法HTabelPool的putTable方法將HTable物件放回到TablePool中。


------------------------------------------------------------------------------------------------------------------
create 'students_age','f1'
-------------------------建立表程式-----------------------------------------------------------------------------------------
package com.hbase;


import java.io.IOException;
import java.util.LinkedList;
import java.util.List;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HConnection;
import org.apache.hadoop.hbase.client.HConnectionManager;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.compress.Compression.Algorithm;
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
import org.apache.hadoop.hbase.util.Bytes;


public class HbaseConnection{
    private String rootDir;
    private String zkServer;
    private String port;


    private Configuration conf;
    private HConnection hConn = null;
    public HbaseConnection(String rootDir,String zkServer,String port){
        this.rootDir = rootDir;
this.zkServer = zkServer;
this.port = port;
        conf = HBaseConfiguration.create();
conf.set("hbase.rootdir",rootDir);
conf.set("hbase.zookeeper.quorum",zkServer);
conf.set("hbase.zookeeper.property.clientPort",port);
try{
   hConn = HConnectionManager.createConnection(conf);
}catch(IOException e){
   e.printStackTrace();
}
    }
    public void createTable(String tableName,List<String> cols){
        try{
   HBaseAdmin admin = new HBaseAdmin(conf);
   if(admin.tableExists(tableName))
       throw new IOException("table exists");
   else{
       HTableDescriptor tableDesc = new HTableDescriptor(tableName);
for(String col : cols){
   HColumnDescriptor colDesc = new HColumnDescriptor(col);
   colDesc.setCompressionType(Algorithm.GZ);
   colDesc.setDataBlockEncoding(DataBlockEncoding.DIFF);
   tableDesc.addFamily(colDesc);
}
   admin.createTable(tableDesc);
}


   }catch(MasterNotRunningException e){
       e.printStackTrace();
   }catch(ZooKeeperConnectionException e){
       e.printStackTrace();
   }catch(IOException e){
       e.printStackTrace();
   }
 
}


    public void saveData(String tableName,List<Put> puts){
    try{
       HTableInterface table = hConn.getTable(tableName);
       table.put(puts);
       table.setAutoFlush(false);
       table.flushCommits();
    }catch(IOException e){
       e.printStackTrace();
    }
    }


    public Result getData(String tableName,String rowkey){
        try{
   HTableInterface table = hConn.getTable(tableName);
   Get get = new Get(Bytes.toBytes(rowkey));
   return table.get(get);
}catch(IOException e){
   e.printStackTrace();
}
        
        return null;
    }
    
    public void format(Result result){
        String rowkey = Bytes.toString(result.getRow());
        KeyValue[] kvs = result.raw();
for(KeyValue kv: kvs){
   String family = Bytes.toString(kv.getFamily());
   String qualifier = Bytes.toString(kv.getQualifier());
   System.out.println("rowkey->" + rowkey + "family->" + family + "qualifier->" + qualifier);
}
    }
    
    public void hbaseScan(String tableName){
        Scan scan = new Scan();
scan.setCaching(1000);
try{
   HTableInterface table = hConn.getTable(tableName);
   ResultScanner scanner = table.getScanner(scan);
   for(Result res: scanner){
       format(res)
   }
}catch(IOException e){
   e.printStackTrace();
}
    }


    public void filterTest(String tableName){
        Scan scan = new Scan():
scan.setCaching(1000);
RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,
///new BinaryComparator(Bytes.tobytes("Jack")));
new RegexStringComparator("J\\w+")));


PageFilter filter = new PageFilter(15);//分頁顯示
scan.setFilter(filter);
try{
   HtableIntegerface table = hConn.getTable(tableName);
   ResultScanner scanner = table.getScanner(scan);


   for(Result res: scanner){
       format(res);
   }
}catch(IOException e){
   e.printStackTrace();
}
    }




    public void pageFilterTest(String tableName){
        PageFilter filter = new PageFilter(4);
byte[] lastRow = null;
int pageCount = 0;
try{
   HtableInterface table = hConn.getTable(tableName);
   while(++pageCount > 0){
       System.out.println("pageCount = " + pageCount);
       Scan scan = new Scan();
scan.setFilter(filter);
       if(lastRow != null){
   scan.setStartRow(lastRow);
}
ResultScanner scanner = table.getScanner(scan);
for(Result res: scanner){
   format(res);
   lastRow = res.getRow();
   if(++count > 3)
       break;
   format(res);
}
if(count < 3)
   break;

   }
}catch(IOException e){
   e.printStackTrace();
}



    }


    public static void main(String[] args){
        String rootDir = "hdfs://hbase";
String zkServer = "192.168.1.198";
String port = "2181";
HbaseConnection conn = new HbaseConnection(rootDir,zkServer,port);
/*List<String> cols = new LinkedList<>();
cols.add("basicInfo");
cols.add("moreInfo");
conn.createTable("students",cols);*/


        List<Put> puts = new LinkedList<Put>();
Put put1 = new Put(Bytes.toBytes("Tom"));
put1.add(Bytes.toBytes("basicInfo"),Bytes.toBytes("age"),Bytes.toBytes("27"));
                put1.add(Bytes.toBytes("moreInfo"),Bytes.toBytes("tel"),Bytes.toBytes("11232"));
                
Put put2 = new Put(Bytes.toBytes("Jim"));
put2.add(Bytes.toBytes("basicInfo"),Bytes.toBytes("age"),Bytes.toBytes("28"));
                put2.add(Bytes.toBytes("moreInfo"),Bytes.toBytes("tel"),Bytes.toBytes("11233"));
        puts.add(put1);
        puts.add(put2);
conn.saveData("students",puts);
Result result = conn.getData("students","Tom");
conn.format(result);


conn.hbaseScan("studnets");
conn.filterTest("students");
    }
}
-------------------------------------------------------------------------------------------------------------------------  




machine


1、公網ip
   內網ip




2-4 內網ip


log4j.properties
log4j.rootLogger = info,stdout,hbase
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%n


log4j.appender.hbase = org.apache.log4j.DailyRollingFileAppender
log4j.appender.hbase.File = ./log.log
log4j.appender.hbase.Append = true
log4j.appender.hbase.layout = org.apache.log4j.PatternLayout
log4j.appender.hbase.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] - [%p] %m%n


---------------------------------------------------------------------------------------------------------
HBase 掃描器
Scanner掃描器
Hbase在掃描資料的時候,使用scanner表掃描器。
HTable通過一個Scan例項,呼叫getScanner(scan)來獲取掃描器。可以配置掃描起止位,以及其他的過濾條件。


通過迭代器返回查詢結果,使用起來雖然不是很方便,不過並不複雜。但是這裡有一點可能被忽略的地方,就是返回的scanner迭代器,每次呼叫next的獲取下一條記錄的時候,預設配置下會訪問一次RegionServer。這在網路不是很好的情況下,對效能的影響是很大的。
建議配置掃描器快取。






掃描器使用
掃描器快取


hbase.client.scanner.caching配置項可以設定HBase scanner一次從服務端抓取的資料條數,預設情況下一次一條。通過將其設定成一個合理的值,可以減少scan過程中next()的而時間開銷,代價是scanner需要通過客戶端的記憶體來維持這些被cache的行記錄。


有三個地方可以進行配置:
1)在HBase的conf配置檔案中進行配置
2)通過呼叫HTable.setScannerCaching(int scannerCaching)進行配置
3)通過呼叫Scan.setCaching(int caching)進行配置。三者的優先順序越來越高。


Hbase過濾器
過濾器簡介
1、使用過濾器可以提高操作表的效率,HBase中兩種資料讀取函式get()和scan()都支援過濾器,支援直接訪問和通過指定起止行鍵來訪問,但是缺少細粒度的篩選功能,如基於正則表示式對鍵或值進行篩選的功能。
2、可以使用預定義好的過濾器或者是實現自定義過濾器
3、過濾器在客戶端建立,通過RPC傳送到伺服器端,在伺服器端執行過濾操作,把資料返回給客戶端


scan 'studnets',{STARTROW=>'J',ENDROW=>'K'}


過濾器:
1、Comparsion Filter(比較過濾器)
RowFilter
FamilyFilter
QualifierFilter
ValueFilter
DependentColumnFilter


2、Dedicated Filter(專用過濾器)
SingleColumnValueFilter
SingleColumnValueExcluderFilter
PrefixFilter
PageFilter
KeyOnlyFilter
FirstKeyOnlyFilter
TimestampsFilter
RandomRowFilter


3、Decorating Filter(附加過濾器)
SkipFilter
WhileMatchFilters




HBase協處理器


HBase作為列資料庫最經常被人的特性包括:
無法輕易建立“二級索引”,難以執行求和、計數、排序等操作。


比如,在舊版本的(<0.92)HBase中,統計資料表的總行數,需要使用Counter方法,執行一次MapReduce Job才能得到。雖然HBase在資料儲存層中集成了MapReduce,能夠有效用於資料表的分散式計算。
然而在很多情況下,做一些簡單的相加或者聚合計算的時候,如果直接將計算過程放置在server端,能夠減少通訊開銷,從而獲得很好的效能提升。於是,HBase在0.92以後引入了處理器(coprocessors),
實現了一些激動人心的新特性:能夠輕易建立二次索引、複雜過濾器以及訪問控制等。


HBase協處理器的靈感來自於JEFFDean 09年的演講。它根據該演講實現了類似於bigtable的協處理器,包括以下特性:
1)每個表伺服器的任意子表都可以執行程式碼
2)客戶端的高層呼叫介面(客戶端能夠直接訪問資料表的行地址,多行讀寫會自動分片成多個並行的RPC呼叫)
3)提供一個非常靈活的、可用於建立分散式服務的資料模型
4)能夠自動化擴充套件、負載均衡、應用請求路由
    HBase的協處理器靈感來自bigtable,但是實現細節不盡相同。HBase建立一個框架,它為使用者提供類庫和執行時環境,使得他們的程式碼能夠在HBase region server和master上處理。
    
協處理器分兩種型別,系統協處理器可以全域性匯入region servre上的所有資料表,表協處理器即是使用者可以指定一張表使用協處理器。
協處理器框架為了更好支援其行為的靈活性,提供了兩個不同方面的外掛。一個觀察者(observer),類似於關係資料庫的觸發器。另一個是終端(endpoint),動態的終端有點像儲存過程。




Observer
觀察者的設計意圖是允許使用者通過程式碼來過載處理器框架的upcall方法,而具體的事件觸發的callback方法有HBase的核心程式碼來執行。處理器框架處理所有的callback呼叫細節,協處理器自身只需要插入新增或者改變的功能。
以Hbase0.92版本為例,它提供了三種觀察者介面:


RegionObserver:提供客戶端的資料操縱事件鉤子:Get、Put、Delete、Scan等。
WALObserver:提供WAL相關操作鉤子。
MasterObserver:提供DDL-型別的操作鉤子。如建立、刪除、修改資料表等。
這些介面可以同時使用在同一個地方,按照不同優先順序順序執行,使用者可以任意基於協調處理器實現複雜的HBase功能層。HBase有很多種事件可以觸發觀察者方法,這些事件與方法從HBase0.92版本起,都會整合在HBase API中。不過這些API可能會由於各種原因有所改動,不同版本的介面改動比較大。
-----------------------------------------------------------------
EndPoint
終端是動態RPC外掛的介面,它的實現程式碼被安裝在伺服器端,從而能夠通過HBase RPC喚醒。客戶端類庫提供了非常方便的方法來呼叫這些動態介面,它們可以在任意時候呼叫一個終端,它們的實現程式碼會被目標region遠端執行,結果會返回到終端。
使用者可以結合使用這些強大的外掛介面,為HBase新增全新的特性。終端的使用,如下面流程所示:
定義一個新的protocol介面,必須繼承CoprocessorProtocol。
實現終端介面,該實現會被匯入region環境執行。
繼承抽象類BaseEndpointCoprocessor。
在客戶端,終端可以被兩個新的Hbase Client API呼叫。單個region:
HTableInterface.coprocessorProxy(Class<T> protocol,byte[] row).regions區域:HTableInterface.coprocessorExec(Class<T> protocol,byte[] startkey,byte[] endKey,Batch.Call<T,R> callable)


有三個方法對Endpoint進行設定:
A.啟動全域性aggregation,能過操縱所有的表上的資料。通過修改hbase-site。xml這個檔案來實現,只需要新增如下程式碼:
<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.RowCountEndpoint</value>
</property>


B.啟動表aggregation,只對特定的表生效。通過HBase Shell來實現。
(1)disable指定表。
hbase>> disable 'students' 
(2)新增aggregation hbase>> alter ‘students’,METHOD =>'table_att','coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.RowCountEndpoint||'
alter ‘students’,'coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.example.RowCountEndpoint||'


協處理器命令:
增加協處理器方法一:alter 'students','coprocessor'=>'|org.apache.hadoop.hbase.coprocessor.example.RowCountEndpoint||'
-----------------------------------------------------------------------------------------------------------------------------------------------------
增加協處理器方法二:


package coprocessor;
import java.io.IOException;
import java.util.List;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
import org.apache.hadoop.hbase.util.Bytes;


public class RegionObserverTest extends BaseRegionObserver{
private static byte[] fixed_rowkey = Bytes.toBytes("John");


@Override
public void preGet(ObserverContext<RegionCoprocessorEnvironment> c,
Get get, List<KeyValue> result) throws IOException {
// TODO Auto-generated method stub
if(Bytes.equals(get.getRow(), fixed_rowkey)){
KeyValue kv = new KeyValue(get.getRow(),Bytes.toBytes("time"),Bytes.toBytes("time"),Bytes.toBytes(System.currentTimeMillis()));
result.add(kv);
}
}
}


alter 'students','coprocessor'=>'hdfs://192.168.1.198:8020/coprocessor.jar|coprocessor.RegionObserverTest||'
enable 'students'


java -cp .:/usr/lib/hbase/lib/* HbaseConnection


備註:程式打包,上傳到hdfs根目錄下,執行alter。


----------------------------------------------------------------------------------------------------------------------------------------------------------


enable 'students'
describe 'students'
刪除協處理器
alter 'students',METHOD => 'table_att_unset',NAME =>'coprocessor$1'




sudo jar tf /usr/lib/hbase/lib/hbase-examples-1.0.0-cdh5.5.0.jar | grep RowCountEndpoint


org/apache/hadoop/hbase/coprocessor/example/RowCountEndpoint.class


hadoop fs -put coprocessor.jar /




javac -cp /home/cloudera/softback/hbase-0.96.2-hadoop2/lib/* HbaseConnection.java
java -cp /usr/lib/hbase/lib/* HbaseConnection




(3)重啟指定表hbase > enable 'mytable' 


C.API呼叫
HTableDescriptor htd = new HTableDescriptor("testTable");
htd.setValue("CORPROCESSOR$1",path.toString + "|" + RowCountEndpoint.class.getCanonicalName() + "|" + Coprocessor.Priority.USER);
---------------------------------------------------------
CoprocessorRowCounter.java


public class CoprocessorRowCounter{
    public static void main(String[] args) throws IOException{
        Configuration conf = HbaseConfiguration.create();
        HTable table = new HTable(conf,"students");
final ExampleProtos.CountRequest request = ExampleProcess.CountRequest.getDefaultInstance();
Map<byte[],Long> results = table.coprocessorService(ExampleProtos.RowCountService.class,null,null,new Batch.Call<ExampleProtos.RowCountService,Long>(){
   public Long call(ExampleProtos.RowCountService counter) throws IOException{
       ServerRpcController controller = new ServerRpcController();
BlockingRpcCallback<ExamplerProtos.CountResponse>();
       counter.getRowCount(controller,request,rpcCallback);
ExampleProtos.CountResponse response  = rpcCallback.get();
if(controller.failedOnException()){
   throw controller.getFailedOn();
}
return (response != null && response.hasCount())?response.getCount():0;
   }
});
    }


}


幾點說明:
1、協調處理器配置的載入順序:先載入配置檔案中定義的協處理器,後加載表描述符中的協處理器
2、COPROCESSOR$<number>中的number定義了載入的順序
3、協處理器配置格式
Coprocess can also be configured to load  on a per table basis,via a shell command “alter”
hbase > alter "t1".METHOD => 'table_alt'
'coprocessor1'=>'hdfs://foo.jar|com.foo.FooRegionObserver[100]arg1=1,arg2=2'


RegionObserverTest.java


import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
public class RegionObserverTest extends BaseRegionObserver{
    
}


>>describe 'students'


alter 'students',METHOD=>'table_att_unset',Name=>'coprocessor$1'


scan 'students'


---------------------------------------------------------------------------
MapReduce on HBase


MapReduce on Hbase
1、可以使用Mapreduce的方法操作hbase資料庫
2、Hadoop Mapreduce 提供相關API,可以與hbase資料庫無縫連線
3、API link: http://hbase.apache.org/devapidocs/index.html


--------------------HbaseMR.java---------------------------------------------------------------------------------
package com.hbase;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Mutation;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;


public class HbaseMR {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException{
        Configuration conf = HBaseConfiguration.create();
        Job job = new Job(conf,"mapreduce on hbase");
        job.setJarByClass(HbaseMR.class);
        Scan scan = new Scan();
        scan.setCaching(1000);
        
        
        TableMapReduceUtil.initTableMapperJob("students", scan,MyMapper.class, Text.class, Text.class, job);
        TableMapReduceUtil.initTableReducerJob("students_age",MyReducer.class, job);
        
        job.waitForCompletion(true);
        
    }
}




class MyMapper extends TableMapper<Text,Text>{
@Override
protected void map(
ImmutableBytesWritable key,
Result value,
Context context)
throws IOException, InterruptedException {
Text k = new Text(Bytes.toString(key.get()));
Text v = new Text(value.getValue(Bytes.toBytes("basicInfo"),Bytes.toBytes("age")));

context.write(v, k);
}
}


class MyReducer extends TableReducer<Text,Text,ImmutableBytesWritable>{


@Override
protected void reduce(
Text key,
Iterable<Text> values,
Context context)
throws IOException, InterruptedException {
Put put = new Put(Bytes.toBytes(key.toString()));

for(Text value: values){
put.add(Bytes.toBytes("f1"),Bytes.toBytes(value.toString()),Bytes.toBytes(value.toString()));
}
context.write(null, put);
}
}
------------------------------------------------------------------------------------------------------


資料儲存格式
B+樹
特點:
1、有n棵子數的結點中含有n個關鍵字,每個關鍵字不儲存資料,只用來索引,所有資料都儲存在葉子節點。
2、所有的葉子結點中包含了全部關鍵字的資訊,及指向含這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大順序連結。
3、所有的非終端結點可以看成是索引部分,結點中僅含其子樹(根結點)中的最大(或最小)關鍵字。


HFile格式
1、資料塊-儲存表中的資料,每一個數據塊由塊頭和一些keyValue(record)組成,key的值是嚴格按照順序儲存的。塊大小預設為64K(由建表時建立cf時指定或者HColumnDescriptor.setBlockSize(size)),
這一部分可以壓縮儲存。在查詢資料時,是以資料塊為單位從硬碟load到記憶體。查詢資料時,是順序的遍歷該塊中的keyValue對。
2、元資料塊(可選的)-儲存使用者自定義的kv對,可以被壓縮。比如booleanfilter就是存在元資料塊中的,該塊只保留value值,key值儲存在元資料索引塊中。每一個元資料塊由塊頭和value值組成。可以
快速判斷key是都在這個HFile中。
3、File Info-Hfile的元資訊,不被壓縮,使用者也可以在這一部分新增自己的元資訊。
4、資料索引塊-Data Block的索引,每條索引的key是被索引的block的第一條記錄的key(格式為:頭資訊,資料塊offset資料塊大小塊第一個記錄的key,.....)


----------------------------------------------------------------------------------------------------
WAL機制
WAL預寫日誌
1)Client向RegionServer端提交資料的時候,會優先寫WAL日誌(HLog),只有當WAL日誌寫成功以後,Client才會被告訴提交資料成功,如果寫WAL失敗會告知客戶端提交失敗
2)一個RegionServer上所有的Region都共享一個HLog,一次資料的提交是先寫WAL,再寫memstore


HLog類
實現了WAL的類叫做HLog。當HRegion被例項化時,HLog例項會被當做一個餐所以和到HRegion的構造器中。當一個Region接收到一個更新操作時,它可以直接把資料儲存到一個共享的WAL例項中去。




HLogKey類
1、當前的WAL使用的是Hadoop的SequenceFile格式,其key是HLogKey例項。HLogKey中記錄了寫入資料的歸屬資訊,除了table和region名字外,同時還包括sequence number和timestamp,timestamp是“寫入時間”,
sequence number的起始值為0,或者是最近一次存入檔案系統中sequence number。
2、HLog Sequence File的Value是Hbase的KeyValue物件,即對應HFile中的KeyValue


WALEdit類
客戶端傳送的每個修改都會封裝成WALEdit類,一個WALEdit類包含了多個更新操作,可以說一個WALEdit就是一個原子操作,包含若干個操作的集合。




LogSyncer類
Table在建立的時候,有一個引數可以設定,是否每次寫Log日誌都需要往叢集裡的其他機器同步一次,預設是每次都同步,同步的開銷是比較大的,但不及時同步又可能因為機器宕而丟日誌。
同步的操作現在是通過Pipeline的方式來實現的,Pipeline是指datanode接受資料後,再傳給另外一臺datanode,是一種序列的方式;n-Way Wirtess是指多datanode同時接受資料,最慢的一臺結束就是整個結束。
差別在於一個延遲大,一個併發高,hdfs現在正在開發中,以便可以選擇是按Pipeline還是n-Way Write來實現寫操作。


Table如果設定每次不同步,則寫操作會被RegionServer快取,並啟動一個LogSyncer執行緒來定時同步日誌,定時時間預設是一秒也是由hbase.regionserver.optionallogflushinterval設定。


LogRoller類
1、日誌寫入的大小是有限制的。LogRoller類會作為一個後臺執行緒執行,在特定的時間間隔內滾動日誌。通過hbase.regionserver.logroll.period屬性控制,預設1小時。
---------------------------------------------------------
Hbase線上資料備份


Hbase Replication
HBase複製是一種不同HBase部署中複製資料的方法。它可以作為一種故障恢復的方法,並提供HBase層次的高可用性。


HBase複製中最基本的架構模式是“主推送”(master-push),因為每個region server都有自己的WAL(或HLog),所以很容易儲存現在正在複製的位置。正如眾所周知的解決方案-MySql的主/從複製,只使用二進位制
檔案來跟蹤修改。一個主叢集可以將資料複製到任意數目的從叢集,每個region server都會參與複製自己的修改。
來自每個region server的HLog是Hbase複製的基礎,並且只要它們需要將資料複製到從叢集,它們就必須被儲存到HDFS上。每個region server從它需要的最老的日誌開始複製,同時在zookeeper中儲存當前恢復的位置
來簡化錯誤恢復。每個從叢集恢復的位置可能不同,但它們處理的HLog佇列內容是相