SpringBoot - 使用hbase-client操作HBase教程1(基本用法)
阿新 • • 發佈:2021-12-07
HBase是一個分散式的、面向列的開源的NoSQL資料庫。Spring Boot專案如果需要操作HBase通常有如下幾種客戶端可以使用:
- hbase-client:比較底層,需要自己進一步封裝api,而且版本號和安裝的hbase也要匹配,否則會報錯
- spring-data-hadoop:2019年4月5停止維護
- Apache Phoenix:使用SQL的方式來操作HBase。Phoenix的效能很高(進行簡單查詢,其效能量級是毫秒),相對於hbase原生的scan並不會差多少,而對於類似的元件hive、Impala等,效能有著顯著的提升
一、安裝配置
1,環境準備
(1)關於HBase的安裝,可以參考我之前寫的文章:(2)同時HBase伺服器主機名不能為localhost或者VM-16-6-centos,否則客戶端無法連線,具體參考我另一篇文章:
2,專案配置
(1)首先編輯專案的pom.xml檔案,新增hbase-client依賴:<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>2.3.0</version> </dependency>
(2)然後在application.properties中新增HBase相關配置(即ZooKeeper的地址和埠):
# HBase 資料來源配置
hbase.config.hbase.zookeeper.quorum=86.168.xx.xx
hbase.config.hbase.zookeeper.property.clientPort=2181
yml版本
hbase: config: hbase: zookeeper: property: clientPort: 2181 quorum: 81.68.xx.xx
3,編寫工具類
(1)首先編寫HBaseConfig.java來讀取配置檔案,獲取hbase引數:@Configuration @ConfigurationProperties(prefix = "hbase") public class HBaseConfig { private Map<String, String> config = new HashMap<>(); public Map<String, String> getConfig() { return config; } public void setConfig(Map<String, String> config) { this.config = config; } public org.apache.hadoop.conf.Configuration configuration() { org.apache.hadoop.conf.Configuration configuration = HBaseConfiguration.create(); //此處可自己自定義和改造 拓展用 // configuration.set(HBASE_QUORUM, "81.68.xx.xx:2181"); // configuration.set(HBASE_ROOTDIR, "/"); // configuration.set(HBASE_ZNODE_PARENT, "/hbase"); for(Map.Entry<String, String> map : config.entrySet()){ configuration.set(map.getKey(), map.getValue()); } return configuration; } @Bean public Admin admin() { Admin admin = null; try { Connection connection = ConnectionFactory.createConnection(configuration()); admin = connection.getAdmin(); } catch (IOException e) { e.printStackTrace(); } return admin; } }
(2)由於hbase-client比較底層,我們還要封裝一個HBaseUtils.java工具類,實現建立表、插入、讀取、刪除資料:
@Service public class HBaseUtils { @Autowired private Admin hbaseAdmin; /** * 判斷表是否存在 * * @param tableName 表名 * @return true/false */ public boolean isExists(String tableName) { boolean tableExists = false; try { TableName table = TableName.valueOf(tableName); tableExists = hbaseAdmin.tableExists(table); } catch (IOException e) { e.printStackTrace(); } return tableExists; } /** * 建立表 * @param tableName 表名 * @param columnFamily 列族 * @return true/false */ public boolean createTable(String tableName, List<String> columnFamily) { return createTable(tableName, columnFamily, null); } /** * 預分割槽建立表 * @param tableName 表名 * @param columnFamily 列族 * @param keys 分割槽集合 * @return true/false */ public boolean createTable(String tableName, List<String> columnFamily, List<String> keys) { if (!isExists(tableName)) { try { TableName table = TableName.valueOf(tableName); HTableDescriptor desc = new HTableDescriptor(table); for (String cf : columnFamily) { desc.addFamily(new HColumnDescriptor(cf)); } if (keys == null) { hbaseAdmin.createTable(desc); } else { byte[][] splitKeys = getSplitKeys(keys); hbaseAdmin.createTable(desc, splitKeys); } return true; } catch (IOException e) { e.printStackTrace(); } } else { System.out.println(tableName + "is exists!!!"); return false; } return false; } /** * 刪除表 * * @param tableName 表名 */ public void dropTable(String tableName) throws IOException { if (isExists(tableName)) { TableName table = TableName.valueOf(tableName); hbaseAdmin.disableTable(table); hbaseAdmin.deleteTable(table); } } /** * 插入資料(單條) * @param tableName 表名 * @param rowKey rowKey * @param columnFamily 列族 * @param column 列 * @param value 值 * @return true/false */ public boolean putData(String tableName, String rowKey, String columnFamily, String column, String value) { return putData(tableName, rowKey, columnFamily, Arrays.asList(column), Arrays.asList(value)); } /** * 插入資料(批量) * @param tableName 表名 * @param rowKey rowKey * @param columnFamily 列族 * @param columns 列 * @param values 值 * @return true/false */ public boolean putData(String tableName, String rowKey, String columnFamily, List<String> columns, List<String> values) { try { Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Put put = new Put(Bytes.toBytes(rowKey)); for (int i=0; i<columns.size(); i++) { put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columns.get(i)), Bytes.toBytes(values.get(i))); } table.put(put); table.close(); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** * 獲取資料(全表資料) * @param tableName 表名 * @return map */ public List<Map<String, String>> getData(String tableName) { List<Map<String, String>> list = new ArrayList<>(); try { Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Scan scan = new Scan(); ResultScanner resultScanner = table.getScanner(scan); for(Result result : resultScanner) { HashMap<String, String> map = new HashMap<>(); //rowkey String row = Bytes.toString(result.getRow()); map.put("row", row); for (Cell cell : result.listCells()) { //列族 String family = Bytes.toString(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); //列 String qualifier = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); //值 String data = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); map.put(family + ":" + qualifier, data); } list.add(map); } table.close(); } catch (IOException e) { e.printStackTrace(); } return list; } /** * 獲取資料(根據傳入的filter) * @param tableName 表名 * @param filter 過濾器 * @return map */ public List<Map<String, String>> getData(String tableName, Filter filter) { List<Map<String, String>> list = new ArrayList<>(); try { Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Scan scan = new Scan(); // 新增過濾器 scan.setFilter(filter); ResultScanner resultScanner = table.getScanner(scan); for(Result result : resultScanner) { HashMap<String, String> map = new HashMap<>(); //rowkey String row = Bytes.toString(result.getRow()); map.put("row", row); for (Cell cell : result.listCells()) { //列族 String family = Bytes.toString(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); //列 String qualifier = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); //值 String data = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); map.put(family + ":" + qualifier, data); } list.add(map); } table.close(); } catch (IOException e) { e.printStackTrace(); } return list; } /** * 獲取資料(根據rowkey) * @param tableName 表名 * @param rowKey rowKey * @return map */ public Map<String, String> getData(String tableName, String rowKey) { HashMap<String, String> map = new HashMap<>(); try { Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Get get = new Get(Bytes.toBytes(rowKey)); Result result = table.get(get); if (result != null && !result.isEmpty()) { for (Cell cell : result.listCells()) { //列族 String family = Bytes.toString(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); //列 String qualifier = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); //值 String data = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); map.put(family + ":" + qualifier, data); } } table.close(); } catch (IOException e) { e.printStackTrace(); } return map; } /** * 獲取資料(根據rowkey,列族,列) * @param tableName 表名 * @param rowKey rowKey * @param columnFamily 列族 * @param columnQualifier 列 * @return map */ public String getData(String tableName, String rowKey, String columnFamily, String columnQualifier) { String data = ""; try { Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Get get = new Get(Bytes.toBytes(rowKey)); get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columnQualifier)); Result result = table.get(get); if (result != null && !result.isEmpty()) { Cell cell = result.listCells().get(0); data = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); } table.close(); } catch (IOException e) { e.printStackTrace(); } return data; } /** * 刪除資料(根據rowkey) * @param tableName 表名 * @param rowKey rowKey */ public void deleteData(String tableName, String rowKey) throws IOException{ Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Delete delete = new Delete(Bytes.toBytes(rowKey)); table.delete(delete); table.close(); } /** * 刪除資料(根據rowkey,列族) * @param tableName 表名 * @param rowKey rowKey * @param columnFamily 列族 */ public void deleteData(String tableName, String rowKey, String columnFamily) throws IOException{ Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Delete delete = new Delete(Bytes.toBytes(rowKey)); delete.addFamily(columnFamily.getBytes()); table.delete(delete); table.close(); } /** * 刪除資料(根據rowkey,列族) * @param tableName 表名 * @param rowKey rowKey * @param columnFamily 列族 * @param column 列 */ public void deleteData(String tableName, String rowKey, String columnFamily, String column) throws IOException{ Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); Delete delete = new Delete(Bytes.toBytes(rowKey)); delete.addColumn(columnFamily.getBytes(), column.getBytes()); table.delete(delete); table.close(); } /** * 刪除資料(多行) * @param tableName 表名 * @param rowKeys rowKey集合 */ public void deleteData(String tableName, List<String> rowKeys) throws IOException{ Table table = hbaseAdmin.getConnection().getTable(TableName.valueOf(tableName)); List<Delete> deleteList = new ArrayList<>(); for(String row : rowKeys){ Delete delete = new Delete(Bytes.toBytes(row)); deleteList.add(delete); } table.delete(deleteList); table.close(); } /** * 分割槽【10, 20, 30】 -> ( ,10] (10,20] (20,30] (30, ) * @param keys 分割槽集合[10, 20, 30] * @return byte二維陣列 */ private byte[][] getSplitKeys(List<String> keys) { byte[][] splitKeys = new byte[keys.size()][]; TreeSet<byte[]> rows = new TreeSet<>(Bytes.BYTES_COMPARATOR); for(String key : keys) { rows.add(Bytes.toBytes(key)); } int i = 0; for (byte[] row : rows) { splitKeys[i] = row; i ++; } return splitKeys; } }
附:使用樣例
(1)下面建立一個Controller呼叫HBaseUtils來操作HBase資料庫:
@RestController @AllArgsConstructor @RequestMapping("/common/front") public class FrontController { @Autowired private HBaseUtils hbaseUtils; @GetMapping("/test") public void test() throws IOException { System.out.println("---開始建立test表---"); hbaseUtils.createTable("test", Arrays.asList("cf")); System.out.println("---判斷test表是否存在---"); Boolean t = hbaseUtils.isExists("test"); System.out.println(t); System.out.println("\n---插入一列資料---"); hbaseUtils.putData("test", "row1", "cf", "a", "value1-1"); System.out.println("\n---插入多列資料---"); hbaseUtils.putData("test", "row2", "cf", Arrays.asList("a", "b", "c"), Arrays.asList("value2-1", "value2-2", "value2-3")); System.out.println("\n---根據rowkey、列族、列查詢資料---"); String columnData = hbaseUtils.getData("test", "row2", "cf", "b"); System.out.println(columnData); System.out.println("\n---根據rowkey查詢資料---"); Map<String, String> rowData = hbaseUtils.getData("test", "row2"); System.out.println(rowData); System.out.println("\n---查詢全表資料---"); List<Map<String, String>> tableData = hbaseUtils.getData("test"); System.out.println(tableData); System.out.println("\n---根據rowkey、列族、列刪除資料---"); hbaseUtils.deleteData("test", "row2", "cf", "b"); System.out.println("\n---根據rowkey、列族刪除資料---"); hbaseUtils.deleteData("test", "row2", "cf"); System.out.println("\n---根據rowkey刪除資料---"); hbaseUtils.deleteData("test", "row2"); System.out.println("\n---根據rowkey批量刪除資料---"); hbaseUtils.deleteData("test", Arrays.asList("row1", "row2")); System.out.println("\n---刪除表---"); hbaseUtils.dropTable("test"); } }
2)使用瀏覽器訪問/test介面,可以看到控制檯輸出如下:
早年同窗始相知,三載瞬逝情卻萌。年少不知愁滋味,猶讀紅豆生南國。別離方知相思苦,心田紅豆根以生。