HBase是Hadoop的數據庫,可以對大數據提供隨機、實時讀寫訪問。他是開源的,分佈式的,多版本的,面向列的,存儲模型。數據庫
在講解的時候我首先給你們講解一下HBase的總體結構,以下圖:數組
HBase Master是服務器負責管理全部的HRegion服務器,HBase Master並不存儲HBase服務器的任何數據,HBase邏輯上的表可能會劃分爲多個HRegion,而後存儲在HRegion Server羣中,HBase Master Server中存儲的是從數據到HRegion Server的映射。緩存
一臺機器只能運行一個HRegion服務器,數據的操做會記錄在Hlog中,在讀取數據時候,HRegion會先訪問Hmemcache緩存,若是 緩存中沒有數據纔回到Hstore中上找,沒一個列都會有一個Hstore集合,每一個Hstore集合包含了不少具體的HstoreFile文件,這些文 件是B樹結構的,方便快速讀取。服務器
再看下HBase數據物理視圖以下:dom
Row Key | Timestamp | Column Family | |
URI | Parser | ||
r1 | t3 | url=http://www.taobao.com | title=每天特價 |
t2 | host=taobao.com | ||
t1 | |||
r2 | t5 | url=http://www.alibaba.com | content=天天… |
t4 | host=alibaba.com |
Ø Row Key: 行鍵,Table的主鍵,Table中的記錄按照Row Key排序異步
Ø Timestamp: 時間戳,每次數據操做對應的時間戳,能夠看做是數據的version number分佈式
Ø Column Family:列簇,Table在水平方向有一個或者多個Column Family組成,一個Column Family中能夠由任意多個Column組成,即Column Family支持動態擴展,無需預先定義Column的數量以及類型,全部Column均以二進制格式存儲,用戶須要自行進行類型轉換。函數
瞭解了HBase的體系結構和HBase數據視圖夠,如今讓咱們一塊兒看看怎樣經過Java來操做HBase數據吧!oop
先說說具體的API先,以下性能
HBaseConfiguration是每個hbase client都會使用到的對象,它表明的是HBase配置信息。它有兩種構造方式:
public HBaseConfiguration()
public HBaseConfiguration(final Configuration c)
默認的構造方式會嘗試從hbase-default.xml和hbase-site.xml中讀取配置。若是classpath沒有這兩個文件,就須要你本身設置配置。
Configuration HBASE_CONFIG = new Configuration();
HBASE_CONFIG.set(「hbase.zookeeper.quorum」, 「zkServer」);
HBASE_CONFIG.set(「hbase.zookeeper.property.clientPort」, 「2181″);
HBaseConfiguration cfg = new HBaseConfiguration(HBASE_CONFIG);
建立表
建立表是經過HBaseAdmin對象來操做的。HBaseAdmin負責表的META信息處理。HBaseAdmin提供了createTable這個方法:
public void createTable(HTableDescriptor desc)
HTableDescriptor 表明的是表的schema, 提供的方法中比較有用的有
setMaxFileSize,指定最大的region size
setMemStoreFlushSize 指定memstore flush到HDFS上的文件大小
增長family經過 addFamily方法
public void addFamily(final HColumnDescriptor family)
HColumnDescriptor 表明的是column的schema,提供的方法比較經常使用的有
setTimeToLive:指定最大的TTL,單位是ms,過時數據會被自動刪除。
setInMemory:指定是否放在內存中,對小表有用,可用於提升效率。默認關閉
setBloomFilter:指定是否使用BloomFilter,可提升隨機查詢效率。默認關閉
setCompressionType:設定數據壓縮類型。默認無壓縮。
setMaxVersions:指定數據最大保存的版本個數。默認爲3。
一個簡單的例子,建立了4個family的表:
HBaseAdmin hAdmin = new HBaseAdmin(hbaseConfig);
HTableDescriptor t = new HTableDescriptor(tableName);
t.addFamily(new HColumnDescriptor(「f1″));
t.addFamily(new HColumnDescriptor(「f2″));
t.addFamily(new HColumnDescriptor(「f3″));
t.addFamily(new HColumnDescriptor(「f4″));
hAdmin.createTable(t);
刪除表
刪除表也是經過HBaseAdmin來操做,刪除表以前首先要disable表。這是一個很是耗時的操做,因此不建議頻繁刪除表。
disableTable和deleteTable分別用來disable和delete表。
Example:
HBaseAdmin hAdmin = new HBaseAdmin(hbaseConfig);
if (hAdmin.tableExists(tableName)) {
hAdmin.disableTable(tableName);
hAdmin.deleteTable(tableName);
}
查詢數據
查詢分爲單條隨機查詢和批量查詢。
單條查詢是經過rowkey在table中查詢某一行的數據。HTable提供了get方法來完成單條查詢。
批量查詢是經過制定一段rowkey的範圍來查詢。HTable提供了個getScanner方法來完成批量查詢。
public Result get(final Get get)
public ResultScanner getScanner(final Scan scan)
Get對象包含了一個Get查詢須要的信息。它的構造方法有兩種:
public Get(byte [] row)
public Get(byte [] row, RowLock rowLock)
Rowlock是爲了保證讀寫的原子性,你能夠傳遞一個已經存在Rowlock,不然HBase會自動生成一個新的rowlock。
Scan對象提供了默認構造函數,通常使用默認構造函數。
Get/Scan的經常使用方法有:
addFamily/addColumn:指定須要的family或者column,若是沒有調用任何addFamily或者Column,會返回全部的columns.
setMaxVersions:指定最大的版本個數。若是不帶任何參數調用setMaxVersions,表示取全部的版本。若是不掉用setMaxVersions,只會取到最新的版本。
setTimeRange:指定最大的時間戳和最小的時間戳,只有在此範圍內的cell才能被獲取。
setTimeStamp:指定時間戳。
setFilter:指定Filter來過濾掉不須要的信息
Scan特有的方法:
setStartRow:指定開始的行。若是不調用,則從表頭開始。
setStopRow:指定結束的行(不含此行)。
setBatch:指定最多返回的Cell數目。用於防止一行中有過多的數據,致使OutofMemory錯誤。
ResultScanner是Result的一個容器,每次調用ResultScanner的next方法,會返回Result.
public Result next() throws IOException;
public Result [] next(int nbRows) throws IOException;
Result表明是一行的數據。經常使用方法有:
getRow:返回rowkey
raw:返回全部的key value數組。
getValue:按照column來獲取cell的值
Example:
Scan s = new Scan();
s.setMaxVersions();
ResultScanner ss = table.getScanner(s);
for(Result r:ss){
System.out.println(new String(r.getRow()));
for(KeyValue kv:r.raw()){
System.out.println(new String(kv.getColumn()));
}
}
插入數據
HTable經過put方法來插入數據。
public void put(final Put put) throws IOException
public void put(final List puts) throws IOException
能夠傳遞單個批Put對象或者List put對象來分別實現單條插入和批量插入。
Put提供了3種構造方式:
public Put(byte [] row)
public Put(byte [] row, RowLock rowLock)
public Put(Put putToCopy)
Put經常使用的方法有:
add:增長一個Cell
setTimeStamp:指定全部cell默認的timestamp,若是一個Cell沒有指定timestamp,就會用到這個值。若是沒有調用,HBase會將當前時間做爲未指定timestamp的cell的timestamp.
setWriteToWAL: WAL是Write Ahead Log的縮寫,指的是HBase在插入操做前是否寫Log。默認是打開,關掉會提升性能,可是若是系統出現故障(負責插入的Region Server掛掉),數據可能會丟失。
另外HTable也有兩個方法也會影響插入的性能
setAutoFlash: AutoFlush指的是在每次調用HBase的Put操做,是否提交到HBase Server。默認是true,每次會提交。若是此時是單條插入,就會有更多的IO,從而下降性能.
setWriteBufferSize: Write Buffer Size在AutoFlush爲false的時候起做用,默認是2MB,也就是當插入數據超過2MB,就會自動提交到Server
Example:
HTable table = new HTable(hbaseConfig, tableName);
table.setAutoFlush(autoFlush);
List lp = new ArrayList();
int count = 10000;
byte[] buffer = new byte[1024];
Random r = new Random();
for (int i = 1; i <= count; ++i) {
Put p = new Put(String.format(「row%09d」,i).getBytes());
r.nextBytes(buffer);
p.add(「f1″.getBytes(), null, buffer);
p.add(「f2″.getBytes(), null, buffer);
p.add(「f3″.getBytes(), null, buffer);
p.add(「f4″.getBytes(), null, buffer);
p.setWriteToWAL(wal);
lp.add(p);
if(i%1000==0){
table.put(lp);
lp.clear();
}
}
刪除數據
HTable 經過delete方法來刪除數據。
public void delete(final Delete delete)
Delete構造方法有:
public Delete(byte [] row)
public Delete(byte [] row, long timestamp, RowLock rowLock)
public Delete(final Delete d)
Delete經常使用方法有
deleteFamily/deleteColumns:指定要刪除的family或者column的數據。若是不調用任何這樣的方法,將會刪除整行。
注意:若是某個Cell的timestamp高於當前時間,這個Cell將不會被刪除,仍然能夠查出來。
Example:
HTable table = new HTable(hbaseConfig, 「mytest」);
Delete d = new Delete(「row1″.getBytes());
table.delete(d)
切分表
HBaseAdmin提供split方法來將table 進行split.
public void split(final String tableNameOrRegionName)
若是提供的tableName,那麼會將table全部region進行split ;若是提供的region Name,那麼只會split這個region.
因爲split是一個異步操做,咱們並不能確切的控制region的個數。
Example:
public void split(String tableName,int number,int timeout) throws Exception {
Configuration HBASE_CONFIG = new Configuration();
HBASE_CONFIG.set(「hbase.zookeeper.quorum」, GlobalConf.ZOOKEEPER_QUORUM);
HBASE_CONFIG.set(「hbase.zookeeper.property.clientPort」, GlobalConf.ZOOKEEPER_PORT);
HBaseConfiguration cfg = new HBaseConfiguration(HBASE_CONFIG);
HBaseAdmin hAdmin = new HBaseAdmin(cfg);
HTable hTable = new HTable(cfg,tableName);
int oldsize = 0;
t = System.currentTimeMillis();
while(true){
int size = hTable.getRegionsInfo().size();
logger.info(「the region number=」+size);
if(size>=number ) break;
if(size!=oldsize){
hAdmin.split(hTable.getTableName());
oldsize = size;
} else if(System.currentTimeMillis()-t>timeout){
break;
}
Thread.sleep(1000*10);
}
}