HTable和HTablePool使用注意事項
HTable和HTablePool都是HBase客戶端API的一部分,可以使用它們對HBase表進行CRUD操作。下面結合在項目中的應用情況,對二者使用過程中的注意事項做一下概括總結。
HTable
HTable是HBase客戶端與HBase服務端通訊的Java API對象,客戶端可以通過HTable對象與服務端進行CRUD操作(增刪改查)。它的創建很簡單:
Configuration conf = HBaseConfiguration.create(); HTable table = new HTable(conf, "tablename"); //TODO CRUD Operation……
HTable使用時的一些注意事項:
1. 規避HTable對象的創建開銷
因為客戶端創建HTable對象后,需要進行一系列的操作:檢查.META.表確認指定名稱的HBase表是否存在,表是否有效等等,整個時間開銷比較重,可能會耗時幾秒鐘之長,因此最好在程序啟動時一次性創建完成需要的HTable對象,如果使用Java API,一般來說是在構造函數中進行創建,程序啟動后直接重用。
2. HTable對象不是線程安全的
HTable對象對于客戶端讀寫數據來說不是線程安全的,因此多線程時,要為每個線程單獨創建復用一個HTable對象,不同對象間不要共享HTable對象使用,特別是在客戶端auto flash被置為false時,由于存在本地write buffer,可能導致數據不一致。
3. HTable對象之間共享Configuration
HTable對象共享Configuration對象,這樣的好處在于:
- 共享ZooKeeper的連接:每個客戶端需要與ZooKeeper建立連接,查詢用戶的table regions位置,這些信息可以在連接建立后緩存起來共享使用;
- 共享公共的資源:客戶端需要通過ZooKeeper查找-ROOT-和.META.表,這個需要網絡傳輸開銷,客戶端緩存這些公共資源后能夠減少后續的網絡傳輸開銷,加快查找過程速度。
因此,與以下這種方式相比:
HTable table1 = new HTable("table1"); HTable table2 = new HTable("table2");
下面的方式更有效些:
Configuration conf = HBaseConfiguration.create(); HTable table1 = new HTable(conf, "table1"); HTable table2 = new HTable(conf, "table2");
備注:即使是高負載的多線程程序,也并沒有發現因為共享Configuration而導致的性能問題;如果你的實際情況中不是如此,那么可以嘗試不共享Configuration。
HTablePool
HTablePool可以解決HTable存在的線程不安全問題,同時通過維護固定數量的HTable對象,能夠在程序運行期間復用這些HTable資源對象。
Configuration conf = HBaseConfiguration.create(); HTablePool pool = new HTablePool(conf, 10);
1. HTablePool可以自動創建HTable對象,而且對客戶端來說使用上是完全透明的,可以避免多線程間數據并發修改問題。
2. HTablePool中的HTable對象之間是公用Configuration連接的,能夠可以減少網絡開銷。
HTablePool的使用很簡單:每次進行操作前,通過HTablePool的getTable方法取得一個HTable對象,然后進行put/get/scan/delete等操作,最后通過HTablePool的putTable方法將HTable對象放回到HTablePool中。
下面是個使用HTablePool的簡單例子:
public void createUser(String username, String firstName, String lastName, String email, String password, String roles) throws IOException { HTable table = rm.getTable(UserTable.NAME); Put put = new Put(Bytes.toBytes(username)); put.add(UserTable.DATA_FAMILY, UserTable.FIRSTNAME, Bytes.toBytes(firstName)); put.add(UserTable.DATA_FAMILY, UserTable.LASTNAME, Bytes.toBytes(lastName)); put.add(UserTable.DATA_FAMILY, UserTable.EMAIL, Bytes.toBytes(email)); put.add(UserTable.DATA_FAMILY, UserTable.CREDENTIALS, Bytes.toBytes(password)); put.add(UserTable.DATA_FAMILY, UserTable.ROLES, Bytes.toBytes(roles)); table.put(put); table.flushCommits(); rm.putTable(table); }
至于多線程使用HTablePool的真實性能情況,需要通過實際的測試工作得到。
浙公網安備 33010602011771號