《HBase 不睡覺書》是一本讓人看了不會睡着的 HBase 技術書籍,寫的很是不錯,爲了加深記憶,決定把書中重要的部分整理成讀書筆記,便於後期查閱,同時但願爲初學 HBase 的同窗帶來一些幫助。數據庫
建立 HBase 鏈接請注意如下幾點:編程
hbase-site.xml
和 Hadoop 配置文件夾中的 core-site.xml
配置文件從服務器上拖下來放到項目 resources 文件夾內;try-with-resources
特性;不推薦將 Connection 實現爲單例,這樣當某個操做卡住時,其餘後續操做也會處於阻塞狀態,沒法達到併發的效果。緩存
public static void main(String[] args) throws URISyntaxException, IOException {
//獲取配置文件
Configuration config = HBaseConfiguration.create();
config.addResource(new Path(ClassLoader.getSystemResource("hbase-site.xml").toURI()));
config.addResource(new Path(ClassLoader.getSystemResource("core-site.xml").toURI()));
//建立鏈接
try (Connection connection = ConnectionFactory.createConnection(config); Admin admin = connection.getAdmin()) {
//定義表名
TableName tableName = TableName.valueOf("tb1");
//定義列族
ColumnFamilyDescriptor myCf = ColumnFamilyDescriptorBuilder.of("cf1");
//定義表
TableDescriptor table = TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(myCf).build();
//執行建立表動做
admin.createTable(table);
} catch (Exception ex) {
ex.printStackTrace();
}
}
複製代碼
早期的教程會教你們使用 HTable 類,並且使用這個類的時候不須要去手動地獲取 Connection,只須要把 Configuration 類做爲構建參數傳給 HTable 類,它會自動地去鏈接並完成操做。這個方法看起來操做很簡單,實則隱含着不少性能和安全問題,因此這個類被廢棄了。安全
官方建議你們先手動獲取 Connection,而後再從 Connection 中獲取 Table 接口(注意:不是 HTable 類,而是 Table 接口):bash
// 已廢棄,不推薦使用
// HTable table = new HTable(config, "mytable");
// 官方推薦
try (Connection connection = ConnectionFactory.createConnection(config)) {
connection.getTable(TableName.valueOf("tb1"));
}
複製代碼
在你讀出數據以後和修改數據中間這段時間,若是有別人也修改了這個數據,就會發生數據不一致的問題,checkAndPut 方法就是爲了解決這個問題而產生的。服務器
checkAndPut 方法只是把檢查和寫入這兩個步驟合二爲一了,checkAndPut 方法在寫入前會先比較目前存在的數據是否與你傳入的數據一致,若是一致則進行 put 操做,並返回 true;若是不一致,則返回 false,但不寫入數據。網絡
最新版本中 checkAndPut 已經棄用了,官方推薦使用 checkAndMutate。併發
checkAndPut 與 checkAndDelete 在最新的 API 中已經不推薦使用了,官方推薦使用 Table.checkAndMutate(byte[], byte[])
。checkAndMutate 會在執行 Put/Delete/RowMutations
操做前檢查 row/family/qualifier
value 是否與預期的值匹配,若是不匹配則不執行操做。oop
table.checkAndMutate(row, family).qualifier(qualifier).ifNotExists().thenPut(put);
複製代碼
保證原子性的狀況下,把數據庫中的某個列的數字加 N(N 能夠是正數或者負數)。post
Table table = connection.getTable(TableName.valueOf("tb1"));
Increment inc = new Increment(Bytes.toBytes("row1"));
inc.addColumn(Bytes.toBytes("cf1"), Bytes.toBytes("age"), 1L);
table.increment(inc);
複製代碼
當須要一次性操做(Put、Get、Delete)不少條數據的時候,爲了操做方便而且提升性能,可使用 batch 方法;這裏的操做列表 actions 裏面的操做能夠是 Put、Get、Delete 中的任意一種;第二個參數的 results 是操做的結果,results 中的結果順序是跟傳入的操做列表順序一一對應的。
void batch(List<Row>actions, Object[] results)
複製代碼
最好不要把針對同一個單元格的 Put 和 Delete 放到同一個 actions 列表裏面,由於 HBase 不必定是順序地執行這些操做的,你可能會獲得意想不到的結果。
HBase 提供了專門針對批量 put 的操做方法:void put(List<Put> puts)
;其實內部也是用 batch 來實現的。須要注意的是,當一部分數據插入成功,可是另外一部分數據插入失敗,好比某個 RegionServer 服務器出現了問題,這時會返回一個 IOException,操做會被放棄,不過插入成功的數據不會被回滾,仍是成功插入了。
對於插入失敗的數據,服務器會嘗試着再次去插入或者換一個 RegionServer,當嘗試的次數大於定義的最大次數會拋出 RetriesExhaustedWithDetailsException 異常,該異常包含了不少錯誤信息,包括有多少操做失敗了,失敗的緣由以及服務器名和重試的次數。
若是定義了錯誤的列族,則只會嘗試一次,由於若是連列族都錯了,就不必再繼續嘗試下去了,HBase 會直接返回 NoSuchColumnFamilyException。
插入失敗的數據會繼續被放到本地的寫緩衝區,並在下次插入的時候重試,你甚至能夠操做它們,好比清除這些數據。
客戶端寫緩衝區就是一個在客戶端 JVM 裏面的緩存機制,能夠把多個 Put 操做攢到一塊兒經過單個 RPC 請求發送給客戶端,目的是節省網絡握手帶來的 IO 消耗。這個緩衝區能夠經過調用 HTable.setAutoFlush(false)
來開啓。
最新版的 API 中 setAutoFlush 被廢棄了,每一個表自帶的 writeBuffer 也被廢棄了,可是客戶端寫緩衝區仍是存在的,只是轉而使用 BufferedMutator 對象。
BufferedMutator bm = connection.getBufferedMutator(TableName.valueOf("tb1"));
// 而後用BufferedMutator對象來提交Put操做
bm.mutate(put);
// 而後調用 flush 或者 close 方法均可以把請求批量地提交給服務端
bm.flush();
bm.close();
複製代碼
大部分狀況下咱們不須要直接調用到 BufferedMutator,也不推薦直接調用 BufferedMutator。
早期的 HBase 在掃描的時候默認是不開啓緩存的,可是通過了廣大使用者許屢次的實踐後,如今的 HBase 在掃描的時候已經默認開啓了緩存。
具體地說就是:每一次的 next() 操做都會產生一次完整的 RPC 請求,而此次 RPC 請求能夠獲取多少數據是經過 hbase-site.xml
中的 hbase.client.scanner.caching
參數配置的。好比你若是配置該項爲 1,那麼當你遍歷了 10 個結果就會發送 10 次請求,顯而易見這是比較消耗性能的,尤爲是當單條的數據量較小的時候。
能夠在表層面修改緩存條數,也能夠在掃描層面去修改,在表的層面修改是經過把這段配置寫到 hbase-site.xml
內去實現:
<property>
<name>hbase.client.scanner.caching</name>
<value>200</value>
</property>
複製代碼
意思是每次 next 操做都獲取 200 條數據,默認配置是100。
可使用 Scan.setCaching(int caching)
方法在掃描層面修改緩存,這個配置優先級比配置文件內的高,能夠複寫這個配置值。緩存當然好,可是帶來的危害就是會佔用大量內存,最糟糕的就是直接出現 OutOfMemoryException,因此也不要盲目的調大緩存。
Any Code,Code Any!
掃碼關注『AnyCode』,編程路上,一塊兒前行。