Python無法直接訪問HBase,必須通過Thrift。
HBase與Thrift之間又支持兩種接口標准,兩種標准互不兼容,功能也互不覆蓋。
Thrift連接HBase還有超時自動斷開的大坑。
- 安裝Thrift依賴(Server端)
Centos: yum install automake libtool flex bison pkgconfig gcc-c++ boost-devel libevent-devel zlib-devel python-devel ruby-devel openssl-devel
Ubuntu: apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
- 安裝Boost(Server端)
可以嘗試yum/apt-get安裝libboost1.53(或其他版本),安裝完嘗試Thrift是否正常啟動,如果無法安裝或安裝完版本不兼容則手動下載安裝
wget http://sourceforge.net/projects/boost/files/boost/1.53.0/boost_1_53_0.tar.gz
tar xvf boost_1_53_0.tar.gz
cd boost_1_53_0
./bootstrap.sh
./b2 install
cp /usr/local/lib/libboost_unit_test_framework.a /usr/lib/
- 修改文件(安裝Thrift報錯:error: ‘uintptr_t’ was not declared)
vim /usr/local/include/boost/cstdint.hpp
第43行左右,將上面語句屏蔽,更新為下面語句 //#if defined(BOOST_HAS_STDINT_H) && (!defined(__GLIBC__) || defined(__GLIBC_HAVE_LONG_LONG)) #if defined(BOOST_HAS_STDINT_H) \ && (!defined(__GLIBC__) \ || defined(__GLIBC_HAVE_LONG_LONG) \ || (defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) \ && (__GLIBC_MINOR__ >= 17)))))
- 安裝Thrift(Server端)
從http://thrift.apache.org/下載最新版本的Thrift
tar -xvf thrift-0.12.0.tar.gz
cd thrift-0.12.0
./configure --libdir=/usr/lib
make
make install
- 啟動HBase-Thrift(Server端)
找到hbase-daemon.sh(如果是ambari安裝則在/usr/hdp/版本號/hbase目錄下面)
啟動Thrift:hbase-daemon.sh start thrift
啟動Thrift2:hbase-daemon.sh start thrift2
默認啟動HBase與Thrift交互端口為9095,Thrift外部端口為9090
多個Thrift同時啟動會端口沖突,可以通過--infoport 9096 -p 9091命令來指定內部和外部端口,同時還需要找到hbase-daemon.sh上層目錄conf下面的hbase-site.xml,修改/新增hbase.thrift.info.port和hbase.regionserver.thrift.port配置,這個沒有嘗試過,不知道有沒有其他坑
- 配置HBase-Thrift(調用Thrift報錯:TTransportException)
TTransportException錯誤分兩種情況
一種是一條結果都獲取不了,這種情況一般是使用問題,比如用Thrift2的接口調用Thrift,或者混淆了bytes和str
另一種情況是可以正常使用,但過幾分鍾莫名其妙就斷了,這種是由於HBase配置有bug
需要在hbase-site.xml加入以下兩項(如果設定超時時間為一天),然后重啟HBase和Thrift
<property>
<name>hbase.thrift.server.socket.read.timeout</name>
<value>86400000</value>
</property>
<property>
<name>hbase.thrift.connection.max-idletime</name>
<value>86400000</value>
</property>
- 安裝Thrift/Thrift2環境(Client端)
pip install thrift
- 使用Thrift方式一:pip安裝(Client端)
pip install hbase-thrift
安裝包安裝到python安裝目錄lib/hbase或lib/site-packages/hbase下面
from thrift import Thrift from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol # 連接 tsocket = TSocket.TSocket("10.0.0.1", 9090) tsocket.setTimeout(5000) ttransport = TTransport.TBufferedTransport(tsocket) protocol = TBinaryProtocol.TBinaryProtocol(ttransport) from hbase import Hbase # 客戶端 client = Hbase.Client(protocol) tsocket.open() #關鍵字 tableName = bytes("namespace:table", encoding='utf8') rowkey = bytes("rowkey", encoding='utf8') # 獲取所有表名 tableNames = client.getTableNames() print('tableNames:',tableNames) # 獲取列族 columnDescriptors = client.getColumnDescriptors(tableName) print("columnName:",columnDescriptors) # 獲取行 row = client.getRow(tableName,rowkey) print("row:",row)
使用hbase-thrift包的優點是包含的接口比較全面,比如獲取所有tables、修改table屬性等,缺點是讀取方法很少,很多讀取方法無法實現
- 使用Thrift方式二:源碼編譯安裝(Client端)
如果hbase使用的是源碼安裝包安裝的,可以找到Server端源碼其中的hbase/thrift/Hbase.thrift
或者上http://svn.apache.org/viewvc/hbase/trunk/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift下載最新版本的Hbase.thrift
執行thrift -r --gen py Hbase.thrift
當前目錄下生成gen-py
將gen-py/hbase中的內容覆蓋到Client端python安裝目錄的lib/hbase或lib/site-packages/hbase下面
from thrift import Thrift from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol # 連接 tsocket = TSocket.TSocket("10.0.0.1", 9090) tsocket.setTimeout(5000) ttransport = TTransport.TBufferedTransport(tsocket) protocol = TBinaryProtocol.TBinaryProtocol(ttransport) from hbase import Hbase # 客戶端 client = Hbase.Client(protocol) tsocket.open() #關鍵字 tableName = bytes("namespace:table", encoding='utf8') rowkey = bytes("rowkey", encoding='utf8') # 獲取所有表名 tableNames = client.getTableNames() print('tableNames:',tableNames) # 獲取列族 columnDescriptors = client.getColumnDescriptors(tableName) print("columnName:",columnDescriptors) # 獲取行 row = client.getRow(tableName,rowkey,attributes={}) print("row:",row)
最新官方的Hbase.thrift生成的包中包含了一些新接口新功能,如getRow()函數的attributes參數,但是實測並沒有什么作用
- 使用Thrift方式三:Happybase(Client端)
pip install happybase
import happybase connect = happybase.Connection(host="10.0.0.1", port=9090) connect.open() table = connect.table("namespace:table") print(table.row('rowkey', timestamp=1554277000000, include_timestamp=True)) connect.close()
happybase的優勢是封裝較好,使用方便
- 使用Thrift2(Client端)
如果需要對表中的內容進行更細致的操作,比如提取某個時間段之間的columns,使用Thrift無法實現,只能使用Thrift2
找到源碼包中的hbase/thrift2/hbase.thrift或者下載http://svn.apache.org/viewvc/hbase/trunk/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift
執行thrift -r --gen py Hbase.thrift
將gen-py/hbase中的內容拷貝到Client端python安裝目錄的lib/hbase或lib/site-packages/hbase2(為了區分thrift與thrift2,如果不用共存也可命名為hbase或其他名稱)
from thrift import Thrift from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol # 連接 tsocket = TSocket.TSocket("10.0.0.2", 9090) tsocket.setTimeout(5000) transport = TTransport.TBufferedTransport(tsocket) protocol = TBinaryProtocol.TBinaryProtocol(transport) import hbase2 # 客戶端 client = hbase2.THBaseService.Client(protocol) tsocket.open() # 獲取行 get = TGet() get.row = bytes("rowkey", encoding='utf8') #get.timestamp = 1554278944040 get.timeRange = TTimeRange() get.timeRange.minStamp = 1554277751530 get.timeRange.maxStamp = 1554277751550 result = client.get(bytes('namespace:table', encoding='utf8'), get)
Thrift2的數據接口完善很多,可以實現一些Thrift無法實現的查詢功能,但是不包含獲取table列表之類的接口
參考文獻:
https://www.cnblogs.com/zhang-ke/p/9008228.html
https://blog.csdn.net/caojinlei_91/article/details/82761157
https://blog.csdn.net/kelonsen/article/details/78477152
https://blog.51cto.com/13103353/2107257
https://blog.csdn.net/wwlhz/article/details/56012053
https://blog.csdn.net/qq_36330643/article/details/83106759
http://www.aiuxian.com/article/p-3104971.html
