原文:http://blog.csdn.net/guxch/article/details/12163047
-----------------------------------------------------------------------------------
一、概述
Hbase是目前比較火的列存儲數據庫,由于Hbase是用Java寫的,因此它原生地提供了Java接口,對非Java程序人員,怎么辦呢?幸好它提供了thrift接口服務器,因此也可以采用其他語言來編寫Hbase的客戶端,本文即是Hbase C++接口的介紹。目前的Hbase(0.94.11,本文即基于此版本)有兩套thrift接口(可以叫thrift1和thrift2),它們并不兼容(隨意性太強,這可能是所有開源軟件都具有的問題)。根據官方文檔,thrift1很可能被拋棄,但網上的文章基本是介紹thrift1的,本文則主要介紹thrift2。
要使用Hbase的thrift接口,必須將它的服務啟動,命令行為:
thrift默認的監聽端口是9090,可以用netstat -nl | grep 9090看看該端口是否有服務。
二、thrift1與thrift2的簡單比較
兩個版本的thrift文件位于如下位置,thrift1的文件有24K左右,而thrift2只有12K左右,看來新版做了大量的簡化。
命名空間上,新版都將thrift改為thrift2,以示區別。下表是thrift和thrift2的區別,可以看出,二者真的差別挺大,特別是服務中的方法,thrift2做了簡化與合成,并把DDL有關的內容去掉了,關于這些結構、服務的具體意義,請參閱thrift文件中的注釋,下文將詳細列出。
? | Thrift | Thrift2 |
結構 | struct TCell struct ColumnDescriptor struct TRegionInfo struct Mutation struct BatchMutation struct TIncrement struct TColumn struct TRowResult struct TScan | struct TTimeRange struct TColumn struct TColumnValue struct TColumnIncrement struct TResult struct TGet struct TPut struct TDelete struct TIncrement struct TScan struct TRowMutations |
異常 | exception IOError exception IllegalArgument exception AlreadyExists | exception TIOError exception TIllegalArgument |
其他 | ? | union TMutation enum TDeleteType enum TDurability |
服務 | 名稱為:Hbase void enableTable() void disableTable() bool isTableEnabled() void compact() void majorCompact() list<Text> getTableNames() map<Text,ColumnDescriptor> getColumnDescriptors() list<TRegionInfo> getTableRegions() void createTable() void deleteTable() list<TCell> get() list<TCell> getVer() list<TCell> getVerTs() list<TRowResult> getRow() list<TRowResult> getRowWithColumns() list<TRowResult> getRowTs() list<TRowResult> getRowWithColumnsTs() list<TRowResult> getRows() list<TRowResult> getRowsWithColumns() list<TRowResult> getRowsTs() list<TRowResult> getRowsWithColumnsTs() void mutateRow() void mutateRowTs() void mutateRows() void mutateRowsTs() i64 atomicIncrement() void deleteAll() void deleteAllTs() void deleteAllRow() void increment() void incrementRows() void deleteAllRowTs() ScannerID scannerOpenWithScan() ScannerID scannerOpen() ScannerID scannerOpenWithStop() ScannerID scannerOpenWithPrefix() ScannerID scannerOpenTs() ScannerID scannerOpenWithStopTs() list<TRowResult> scannerGet() list<TRowResult> scannerGetList() void scannerClose() list<TCell> getRowOrBefore() TRegionInfo getRegionInfo() | 名稱為:THBaseService bool exists(...) TResult get(...) list<TResult> getMultiple(...) void put(...) bool checkAndPut(...) void putMultiple(...) void deleteSingle(...) list<TDelete> deleteMultiple(...) bool checkAndDelete(...) TResult increment(...) i32 openScanner(...) list<TResult> getScannerRows(...) void closeScanner(...) void mutateRow(...) list<TResult> getScannerResults(...) |
三、thrift2接口客戶端生成文件
包含6個文件hbase_constants.cpp/.h、 hbase_types.cpp/.h、THBaseService.cpp/.h,結構的定義都在hbase_types中,服務方法的實現在THBaseService中(關于這幾個文件的詳細說明,見作者其他博文)。由于我們通常關心數據的查、增、刪(對Hbase來說,改是增加一個新“版本”),因此下面的討論只圍繞這些操作展開。
四、thrift2接口主要結構
以下是主要涉及的結構及其意義。
- TColumn 對列的封裝
- TColumnValue? 對列及其值的封裝
- TResult? 對單行(Row)及其查詢結果(若干colunmvalue)的封裝
- TGet? 對查詢一行(row)的封裝,可以設置行內的查詢條件
- TPut? 與TGet一樣,只是它是寫入若干“列”
- TDelete? 與TGet一樣,只是它是刪除若干“列”
- TScan 對查詢多行和多列的封裝,有點類似于“cursor”
- TRowMutations 實際上是若干個TDelete和TPut的集合,完成對一行內數據的“原子”操作
五、thrift2接口service函數
1.?? ?查數據
Service中有關查數據的函數如下:
- get:對某一行內的查詢,輸入是表名、TGet結構,輸出是TResult
- getMultiple:實際上是對get的擴展,輸入是表名、TGet數組,輸出是TResult數組
- openScanner、getScannerRows、closeScanner:這三個連在一起使用,類似于”cursor”,由openScanner打開一個scanner,getScannerRows從這個打開的scanner順序得到若干行(也就是一個TResult數組,行數可指定),得不到數據行后可認為已讀完,最后用closeScanner關閉這個scanner。查詢的條件由TScan封裝,在打開時傳入。需要注意的是每次取數據的行數要合適,否則有效率問題。
2.?? ?增數據
Service中有關添加數據的函數如下:
- put:對某一行內增加若干列,輸入是表名,TPut結構
- putMultiple:對put的擴展,一次增加若干行內的若個列,輸入是表名、TPut數組
- checkAndPut:這個函數比較有意思,它提供了一種“原子”操作的概念,當傳入的(表名+列族名+列名+數據)都存在于數據庫時,才做操作,返回true,否則不做任何操作而返回false。可以看出,Hbase內部實現這個操作時肯定是加鎖的。它使用的場合如下:某時刻一個用戶取得了某個值,以后只有在確保沒有其他人操作該值的情況下才能進行更新。
3.?? ?刪數據
Service中有關刪除數據的函數如下:deleteSingle,deleteMultiple,checkAndDelete,這三個與上面的put函數類似,不再論述。
4.?? ?其他
Service中其他的函數如下:
- exists:檢查表內是否存在某行或某行內某些列,輸入是表名、TGet,輸出是bool
- mutateRow:將某行內若干put和delete操作集合起來,形成一個“原子”操作。輸入是表名、TRowMutations結構。
- increment:增加一行內某些列的值,這個操作比較特別,是專門用于計數的,也保證了“原子”操作特性。
需要注意的是,以上大部分函數都是void,如果操作發生錯誤,thrift的做法是拋出異常,因此進行操作時應有異常捕獲處理。
thrift2接口比較簡單明了,當然,實際使用時,會進行或多或少的再次封裝,以適應自己的應用需要,對該接口的再次封裝,這里不在討論。