From 051e9991f3b690ffba352eb24c0f077b0f39a3cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Wed, 10 Apr 2019 17:34:17 +0800 Subject: [PATCH] Hbase java api --- README.md | 16 +- code/Hbase/hbase-java-api-1.x/pom.xml | 38 + .../main/java/com/heibaiying/HBaseUtils.java | 267 ++++++ .../java/com/heibaiying/HbaseUtilsTest.java | 107 +++ code/Hbase/hbase-java-api-2.x/pom.xml | 37 + .../main/java/com/heibaiying/HBaseUtils.java | 266 ++++++ .../test/java/heibaiying/HBaseUtilsTest.java | 109 +++ notes/Hbase Java API.md | 758 ++++++++++++++++++ pictures/deprecated.png | Bin 0 -> 32408 bytes pictures/hbase-arc.png | Bin 0 -> 46105 bytes pictures/hbase-connection.png | Bin 0 -> 35085 bytes 11 files changed, 1591 insertions(+), 7 deletions(-) create mode 100644 code/Hbase/hbase-java-api-1.x/pom.xml create mode 100644 code/Hbase/hbase-java-api-1.x/src/main/java/com/heibaiying/HBaseUtils.java create mode 100644 code/Hbase/hbase-java-api-1.x/src/test/java/com/heibaiying/HbaseUtilsTest.java create mode 100644 code/Hbase/hbase-java-api-2.x/pom.xml create mode 100644 code/Hbase/hbase-java-api-2.x/src/main/java/com/heibaiying/HBaseUtils.java create mode 100644 code/Hbase/hbase-java-api-2.x/src/test/java/heibaiying/HBaseUtilsTest.java create mode 100644 notes/Hbase Java API.md create mode 100644 pictures/deprecated.png create mode 100644 pictures/hbase-arc.png create mode 100644 pictures/hbase-connection.png diff --git a/README.md b/README.md index 078484b..7f0032d 100644 --- a/README.md +++ b/README.md @@ -98,14 +98,16 @@ TODO ## 九、HBase -1. [HBase基本环境搭建(Standalone /pseudo-distributed mode)](https://github.com/heibaiying/BigData-Notes/blob/master/notes/installation/Hbase%E5%9F%BA%E6%9C%AC%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md) +1. Hbase 简介 2. [HBase系统架构及数据结构](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E5%8F%8A%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.md) -3. [HBase常用Shell命令](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%20Shell.md) -4. HBase Java API -5. [HBase 协处理器](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase协处理器.md) -6. [HBase 容灾与备份](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E5%AE%B9%E7%81%BE%E4%B8%8E%E5%A4%87%E4%BB%BD.md) -7. [HBase的SQL中间层——Phoenix](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E7%9A%84SQL%E5%B1%82%E2%80%94%E2%80%94Phoenix.md) -8. [Spring/Spring Boot 整合 Mybatis + Phoenix](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Spring%2BMybtais%2BPhoenix%E6%95%B4%E5%90%88.md) +3. [HBase基本环境搭建(Standalone /pseudo-distributed mode)](https://github.com/heibaiying/BigData-Notes/blob/master/notes/installation/Hbase%E5%9F%BA%E6%9C%AC%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md) +4. [HBase常用Shell命令](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%20Shell.md) +5. HBase Java API +6. Hbase 过滤器 +7. [HBase 协处理器](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase协处理器.md) +8. [HBase 容灾与备份](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E5%AE%B9%E7%81%BE%E4%B8%8E%E5%A4%87%E4%BB%BD.md) +9. [HBase的SQL中间层——Phoenix](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hbase%E7%9A%84SQL%E5%B1%82%E2%80%94%E2%80%94Phoenix.md) +10. [Spring/Spring Boot 整合 Mybatis + Phoenix](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Spring%2BMybtais%2BPhoenix%E6%95%B4%E5%90%88.md) ## 十、Kafka 1. Kafka 简介及消息处理过程分析 diff --git a/code/Hbase/hbase-java-api-1.x/pom.xml b/code/Hbase/hbase-java-api-1.x/pom.xml new file mode 100644 index 0000000..915329b --- /dev/null +++ b/code/Hbase/hbase-java-api-1.x/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.heibaiying + hbase-java-api-1.x + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + + + org.apache.hbase + hbase-client + 1.2.0 + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/code/Hbase/hbase-java-api-1.x/src/main/java/com/heibaiying/HBaseUtils.java b/code/Hbase/hbase-java-api-1.x/src/main/java/com/heibaiying/HBaseUtils.java new file mode 100644 index 0000000..cc76890 --- /dev/null +++ b/code/Hbase/hbase-java-api-1.x/src/main/java/com/heibaiying/HBaseUtils.java @@ -0,0 +1,267 @@ +package com.heibaiying; + +import javafx.util.Pair; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.*; +import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.util.Bytes; + +import java.io.IOException; +import java.util.List; + +public class HBaseUtils { + + private static Connection connection; + + static { + Configuration configuration = HBaseConfiguration.create(); + configuration.set("hbase.zookeeper.property.clientPort", "2181"); + // 如果是集群 则主机名用逗号分隔 + configuration.set("hbase.zookeeper.quorum", "hadoop001"); + try { + connection = ConnectionFactory.createConnection(configuration); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 创建HBase表 + * + * @param tableName 表名 + * @param columnFamilies 列族的数组 + */ + public static boolean createTable(String tableName, List columnFamilies) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + if (admin.tableExists(tableName)) { + return false; + } + HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName)); + columnFamilies.forEach(columnFamily -> { + HColumnDescriptor columnDescriptor = new HColumnDescriptor(columnFamily); + columnDescriptor.setMaxVersions(1); + tableDescriptor.addFamily(columnDescriptor); + }); + admin.createTable(tableDescriptor); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除hBase表 + * + * @param tableName 表名 + */ + public static boolean deleteTable(String tableName) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + // 删除表前需要先禁用表 + admin.disableTable(tableName); + admin.deleteTable(tableName); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param qualifier 列标识 + * @param value 数据 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, String qualifier, + String value) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(qualifier), Bytes.toBytes(value)); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param pairList 列标识和值的集合 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, List> pairList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + pairList.forEach(pair -> put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(pair.getKey()), Bytes.toBytes(pair.getValue()))); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 根据rowKey获取指定行的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static Result getRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + return table.get(get); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 获取指定行指定列(cell)的最新版本的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamily 列族 + * @param qualifier 列标识 + */ + public static String getCell(String tableName, String rowKey, String columnFamily, String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + if (!get.isCheckExistenceOnly()) { + get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + Result result = table.get(get); + byte[] resultValue = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + return Bytes.toString(resultValue); + } else { + return null; + } + + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索全表 + * + * @param tableName 表名 + */ + public static ResultScanner getScanner(String tableName) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param startRowKey 起始RowKey + * @param endRowKey 终止RowKey + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, String startRowKey, String endRowKey, + FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setStartRow(Bytes.toBytes(startRowKey)); + scan.setStopRow(Bytes.toBytes(endRowKey)); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 删除指定行记录 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static boolean deleteRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + table.delete(delete); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除指定行的指定列 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param familyName 列族 + * @param qualifier 列标识 + */ + public static boolean deleteColumn(String tableName, String rowKey, String familyName, + String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + delete.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(qualifier)); + table.delete(delete); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + +} diff --git a/code/Hbase/hbase-java-api-1.x/src/test/java/com/heibaiying/HbaseUtilsTest.java b/code/Hbase/hbase-java-api-1.x/src/test/java/com/heibaiying/HbaseUtilsTest.java new file mode 100644 index 0000000..159d883 --- /dev/null +++ b/code/Hbase/hbase-java-api-1.x/src/test/java/com/heibaiying/HbaseUtilsTest.java @@ -0,0 +1,107 @@ +package com.heibaiying; + +import javafx.util.Pair; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.filter.CompareFilter; +import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class HBaseUtilsTest { + + private static final String TABLE_NAME = "class"; + private static final String TEACHER = "teacher"; + private static final String STUDENT = "student"; + + @Test + public void createTable() { + // 新建表 + List columnFamilies = Arrays.asList(TEACHER, STUDENT); + boolean table = HBaseUtils.createTable(TABLE_NAME, columnFamilies); + System.out.println("表创建结果:" + table); + } + + @Test + public void insertData() { + List> pairs1 = Arrays.asList(new Pair<>("name", "Tom"), + new Pair<>("age", "22"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey1", STUDENT, pairs1); + + List> pairs2 = Arrays.asList(new Pair<>("name", "Jack"), + new Pair<>("age", "33"), + new Pair<>("gender", "2")); + HBaseUtils.putRow(TABLE_NAME, "rowKey2", STUDENT, pairs2); + + List> pairs3 = Arrays.asList(new Pair<>("name", "Mike"), + new Pair<>("age", "44"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey3", STUDENT, pairs3); + } + + + @Test + public void getRow() { + Result result = HBaseUtils.getRow(TABLE_NAME, "rowKey1"); + if (result != null) { + System.out.println(Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name")))); + } + + } + + @Test + public void getCell() { + String cell = HBaseUtils.getCell(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("cell age :" + cell); + + } + + @Test + public void getScanner() { + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + + @Test + public void getScannerWithFilter() { + FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); + SingleColumnValueFilter nameFilter = new SingleColumnValueFilter(Bytes.toBytes(STUDENT), + Bytes.toBytes("name"), CompareFilter.CompareOp.EQUAL, Bytes.toBytes("Jack")); + filterList.addFilter(nameFilter); + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME, filterList); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + @Test + public void deleteColumn() { + boolean b = HBaseUtils.deleteColumn(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteRow() { + boolean b = HBaseUtils.deleteRow(TABLE_NAME, "rowKey2"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteTable() { + boolean b = HBaseUtils.deleteTable(TABLE_NAME); + System.out.println("删除结果: " + b); + } +} \ No newline at end of file diff --git a/code/Hbase/hbase-java-api-2.x/pom.xml b/code/Hbase/hbase-java-api-2.x/pom.xml new file mode 100644 index 0000000..a4a449b --- /dev/null +++ b/code/Hbase/hbase-java-api-2.x/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + com.heibaiying + hbase-java-api-2.x + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + + org.apache.hbase + hbase-client + 2.1.4 + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/code/Hbase/hbase-java-api-2.x/src/main/java/com/heibaiying/HBaseUtils.java b/code/Hbase/hbase-java-api-2.x/src/main/java/com/heibaiying/HBaseUtils.java new file mode 100644 index 0000000..8f1489f --- /dev/null +++ b/code/Hbase/hbase-java-api-2.x/src/main/java/com/heibaiying/HBaseUtils.java @@ -0,0 +1,266 @@ +package com.heibaiying; + +import javafx.util.Pair; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.*; +import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.util.Bytes; + +import java.io.IOException; +import java.util.List; + +public class HBaseUtils { + + private static Connection connection; + + static { + Configuration configuration = HBaseConfiguration.create(); + configuration.set("hbase.zookeeper.property.clientPort", "2181"); + // 如果是集群 则主机名用逗号分隔 + configuration.set("hbase.zookeeper.quorum", "hadoop001"); + try { + connection = ConnectionFactory.createConnection(configuration); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 创建HBase表 + * + * @param tableName 表名 + * @param columnFamilies 列族的数组 + */ + public static boolean createTable(String tableName, List columnFamilies) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + if (admin.tableExists(TableName.valueOf(tableName))) { + return false; + } + TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)); + columnFamilies.forEach(columnFamily -> { + ColumnFamilyDescriptorBuilder cfDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily)); + cfDescriptorBuilder.setMaxVersions(1); + ColumnFamilyDescriptor familyDescriptor = cfDescriptorBuilder.build(); + tableDescriptor.setColumnFamily(familyDescriptor); + }); + admin.createTable(tableDescriptor.build()); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除hBase表 + * + * @param tableName 表名 + */ + public static boolean deleteTable(String tableName) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + // 删除表前需要先禁用表 + admin.disableTable(TableName.valueOf(tableName)); + admin.deleteTable(TableName.valueOf(tableName)); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param qualifier 列标识 + * @param value 数据 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, String qualifier, + String value) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(qualifier), Bytes.toBytes(value)); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param pairList 列标识和值的集合 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, List> pairList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + pairList.forEach(pair -> put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(pair.getKey()), Bytes.toBytes(pair.getValue()))); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 根据rowKey获取指定行的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static Result getRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + return table.get(get); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 获取指定行指定列(cell)的最新版本的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamily 列族 + * @param qualifier 列标识 + */ + public static String getCell(String tableName, String rowKey, String columnFamily, String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + if (!get.isCheckExistenceOnly()) { + get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + Result result = table.get(get); + byte[] resultValue = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + return Bytes.toString(resultValue); + } else { + return null; + } + + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索全表 + * + * @param tableName 表名 + */ + public static ResultScanner getScanner(String tableName) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param startRowKey 起始RowKey + * @param endRowKey 终止RowKey + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, String startRowKey, String endRowKey, + FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.withStartRow(Bytes.toBytes(startRowKey)); + scan.withStopRow(Bytes.toBytes(endRowKey)); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 删除指定行记录 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static boolean deleteRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + table.delete(delete); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除指定行指定列 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param familyName 列族 + * @param qualifier 列标识 + */ + public static boolean deleteColumn(String tableName, String rowKey, String familyName, + String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + delete.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(qualifier)); + table.delete(delete); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + +} diff --git a/code/Hbase/hbase-java-api-2.x/src/test/java/heibaiying/HBaseUtilsTest.java b/code/Hbase/hbase-java-api-2.x/src/test/java/heibaiying/HBaseUtilsTest.java new file mode 100644 index 0000000..a11e6da --- /dev/null +++ b/code/Hbase/hbase-java-api-2.x/src/test/java/heibaiying/HBaseUtilsTest.java @@ -0,0 +1,109 @@ +package heibaiying; + +import com.heibaiying.HBaseUtils; +import javafx.util.Pair; +import org.apache.hadoop.hbase.CompareOperator; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.filter.CompareFilter; +import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class HBaseUtilsTest { + + private static final String TABLE_NAME = "class"; + private static final String TEACHER = "teacher"; + private static final String STUDENT = "student"; + + @Test + public void createTable() { + // 新建表 + List columnFamilies = Arrays.asList(TEACHER, STUDENT); + boolean table = HBaseUtils.createTable(TABLE_NAME, columnFamilies); + System.out.println("表创建结果:" + table); + } + + @Test + public void insertData() { + List> pairs1 = Arrays.asList(new Pair<>("name", "Tom"), + new Pair<>("age", "22"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey1", STUDENT, pairs1); + + List> pairs2 = Arrays.asList(new Pair<>("name", "Jack"), + new Pair<>("age", "33"), + new Pair<>("gender", "2")); + HBaseUtils.putRow(TABLE_NAME, "rowKey2", STUDENT, pairs2); + + List> pairs3 = Arrays.asList(new Pair<>("name", "Mike"), + new Pair<>("age", "44"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey3", STUDENT, pairs3); + } + + + @Test + public void getRow() { + Result result = HBaseUtils.getRow(TABLE_NAME, "rowKey1"); + if (result != null) { + System.out.println(Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name")))); + } + + } + + @Test + public void getCell() { + String cell = HBaseUtils.getCell(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("cell age :" + cell); + + } + + @Test + public void getScanner() { + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + + @Test + public void getScannerWithFilter() { + FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); + SingleColumnValueFilter nameFilter = new SingleColumnValueFilter(Bytes.toBytes(STUDENT), + Bytes.toBytes("name"), CompareOperator.EQUAL, Bytes.toBytes("Jack")); + filterList.addFilter(nameFilter); + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME, filterList); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + @Test + public void deleteColumn() { + boolean b = HBaseUtils.deleteColumn(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteRow() { + boolean b = HBaseUtils.deleteRow(TABLE_NAME, "rowKey2"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteTable() { + boolean b = HBaseUtils.deleteTable(TABLE_NAME); + System.out.println("删除结果: " + b); + } +} \ No newline at end of file diff --git a/notes/Hbase Java API.md b/notes/Hbase Java API.md new file mode 100644 index 0000000..6f858f8 --- /dev/null +++ b/notes/Hbase Java API.md @@ -0,0 +1,758 @@ +# Hbase Java API 的基本使用 + + + + + +## 一、简述 + +截至到目前(2019年4月),Hbase 主要有1.x 和 2.x 两个主要的版本,两个版本的Java API的接口和方法都是有所不同的,1.x 中某些方法在2.x中被标识为`@deprecated `过时,所以下面关于API的样例,我会分别给出1.x和2.x两个版本。完整的代码见本仓库: + +>+ [Java API 1.x Examples](https://github.com/heibaiying/BigData-Notes/tree/master/code/Hbase/hbase-java-api-1.x) +> +>+ [Java API 2.x Examples](https://github.com/heibaiying/BigData-Notes/tree/master/code/Hbase/hbase-java-api-2.x) + +同时在实际使用中,客户端的版本必须与服务端保持一致,如果用2.x版本的客户端代码去连接1.x版本的服务端,是会抛出`NoSuchColumnFamilyException`等异常的。 + +## 二、Java API 1.x 基本使用 + +#### 2.1 新建Maven工程,导入项目依赖 + +要使用Java API 操作HBase,仅需要引入`hbase-client`。这里我服务端的Hbase版本为`hbase-1.2.0-cdh5.15.2`,对应的`Hbase client` 选取 1.2.0 版本 + +```xml + + org.apache.hbase + hbase-client + 1.2.0 + +``` + +#### 2.2 API 基本使用 + +这里列举了常用的增删改查操作 + +```java +public class HBaseUtils { + + private static Connection connection; + + static { + Configuration configuration = HBaseConfiguration.create(); + configuration.set("hbase.zookeeper.property.clientPort", "2181"); + // 如果是集群 则主机名用逗号分隔 + configuration.set("hbase.zookeeper.quorum", "hadoop001"); + try { + connection = ConnectionFactory.createConnection(configuration); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 创建HBase表 + * + * @param tableName 表名 + * @param columnFamilies 列族的数组 + */ + public static boolean createTable(String tableName, List columnFamilies) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + if (admin.tableExists(tableName)) { + return false; + } + HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName)); + columnFamilies.forEach(columnFamily -> { + HColumnDescriptor columnDescriptor = new HColumnDescriptor(columnFamily); + columnDescriptor.setMaxVersions(1); + tableDescriptor.addFamily(columnDescriptor); + }); + admin.createTable(tableDescriptor); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除hBase表 + * + * @param tableName 表名 + */ + public static boolean deleteTable(String tableName) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + // 删除表前需要先禁用表 + admin.disableTable(tableName); + admin.deleteTable(tableName); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param qualifier 列标识 + * @param value 数据 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, String qualifier, + String value) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(qualifier), Bytes.toBytes(value)); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param pairList 列标识和值的集合 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, List> pairList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + pairList.forEach(pair -> put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(pair.getKey()), Bytes.toBytes(pair.getValue()))); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 根据rowKey获取指定行的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static Result getRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + return table.get(get); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 获取指定行指定列(cell)的最新版本的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamily 列族 + * @param qualifier 列标识 + */ + public static String getCell(String tableName, String rowKey, String columnFamily, String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + if (!get.isCheckExistenceOnly()) { + get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + Result result = table.get(get); + byte[] resultValue = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + return Bytes.toString(resultValue); + } else { + return null; + } + + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索全表 + * + * @param tableName 表名 + */ + public static ResultScanner getScanner(String tableName) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param startRowKey 起始RowKey + * @param endRowKey 终止RowKey + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, String startRowKey, String endRowKey, + FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setStartRow(Bytes.toBytes(startRowKey)); + scan.setStopRow(Bytes.toBytes(endRowKey)); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 删除指定行记录 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static boolean deleteRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + table.delete(delete); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除指定行的指定列 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param familyName 列族 + * @param qualifier 列标识 + */ + public static boolean deleteColumn(String tableName, String rowKey, String familyName, + String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + delete.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(qualifier)); + table.delete(delete); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + +} +``` + +### 2.3 单元测试 + +以单元测试的方式对封装的API进行测试 + +```java +public class HBaseUtilsTest { + + private static final String TABLE_NAME = "class"; + private static final String TEACHER = "teacher"; + private static final String STUDENT = "student"; + + @Test + public void createTable() { + // 新建表 + List columnFamilies = Arrays.asList(TEACHER, STUDENT); + boolean table = HBaseUtils.createTable(TABLE_NAME, columnFamilies); + System.out.println("表创建结果:" + table); + } + + @Test + public void insertData() { + List> pairs1 = Arrays.asList(new Pair<>("name", "Tom"), + new Pair<>("age", "22"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey1", STUDENT, pairs1); + + List> pairs2 = Arrays.asList(new Pair<>("name", "Jack"), + new Pair<>("age", "33"), + new Pair<>("gender", "2")); + HBaseUtils.putRow(TABLE_NAME, "rowKey2", STUDENT, pairs2); + + List> pairs3 = Arrays.asList(new Pair<>("name", "Mike"), + new Pair<>("age", "44"), + new Pair<>("gender", "1")); + HBaseUtils.putRow(TABLE_NAME, "rowKey3", STUDENT, pairs3); + } + + + @Test + public void getRow() { + Result result = HBaseUtils.getRow(TABLE_NAME, "rowKey1"); + if (result != null) { + System.out.println(Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name")))); + } + + } + + @Test + public void getCell() { + String cell = HBaseUtils.getCell(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("cell age :" + cell); + + } + + @Test + public void getScanner() { + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + + @Test + public void getScannerWithFilter() { + FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); + SingleColumnValueFilter nameFilter = new SingleColumnValueFilter(Bytes.toBytes(STUDENT), + Bytes.toBytes("name"), CompareOperator.EQUAL, Bytes.toBytes("Jack")); + filterList.addFilter(nameFilter); + ResultScanner scanner = HBaseUtils.getScanner(TABLE_NAME, filterList); + if (scanner != null) { + scanner.forEach(result -> System.out.println(Bytes.toString(result.getRow()) + "->" + Bytes + .toString(result.getValue(Bytes.toBytes(STUDENT), Bytes.toBytes("name"))))); + scanner.close(); + } + } + + @Test + public void deleteColumn() { + boolean b = HBaseUtils.deleteColumn(TABLE_NAME, "rowKey2", STUDENT, "age"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteRow() { + boolean b = HBaseUtils.deleteRow(TABLE_NAME, "rowKey2"); + System.out.println("删除结果: " + b); + } + + @Test + public void deleteTable() { + boolean b = HBaseUtils.deleteTable(TABLE_NAME); + System.out.println("删除结果: " + b); + } +} +``` + + + +## 三、Java API 2.x 基本使用 + +#### 3.1 新建Maven工程,导入项目依赖 + +这里选取的`HBase Client`的版本为最新的`2.1.4` + +```xml + + org.apache.hbase + hbase-client + 2.1.4 + +``` + +#### 3.2 API 的基本使用 + +2.x 版本相比于1.x 废弃了一部分方法,关于废弃的方法在源码中都会指明新的替代方法,比如,在2.x中创建表时:`HTableDescriptor`和`HColumnDescriptor`等类都标识为废弃,且会在3.0.0版本移除,取而代之的是使用`TableDescriptorBuilder`和`ColumnFamilyDescriptorBuilder`来定义表和列族。在升级版本时,可以用源码中指明的新的替代方法来代替过期的方法。 + +
+ + + +以下为HBase 2.x 版本Java API使用的完整示例: + +```java +public class HBaseUtils { + + private static Connection connection; + + static { + Configuration configuration = HBaseConfiguration.create(); + configuration.set("hbase.zookeeper.property.clientPort", "2181"); + // 如果是集群 则主机名用逗号分隔 + configuration.set("hbase.zookeeper.quorum", "hadoop001"); + try { + connection = ConnectionFactory.createConnection(configuration); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 创建HBase表 + * + * @param tableName 表名 + * @param columnFamilies 列族的数组 + */ + public static boolean createTable(String tableName, List columnFamilies) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + if (admin.tableExists(TableName.valueOf(tableName))) { + return false; + } + TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)); + columnFamilies.forEach(columnFamily -> { + ColumnFamilyDescriptorBuilder cfDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily)); + cfDescriptorBuilder.setMaxVersions(1); + ColumnFamilyDescriptor familyDescriptor = cfDescriptorBuilder.build(); + tableDescriptor.setColumnFamily(familyDescriptor); + }); + admin.createTable(tableDescriptor.build()); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除hBase表 + * + * @param tableName 表名 + */ + public static boolean deleteTable(String tableName) { + try { + HBaseAdmin admin = (HBaseAdmin) connection.getAdmin(); + // 删除表前需要先禁用表 + admin.disableTable(TableName.valueOf(tableName)); + admin.deleteTable(TableName.valueOf(tableName)); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param qualifier 列标识 + * @param value 数据 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, String qualifier, + String value) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(qualifier), Bytes.toBytes(value)); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 插入数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamilyName 列族名 + * @param pairList 列标识和值的集合 + */ + public static boolean putRow(String tableName, String rowKey, String columnFamilyName, List> pairList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Put put = new Put(Bytes.toBytes(rowKey)); + pairList.forEach(pair -> put.addColumn(Bytes.toBytes(columnFamilyName), Bytes.toBytes(pair.getKey()), Bytes.toBytes(pair.getValue()))); + table.put(put); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 根据rowKey获取指定行的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static Result getRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + return table.get(get); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 获取指定行指定列(cell)的最新版本的数据 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param columnFamily 列族 + * @param qualifier 列标识 + */ + public static String getCell(String tableName, String rowKey, String columnFamily, String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Get get = new Get(Bytes.toBytes(rowKey)); + if (!get.isCheckExistenceOnly()) { + get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + Result result = table.get(get); + byte[] resultValue = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(qualifier)); + return Bytes.toString(resultValue); + } else { + return null; + } + + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索全表 + * + * @param tableName 表名 + */ + public static ResultScanner getScanner(String tableName) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 检索表中指定数据 + * + * @param tableName 表名 + * @param startRowKey 起始RowKey + * @param endRowKey 终止RowKey + * @param filterList 过滤器 + */ + + public static ResultScanner getScanner(String tableName, String startRowKey, String endRowKey, + FilterList filterList) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Scan scan = new Scan(); + scan.withStartRow(Bytes.toBytes(startRowKey)); + scan.withStopRow(Bytes.toBytes(endRowKey)); + scan.setFilter(filterList); + return table.getScanner(scan); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 删除指定行记录 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + */ + public static boolean deleteRow(String tableName, String rowKey) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + table.delete(delete); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + + /** + * 删除指定行指定列 + * + * @param tableName 表名 + * @param rowKey 唯一标识 + * @param familyName 列族 + * @param qualifier 列标识 + */ + public static boolean deleteColumn(String tableName, String rowKey, String familyName, + String qualifier) { + try { + Table table = connection.getTable(TableName.valueOf(tableName)); + Delete delete = new Delete(Bytes.toBytes(rowKey)); + delete.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(qualifier)); + table.delete(delete); + table.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + +} +``` + + + +## 四、正确连接Hbase + +在上面的代码中在类加载时候就初始化了Connection连接,并且之后的方法都是复用这个Connection,这时我们可能会考虑是否可以使用义连接池来获取更好的性能表现?实际上这是没有必要的。 + +首先官方对于`Connection Pooling`做了如下表述: + +```properties +Connection Pooling +For applications which require high-end multithreaded access (e.g., web-servers or application servers that may serve many application threads in a single JVM), you can pre-create a Connection, as shown in the following example: + +#对于高并发多线程访问的应用程序(例如,在单个JVM中存在的为多个线程服务的Web服务器或应用程序服务器),您只需要预先创建一个Connection。例子如下: +``` + +```java +// Create a connection to the cluster. +Configuration conf = HBaseConfiguration.create(); +try (Connection connection = ConnectionFactory.createConnection(conf); + Table table = connection.getTable(TableName.valueOf(tablename))) { + // use table as needed, the table returned is lightweight +} +``` + +之所以能这样使用,这是因为Connection并不是一个简单的socket连接,[接口文档](https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Connection.html)中对Connection的表述是: + +```properties +A cluster connection encapsulating lower level individual connections to actual servers and a connection to zookeeper. Connections are instantiated through the ConnectionFactory class. The lifecycle of the connection is managed by the caller, who has to close() the connection to release the resources. + +# Connection是一个集群连接,封装了与多台服务器(Matser/Region Server)的底层连接以及与zookeeper的连接。连接通过ConnectionFactory类实例化。连接的生命周期由调用者管理,调用者必须使用close()关闭连接以释放资源。 +``` + +之所以封装这些连接,是因为HBase客户端需要连接三个不同的服务角色: + ++ Zookeeper:主要用于获得meta-region位置,集群Id、master等信息。 ++ HBase Master:主要用于执行HBaseAdmin接口的一些操作,例如建表等。 ++ HBase RegionServer:用于读、写数据。 + +
+ +Connection对象和实际的socket连接之间的对应关系如下图: + +
+ +> 上面两张图片引用自博客:[连接HBase的正确姿势](https://yq.aliyun.com/articles/581702?spm=a2c4e.11157919.spm-cont-list.1.146c27aeFxoMsN%20%E8%BF%9E%E6%8E%A5HBase%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF) + +在HBase客户端代码中,真正对应socket连接的是RpcConnection对象。HBase使用PoolMap这种数据结构来存储客户端到HBase服务器之间的连接。PoolMap封装了ConcurrentHashMap>的结构,key是ConnectionId(封装了服务器地址和用户ticket),value是一个RpcConnection对象的资源池。当HBase需要连接一个服务器时,首先会根据ConnectionId找到对应的连接池,然后从连接池中取出一个连接对象。 + +```java +@InterfaceAudience.Private +public class PoolMap implements Map { + private PoolType poolType; + + private int poolMaxSize; + + private Map> pools = new ConcurrentHashMap<>(); + + public PoolMap(PoolType poolType) { + this.poolType = poolType; + } + ..... +``` + +HBase中提供了三种资源池的实现,分别是Reusable,RoundRobin和ThreadLocal。具体实现可以通hbase.client.ipc.pool.type配置项指定,默认为Reusable。连接池的大小也可以通过hbase.client.ipc.pool.size配置项指定,默认为1,即每个Server 1个连接。也可以通过修改配置实现: + +```java +config.set("hbase.client.ipc.pool.type",...); +config.set("hbase.client.ipc.pool.size",...); +connection = ConnectionFactory.createConnection(config); +``` + +从以上的表述中,可以看出HBase中Connection类已经实现了对连接的管理功能,所以我们不需要自己在Connection之上再做额外的管理。 + +另外,Connection是线程安全的,而Table和Admin则不是线程安全的,因此正确的做法是一个进程共用一个Connection对象,而在不同的线程中使用单独的Table和Admin对象,且Table和Admin的获取`getTable()`和`getAdmin()`都是轻量级的操作,所以不必担心性能的消耗,在使用完成后建议显示的调用`close()`方法关闭它们。 + + + +## 参考资料 + +1. [连接HBase的正确姿势](https://yq.aliyun.com/articles/581702?spm=a2c4e.11157919.spm-cont-list.1.146c27aeFxoMsN%20%E8%BF%9E%E6%8E%A5HBase%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF) +2. [Apache HBase ™ Reference Guide](http://hbase.apache.org/book.htm) + diff --git a/pictures/deprecated.png b/pictures/deprecated.png new file mode 100644 index 0000000000000000000000000000000000000000..71378641f16c7d8884f5830b13b1d61b4b5a9bdd GIT binary patch literal 32408 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 literal 0 HcmV?d00001 diff --git a/pictures/hbase-arc.png b/pictures/hbase-arc.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce2be97cef5758da11dadd8979663f95458cf34 GIT binary patch literal 46105 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�hEx6dH$DlRR}-=M#$o(SHB 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 A0{{R3 literal 0 HcmV?d00001