SpringBoot整合Hbase的實現示例
簡介
當單表資料量過大的時候,關係性資料庫會出現效能瓶頸,這時候我們就可以用NoSql,比如Hbase就是一個不錯的解決方案。接下來是用Spring整合Hbase的實際案例,且在最後會給出整合中可能會出現的問題,以及解決方案。這裡我是用本地Windows的IDEA,與區域網的偽分佈Hbase叢集做的連線,其中Hbase叢集包括的元件有:Jdk1.8、Hadoop2.7.6、ZooKeeper3.4.10、Hbase2.0.1,因為這裡只是開發環境,所以做一個偽分佈的就好,之後部署的時候再按生產環境要求來即可
整合步驟
目錄結構
pom.xml
這裡要匯入Hbase連線所需要包,需要找和你Hbase版本一致的包
<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>2.0.1</version> </dependency>
hbase-site.xml
我是用的配置檔案連線方法,這個配置檔案你在hbase的安裝目錄下的conf目錄就可以找到,然後你直接把它複製到專案的resources目錄下就好,當然你也可以用application.properties配置檔案外加註入和程式碼的方式代替這個配置檔案
HBaseConfig.java
這裡因為只需連線Hbase就沒連線Hadoop,如果要連線Hadoop,Windows下還要下載winutils.exe工具,後面會介紹
@Configuration public class HBaseConfig { @Bean public HBaseService getHbaseService() { //設定臨時的hadoop環境變數,之後程式會去這個目錄下的\bin目錄下找winutils.exe工具,windows連線hadoop時會用到 //System.setProperty("hadoop.home.dir","D:\\Program Files\\Hadoop"); //執行此步時,會去resources目錄下找相應的配置檔案,例如hbase-site.xml org.apache.hadoop.conf.Configuration conf = HBaseConfiguration.create(); return new HBaseService(conf); } }
HBaseService.java
這是做連線後的一些操作可以參考之後自己寫一下
public class HBaseService { private Logger log = LoggerFactory.getLogger(HBaseService.class); /** * 管理員可以做表以及資料的增刪改查功能 */ private Admin admin = null; private Connection connection = null; public HBaseService(Configuration conf) { try { connection = ConnectionFactory.createConnection(conf); admin = connection.getAdmin(); } catch (IOException e) { log.error("獲取HBase連線失敗!"); } } /** * 建立表 create <table>,{NAME => <column family>,VERSIONS => <VERSIONS>} */ public boolean creatTable(String tableName,List<String> columnFamily) { try { //列族column family List<ColumnFamilyDescriptor> cfDesc = new ArrayList<>(columnFamily.size()); columnFamily.forEach(cf -> { cfDesc.add(ColumnFamilyDescriptorBuilder.newBuilder( Bytes.toBytes(cf)).build()); }); //表 table TableDescriptor tableDesc = TableDescriptorBuilder .newBuilder(TableName.valueOf(tableName)) .setColumnFamilies(cfDesc).build(); if (admin.tableExists(TableName.valueOf(tableName))) { log.debug("table Exists!"); } else { admin.createTable(tableDesc); log.debug("create table Success!"); } } catch (IOException e) { log.error(MessageFormat.format("建立表{0}失敗",tableName),e); return false; } finally { close(admin,null,null); } return true; } /** * 查詢所有表的表名 */ public List<String> getAllTableNames() { List<String> result = new ArrayList<>(); try { TableName[] tableNames = admin.listTableNames(); for (TableName tableName : tableNames) { result.add(tableName.getNameAsString()); } } catch (IOException e) { log.error("獲取所有表的表名失敗",e); } finally { close(admin,null); } return result; } /** * 遍歷查詢指定表中的所有資料 */ public Map<String,Map<String,String>> getResultScanner(String tableName) { Scan scan = new Scan(); return this.queryData(tableName,scan); } /** * 通過表名及過濾條件查詢資料 */ private Map<String,String>> queryData(String tableName,Scan scan) { // <rowKey,對應的行資料> Map<String,String>> result = new HashMap<>(); ResultScanner rs = null; //獲取表 Table table = null; try { table = getTable(tableName); rs = table.getScanner(scan); for (Result r : rs) { // 每一行資料 Map<String,String> columnMap = new HashMap<>(); String rowKey = null; // 行鍵,列族和列限定符一起確定一個單元(Cell) for (Cell cell : r.listCells()) { if (rowKey == null) { rowKey = Bytes.toString(cell.getRowArray(),cell.getRowOffset(),cell.getRowLength()); } columnMap.put( //列限定符 Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()),//列族 Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength())); } if (rowKey != null) { result.put(rowKey,columnMap); } } } catch (IOException e) { log.error(MessageFormat.format("遍歷查詢指定表中的所有資料失敗,tableName:{0}",e); } finally { close(null,rs,table); } return result; } /** * 為表新增或者更新資料 */ public void putData(String tableName,String rowKey,String familyName,String[] columns,String[] values) { Table table = null; try { table = getTable(tableName); putData(table,rowKey,tableName,familyName,columns,values); } catch (Exception e) { log.error(MessageFormat.format("為表新增 or 更新資料失敗,tableName:{0},rowKey:{1},familyName:{2}",familyName),table); } } private void putData(Table table,String tableName,String[] values) { try { //設定rowkey Put put = new Put(Bytes.toBytes(rowKey)); if (columns != null && values != null && columns.length == values.length) { for (int i = 0; i < columns.length; i++) { if (columns[i] != null && values[i] != null) { put.addColumn(Bytes.toBytes(familyName),Bytes.toBytes(columns[i]),Bytes.toBytes(values[i])); } else { throw new NullPointerException(MessageFormat.format( "列名和列資料都不能為空,column:{0},value:{1}",columns[i],values[i])); } } } table.put(put); log.debug("putData add or update data Success,rowKey:" + rowKey); table.close(); } catch (Exception e) { log.error(MessageFormat.format( "為表新增 or 更新資料失敗,e); } } /** * 根據表名獲取table */ private Table getTable(String tableName) throws IOException { return connection.getTable(TableName.valueOf(tableName)); } /** * 關閉流 */ private void close(Admin admin,ResultScanner rs,Table table) { if (admin != null) { try { admin.close(); } catch (IOException e) { log.error("關閉Admin失敗",e); } if (rs != null) { rs.close(); } if (table != null) { rs.close(); } if (table != null) { try { table.close(); } catch (IOException e) { log.error("關閉Table失敗",e); } } } } }
HBaseApplicationTests.java
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest class HBaseApplicationTests { @Resource private HBaseService hbaseService; //測試建立表 @Test public void testCreateTable() { hbaseService.creatTable("test_base",Arrays.asList("a","back")); } //測試加入資料 @Test public void testPutData() { hbaseService.putData("test_base","000001","a",new String[]{ "project_id","varName","coefs","pvalues","tvalues","create_time"},new String[]{"40866","mob_3","0.9416","0.0000","12.2293","null"}); hbaseService.putData("test_base","000002","idno_prov","0.9317","9.8679","000003","education","0.8984","25.5649","null"}); } //測試遍歷全表 @Test public void testGetResultScanner() { Map<String,String>> result2 = hbaseService.getResultScanner("test_base"); System.out.println("-----遍歷查詢全表內容-----"); result2.forEach((k,value) -> { System.out.println(k + "--->" + value); }); } }
執行結果
Hbase資料庫查詢結果
IDEA的遍歷結果
報錯與解決方案
報錯一
解決方案:
這是引數配置的有問題,如果你是用hbase-site.xml配置檔案配置的引數,那麼檢查它,用程式碼配置就檢查程式碼引數
報錯二
解決方案:
更改windows本地hosts檔案,C:\Windows\System32\drivers\etc\hosts,新增Hbase服務所在主機地址與主機名稱,這裡你如果儲存不了hosts檔案,把它拉出到桌面改好再拉回即可
報錯三
解決方案:
這是因為在Windows下連線Hadoop需要一個叫Winutils.exe的工具,並且從原始碼可知,它會去讀你Windows下的環境變數,如果你不想在本地設定,可以用方法System.setProperty()設定實時環境變數,另外,如果你只用Hbase,其實這個報錯並不影響你使用Hbase服務
程式碼地址
https://github.com/xiaoxiamo/SpringBoot_HBase
到此這篇關於SpringBoot整合Hbase的實現示例的文章就介紹到這了,更多相關SpringBoot整合Hbase內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!