HBase是一個基於HDFS的非關系型數據庫(海量數據存儲)
HBase的特點
1.海量數據存儲,HBase中的表可以容納上百億行x上百萬列的數據。
2.列式存儲,HBase中的數據是基於列進行存儲的,能夠動態的增加和刪除列。
3.准實時查詢,HBase在海量的數據量下能夠接近准實時的查詢(百毫秒以內)
4.多版本,HBase中每一列的數據都有多個版本。
5.高可靠性,HBase中的數據存儲於HDFS中且依賴於Zookeeper進行Master和RegionServer的協調管理。
1.HBase的表結構

HBase中的表由RowKey、ColumnFamily、Column、Timestamp組成。
RowKey
記錄的唯一標識,相當於關系型數據庫中的主鍵。
RowKey的最大長度為64KB且按字典順序進行排序存儲。
HBase會自動為RowKey加上索引,當按RowKey查詢時速度會很快。
ColumnFamily
列簇是列的命名空間,是邏輯上類型相同的一組列,每個列簇下可以有任意數量的列,HBase在創建表時只需要指定表名以及列簇(表中的列簇最好不超過5個)
列簇下的列有着相同的前綴,使用冒號來對列簇和列名進行分隔。
Column
當創建了一張HBase的表時,默認只有列簇,列只有在插入數據后才存在(列在列簇下是有序的),為空的列不占用存儲空間。
Timestamp
每個列的value都有多個版本,每個版本對應一個時間戳,在進行插入時由HBase自動進行賦值。
2.HBase的物理模型
2.1 Region

HBase表中的數據存儲在Region當中,每個Region都包含MemoryStore和StoreFile,MemoryStore位於內存當中,每個列簇都對應一個MemoryStore,而StoreFile存儲在HDFS當中,每當MemoryStore中的數據達到128M時將會生成一個StoreFile並寫入到HDFS中。
由Master將新的Region分配到相應的RegionServer中,實現負載均衡。
2.2 RegionServer

RegionServer負責管理Region,會將Region所產生的StoreFile寫入到HDFS當中,同時當Reigon中的StoreFile超過一定的數量時,會對StoreFile進行合並,當StoreFile的文件大小達到指定的閥值時,會對Region進行切分。
RegionServer負責對表中的數據進行操作(插入、刪除、查詢、更新)
2.3 Master

Master負責對表進行操作,同時當RegionServer對Region進行切分后,Master會將新的Region分配給合適RegionServer進行管理(負載均衡),當RegionServer宕機后負責RegionServer上的Region遷移(通過WAL日志)
如果Master失效了僅會導致mete數據和表無法被修改,表中的數據仍然可以進行讀取和寫入。
2.4 關於Zookeeper在HBase中的作用
當HBase集群啟動后,Master和RegionServer會分別向Zookeeper進行注冊,並且在Zookeeper中保存meta表數據、Region與RegionServer的關系,以及RegionServer的訪問地址等信息。
meta表中維護着TableName與RowKey、RowKey與Region的關系。
1.存放HBase的meta表數據、Region與RegionServer的關系、以及RegionServer的訪問地址等信息。
2.保證Master的高可用,當狀態為Active的Master無法對外提供服務時,會將狀態為StandBy的Master切換為Active狀態。
3.實時監控RegionServer,當某個RegionServer節點無法提供服務時將會通知Master,由Master進行RegionServer上的Region遷移。
2.5 HBase處理讀請求的流程
1.HBase Client連接Zookeeper,根據TableName和RowKey從Zookeeper中查詢這些記錄對應存放的Region以及所關聯的RegionServe。
2.HBase Client請求這些RegionServer並找到對應的Region。
3.如果Region的MemoryStore中存在目標的RowKey則直接從MemoryStore中進行查詢,否則從StoreFile中進行查詢。
2.6 HBase處理寫請求的流程
1.HBase Client連接Zookeeper,根據TableName找到其Region列表及其關聯的RegionServer。
2.然后通過一定的算法計算出數據要寫入的Region,並依次連接要寫入的Region其對應的RegionServer。
3.然后把數據寫入到HLog和Region的MemoryStore中。
4.每當MemoryStore中的大小達到128M時,會生成一個StoreFile,並寫入到HDFS中。
5.當StoreFile的數量超過一定時,會進行StoreFile的合並,將多個StoreFile文件合並成一個StoreFile,當StoreFile的文件大小超過指定的閾值時,會進行Region的切分,由Master將新的Region分配給合適的RegionServer進行管理(負載均衡)
HBase Client會在第一次讀取或寫入時才需要連接Zookeeper,會將Zookeeper中的相關數據緩存到本地,往后直接從本地進行查詢,當Zookeeper中的信息發生改變時,將會通過通知機制去通知HBase Client進行更新。
2.7 HBase在HDFS中的目錄

tmp目錄:當創建和刪除HBase的表時,會將表移動到該目錄中進行操作。
MasterProcWALs目錄:預寫日志目錄,主要用於存儲Master的操作日志。
WALs目錄:預寫日志目錄,主要用於存儲RegionServer的操作日志。
data目錄:存放Region中的StoreFile。
hbase.id文件:HBase集群的唯一標識。
hbase.version文件:HBase集群的版本號。
oldWALs目錄:當WALs目錄下的日志文件超過一定時間后,會將其移動到oldWALs目錄中,Master會定期進行清理。
3.搭建HBase集群
3.1 安裝JDK
由於HBase是通過JAVA語言編寫的,因此需要安裝JDK並配置好JAVA_HOME環境變量。

3.2 啟動HDFS集群
由於HBase是基於HDFS的,因此需要安裝Hadoop並啟動HDFS集群。

3.3 啟動Zookeeper集群
由於HBase需要在Zookeeper中保存meta信息以及Region與RegionServer的關系,同時需要依賴Zookeeper保證Master節點的高可用,因此需要搭建Zookeeper集群(HDFS的NameNode也需要通過Zookeeper保證高可用)



3.4 安裝HBase
1.從CDH中下載HBase並進行解壓 。

3.5 修改配置
1.修改hbase-env.sh配置文件
#設置JDK的安裝目錄
export JAVA_HOME=/usr/jdk8/jdk1.8.0_161
#true則使用hbase自帶的zk服務,false則使用外部的zk服務.
export HBASE_MANAGES_ZK=flase
2.修改hbase-site.xml配置文件
<configuration> <!-- 指定HBase日志的存放目錄 --> <property> <name>hbase.tmp.dir</name> <value>/usr/hbase/hbase-1.2.8/logs</value> </property> <!-- 指定HBase中的數據存儲在HDFS中的目錄 --> <property> <name>hbase.rootdir</name> <value>hdfs://nameservice:8020/hbase</value> </property> <!-- 設置是否是分布式 --> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <!-- 指定HBase使用的ZK地址 --> <property> <name>hbase.zookeeper.quorum</name> <value>192.168.1.80:2181,192.168.1.81:2181,192.168.1.82:2181</value> </property> </configuration>
4.修改regionservers文件,配置充當RegionServer的節點

值可以是主機名或者IP地址。
如果Hadoop配置了HDFS高可用集群,那么就會有兩個NameNode和一個NameService,此時就需要將HDFS的core-site.xml和hdfs-site.xml配置文件復制到HBase的conf目錄下,且hbase-site.xml配置文件中的hbase.rootdir配置項的HDFS地址要指向NameService的名稱。
5.NTP時間同步
NTP是一個時間服務器,作用是使集群中的各個節點的時間都保持一致。
由於在HBase集群中,Zookeeper與HBase對時間的要求較高,如果兩個節點之間的時間相差過大,那么整個集群就會崩潰,因此需要使各個節點的時間都保持一致。
#查看是否安裝了NTP服務
rpm -qa|grep ntp
#安裝NTP服務
yum install ntp -y
#從NTP服務器中獲取時間並同步本地
ntpdate 192.168.1.80
在實際的應用場景中,可以自己搭建NTP服務器,也可以使用第三方開源的NTP服務器,如阿里等。
使用 “ntpdate NTP服務器地址” 命令從NTP服務器中獲取時間並同步本地,一般配合Linux的crontab使用,每隔5分鍾進行一次時間的同步。
3.6 啟動集群
bin/start-hbase.sh

當執行start-hbase.sh命令后,會在本節點中啟動一個Master和一個RegionServer進程,並通過SSH訪問其它節點啟動RegionServer進程。


3.7 配置Master節點的高可用
由於HBase中Master節點的高可用是通過Zookeeper進行協調的,需要在其他節點中手動啟動Master,當狀態為Active的Master無法對外提供服務時,會將處於StandBy的Master切換為Active狀態,對外提供服務。

3.8 HBase的可視化管理界面
當HBase集群啟動后,可以訪問http://localhost:16030,進入HBase的可視化管理界面。

4.使用Shell操作HBase
#進入HBase的可執行命名窗口
bin/hbase shell
#創建表
create 'tableName' , 'columnFamily' , 'columnFamily...'
#添加和更新記錄
put 'tableName' , 'rowkey' , 'columnFamily:column' , 'value'
#查詢記錄
get 'tableName' , 'rowkey'
#查看表中的所有記錄
scan 'tableName'
#查看表中指定列的所有記錄
scan 'tableName' , {COLUMNS=>'columnFamily:column'}
#統計表的記錄數
count 'tableName'
#刪除整條記錄
deleteall 'tableName' , 'rowkey'
#刪除記錄中的某一列
delete 'tableName' , 'rowkey' ,'columnFamily:column'
#禁用表
disable 'tableName'
#啟動表
enable 'tableName'
#查看表是否被禁用
is_disabled 'tableName'
#刪除表
drop 'tableName'
#檢查表是否存在
exists 'tableName'
#查看當前HBase中的表
list
在刪除表時需要禁用表,否則無法刪除。
當使用put命令時,如果RowKey不存在則插入一條記錄,如果Column已存在則更新value,否則插入Column和value。
5.JAVA中操作HBase
5.1 導入相關依賴
<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>2.2.5</version> </dependency>
5.2 初始化配置並獲取連接
static { // 使用Configuration對象封裝連接信息,比如hbase連接的ZK地址以及端口等。 // 默認會加載classpath下的hbase-site.xml配置文件,如果classpath下存在hbase-site.xml配置文件則不需要通過Configuration實例進行連接的配置。 Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", ZK_CLUSTER_HOSTS); configuration.set("hbase.zookeeper.property.clientPort", ZK_CLUSTER_PORT); try { connection = ConnectionFactory.createConnection(configuration); } catch (Exception e) { System.out.println("初始化HBase連接失敗" + e); } }
5.3 對表進行管理
使用Admin對象對表進行管理,通過Connection.getAdmin()方法獲取一個Admin實例。
//判斷表是否存在 boolean tableExists(TableName); //獲取HBase中表的描述器(表信息) TableDescriptor [] listTableDescriptors(Pattern); //獲取HBase中的表名稱 TableName [] listTableNames(); //創建表 void createTable(TableDescriptor); //刪除表 void deleteTable(TableName); //啟用表 void enableTable(TableName); //禁用表 void disableTable(TableName); //判斷表是否是啟用狀態 boolean isTableEnabled(TableName); //判斷表是否是禁用狀態 boolean isTableDisabled(TableName); //為表添加列簇 void addColumnFamily(TableName,ColumnDescriptor); //刪除表中的列簇 void deleteColumnFamily(TableName,byte); //修改表中的列簇 void modifyColumnFamily(TableName,ColumnDescriptor);
5.4 對表中的數據進行增刪改查操作
使用Table對象對表中的數據進行操作,通過Connection.getTable(byte [] tableName)方法獲取一個Table實例。
//判斷指定的RowKey是否存在 boolean exists(Get get); //添加或更新記錄 void put(Put); //批量添加或更新記錄 void put(List<Put>); //根據RowKey獲取記錄 Result get(Get get); //根據多個RowKey獲取記錄 Result [] get(List<Get>); //根據指定的條件掃描表 ResultScanner getScanner(Scan); //根據RowKey刪除記錄 void delete(Delete); //批量根據RowKey刪除記錄 void delete(List<Delete>)
1.使用Put、Delete、Get實例分別用來封裝新增/更新、刪除、查詢操作的參數,通過其構造方法傳入RowKey。
2.put()方法可以用來新增和更新記錄,當RowKey不存在時則創建記錄,否則如果Column相同則更新,否則新增。
3.在進行查詢操作時,會返回Result實例,Result實例包含了一條記錄的完整信息,同時一個Cell對象對應一個ColumnFamily、Column、Value,可以通過CellUtil工具類來獲取Cell實例中對應的ColumnFamily、Column、Value等信息。
4.ResultScanner接口繼承Iterable接口,其泛型是Result,也就是Result的集合,可以直接進行遍歷。
由於HBase是基於列進行存儲的,因此在查詢某些列的數據時效率會很高。
由於大部分API都需要傳入字節數組類型,可以使用HBase提供了Bytes工具類來進行字符串和字節數組之間的轉換。
完整的HBaseUtils
/** * 使用HRecord表示HBase中的一條記錄 */ @Data @Builder(toBuilder = true) public class HRecord { private String rowKey; private List<HColumn> columnList; @Data @Builder public static class HColumn { private String columnFamily; private String column; private String value; } }
/** * @author: Zhuang HaoTang * @create: 2020-06-25 19:58 * @description: */ public class HBaseUtils { /** * ZK集群地址 */ private static final String ZK_CLUSTER_HOSTS = "localhost"; /** * ZK端口 */ private static final String ZK_CLUSTER_PORT = "2181"; /** * HBase全局連接 */ private static Connection connection; static { // 使用Configuration對象封裝連接信息,比如hbase連接的ZK地址以及端口等。 // 默認會加載classpath下的hbase-site.xml配置文件,如果classpath下存在hbase-site.xml配置文件則不需要通過Configuration實例進行連接的配置。 Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", ZK_CLUSTER_HOSTS); configuration.set("hbase.zookeeper.property.clientPort", ZK_CLUSTER_PORT); try { connection = ConnectionFactory.createConnection(configuration); } catch (Exception e) { System.out.println("初始化HBase連接失敗" + e); } } /*---------------------------------------對表進行管理---------------------------------------*/ /** * 創建表 */ public static void createTable(String tableName, String... columnFamilies) throws Exception { Admin admin = connection.getAdmin(); // 表的描述器 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)); // 存儲columnFamily描述器集合 Collection<ColumnFamilyDescriptor> columnFamilyDescriptorsCollection = Lists.newArrayList(); for (String columnFamily : columnFamilies) { // ColumnFamily描述器 ColumnFamilyDescriptor columnFamilyDescriptor = ColumnFamilyDescriptorBuilder.of(columnFamily); columnFamilyDescriptorsCollection.add(columnFamilyDescriptor); } tableDescriptorBuilder.setColumnFamilies(columnFamilyDescriptorsCollection); admin.createTable(tableDescriptorBuilder.build()); } /** * 為表添加列簇 */ public static void addColumnFamily(String tableName, String columnFamily) throws Exception { Admin admin = connection.getAdmin(); admin.addColumnFamily(TableName.valueOf(tableName), ColumnFamilyDescriptorBuilder.of(columnFamily)); } /** * 刪除表中的列簇 */ public static void deleteColumnFamily(String tableName, String columnFamily) throws Exception { Admin admin = connection.getAdmin(); admin.deleteColumnFamily(TableName.valueOf(tableName), Bytes.toBytes(columnFamily)); } /** * 獲取表的描述器(表信息) */ public static List<TableDescriptor> getTableDescriptor(String tableName) throws Exception { Admin admin = connection.getAdmin(); return admin.listTableDescriptors(Pattern.compile(tableName)); } /** * 刪除表 */ public static void deleteTable(String tableName) throws Exception { Admin admin = connection.getAdmin(); if (admin.tableExists(TableName.valueOf(tableName))) { // 先禁用再刪除 admin.disableTable(TableName.valueOf(tableName)); admin.deleteTable(TableName.valueOf(tableName)); } } /*---------------------------------------對表中的數據進行CRUD---------------------------------------*/ /** * 插入或更新記錄 */ public static void insertOrUpdate(String tableName, HRecord record) throws Exception { Table table = connection.getTable(TableName.valueOf(tableName)); Put put = new Put(Bytes.toBytes(record.getRowKey())); record.getColumnList().forEach(column -> put.addColumn(Bytes.toBytes(column.getColumnFamily()), Bytes.toBytes(column.getColumn()), Bytes.toBytes(column.getValue()))); table.put(put); } /** * 批量插入或更新記錄 */ public static void batchInsertOrUpdate(String tableName, Collection<HRecord> records) throws Exception { Table table = connection.getTable(TableName.valueOf(tableName)); List<Put> puts = records.stream().map(record -> { Put put = new Put(Bytes.toBytes(record.getRowKey())); record.getColumnList().forEach(column -> put.addColumn(Bytes.toBytes(column.getColumnFamily()), Bytes.toBytes(column.getColumn()), Bytes.toBytes(column.getValue()))); return put; }).collect(Collectors.toList()); table.put(puts); } /** * 掃描全表 */ public static ResultScanner scan(String tableName) throws Exception { Table table = connection.getTable(TableName.valueOf(tableName)); return table.getScanner(new Scan()); } /** * 掃描表中的某些列 * @param columns key:columnFamily value:Set<column> */ public static ResultScanner scanByColumns(String tableName, Map<String, Set<String>> columns) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Scan scan = new Scan(); for (Map.Entry<String, Set<String>> entry : columns.entrySet()) { String columnFamily = entry.getKey(); entry.getValue().forEach(column -> scan.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column))); } return table.getScanner(scan); } /** * 根據RowKey查詢記錄 */ public static Result getByRowKey(String tableName, String rowKey) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Get get = new Get(Bytes.toBytes(rowKey)); return table.get(get); } /** * 根據RowKey刪除記錄 */ public static void deleteByRowKey(String tableName, String rowKey) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Delete delete = new Delete(Bytes.toBytes(rowKey)); table.delete(delete); } /** * 批量根據RowKey刪除記錄 */ public static void batchDeleteByRowKey(String tableName, Collection<String> rowKeys) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); List<Delete> deletes = rowKeys.stream().map(rowKey -> new Delete(Bytes.toBytes(rowKey))).collect(Collectors.toList()); table.delete(deletes); } /** * 刪除記錄中的某列 */ public static void deleteColumnOfRow(String tableName, String rowKey, String columnFamily, String column) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Delete delete = new Delete(Bytes.toBytes(rowKey)); delete.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column)); table.delete(delete); } }
測試類
/** * @author: Zhuang HaoTang * @create: 2020-06-26 10:12 * @description: */ public class HBaseUtilsTest { private static final String TABLE_NAME = "blacklist_customer_info"; @Test public void testCreateTable() { try { HBaseUtils.createTable(TABLE_NAME, "cf1", "cf2"); } catch (Exception e) { e.printStackTrace(); } } @Test public void testAddColumnFamily() { try { HBaseUtils.addColumnFamily(TABLE_NAME, "cf3"); } catch (Exception e) { e.printStackTrace(); } } @Test public void testDeleteColumnFamily() { try { HBaseUtils.deleteColumnFamily(TABLE_NAME, "cf3"); } catch (Exception e) { e.printStackTrace(); } } @Test public void testGetTableDescriptor() throws Exception { TableDescriptor tableDescriptor = Iterables.getOnlyElement(HBaseUtils.getTableDescriptor(TABLE_NAME)); System.out.println("表名:" + tableDescriptor.getTableName()); tableDescriptor.getColumnFamilyNames().forEach(columnFamilyByte -> System.out.println("列簇:" + Bytes.toString(columnFamilyByte))); } @Test public void testDeleteTable() { try { HBaseUtils.deleteTable(TABLE_NAME); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsert() { HRecord record = HRecord.builder().rowKey(UUID.randomUUID().toString().replace("-", "")).build(); List<HRecord.HColumn> columnList = Lists.newArrayList(); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("庄浩棠").build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("idcard").value("440112************").build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("phone").value("156****8105").build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("risk_status").value("2").build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf2").column("idcard_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("440112************"))).build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf2").column("phone_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("156****8105"))).build()); record = record.toBuilder().columnList(columnList).build(); try { HBaseUtils.insertOrUpdate(TABLE_NAME, record); } catch (Exception e) { e.printStackTrace(); } } @Test public void testBatchInsert() { HRecord record1 = HRecord.builder().rowKey(UUID.randomUUID().toString().replace("-", "")).build(); List<HRecord.HColumn> columnList1 = Lists.newArrayList(); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("梁紅英").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("idcard").value("130404************").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("phone").value("186****6666").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("risk_status").value("2").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf2").column("idcard_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("130404************"))).build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf2").column("phone_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("186****6666"))).build()); record1 = record1.toBuilder().columnList(columnList1).build(); HRecord record2 = HRecord.builder().rowKey(UUID.randomUUID().toString().replace("-", "")).build(); List<HRecord.HColumn> columnList2 = Lists.newArrayList(); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("夕涵山").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("idcard").value("360731************").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("phone").value("145****8637").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("risk_status").value("2").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf2").column("idcard_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("360731************"))).build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf2").column("phone_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("145****8637"))).build()); record2 = record2.toBuilder().columnList(columnList2).build(); try { HBaseUtils.batchInsertOrUpdate(TABLE_NAME, Lists.newArrayList(record1, record2)); } catch (Exception e) { e.printStackTrace(); } } @Test public void testUpdate() { String rowKey = "10e21b2a08614daca6de0d3a4c2d0fd0"; HRecord record = HRecord.builder().rowKey(rowKey).build(); List<HRecord.HColumn> columnList = Lists.newArrayList(); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("zhuanght").build()); columnList.add(HRecord.HColumn.builder().columnFamily("cf1").column("idcard").value("440112************").build()); record = record.toBuilder().columnList(columnList).build(); try { HBaseUtils.insertOrUpdate(TABLE_NAME, record); } catch (Exception e) { e.printStackTrace(); } } @Test public void testBatchUpdate() { String rowKey1 = "10e21b2a08614daca6de0d3a4c2d0fd0"; HRecord record1 = HRecord.builder().rowKey(rowKey1).build(); List<HRecord.HColumn> columnList1 = Lists.newArrayList(); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("庄浩棠").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("address").value("廣州市").build()); columnList1.add(HRecord.HColumn.builder().columnFamily("cf1").column("phone_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("136****1502"))).build()); record1 = record1.toBuilder().columnList(columnList1).build();//6 String rowKey2 = "f0f0492c36fb4792be266e922f042685"; HRecord record2 = HRecord.builder().rowKey(rowKey2).build(); List<HRecord.HColumn> columnList2 = Lists.newArrayList(); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("name").value("夕涵山").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf1").column("idcard").value("360731************").build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf2").column("idcard_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("360731************"))).build()); columnList2.add(HRecord.HColumn.builder().columnFamily("cf2").column("phone_md5").value(MD5Hash.getMD5AsHex(Bytes.toBytes("145****8637"))).build()); record2 = record2.toBuilder().columnList(columnList2).build(); try { HBaseUtils.batchInsertOrUpdate(TABLE_NAME, Lists.newArrayList(record1, record2)); } catch (Exception e) { e.printStackTrace(); } } @Test public void testScanner() { try { ResultScanner resultScanner = HBaseUtils.scan("blacklist_customer_info"); for (Result result : resultScanner) { StringBuilder recordStr = new StringBuilder(String.format("rowKey:%s", Bytes.toString(result.getRow()))); result.listCells().forEach(cell -> recordStr.append(String.format("\n%s:%s--》%s", Bytes.toString(CellUtil.cloneFamily(cell)), Bytes.toString(CellUtil.cloneQualifier(cell)), Bytes.toString(CellUtil.cloneValue(cell))))); System.out.println("===================================================================="); System.out.println(recordStr); } } catch (Exception e) { e.printStackTrace(); } } @Test public void testScanByColumns() { Map<String, Set<String>> columns = Maps.newHashMap(); columns.put("cf1", Sets.newHashSet("name", "idcard")); columns.put("cf2", Sets.newHashSet("idcard_md5")); try { ResultScanner resultScanner = HBaseUtils.scanByColumns(TABLE_NAME, columns); for (Result result : resultScanner) { StringBuilder recordStr = new StringBuilder(String.format("rowKey:%s", Bytes.toString(result.getRow()))); result.listCells().forEach(cell -> recordStr.append(String.format("\n%s:%s--》%s", Bytes.toString(CellUtil.cloneFamily(cell)), Bytes.toString(CellUtil.cloneQualifier(cell)), Bytes.toString(CellUtil.cloneValue(cell))))); System.out.println("===================================================================="); System.out.println(recordStr); } } catch (IOException e) { e.printStackTrace(); } } @Test public void testGetByRowKey() { String tableName = "blacklist_customer_info"; String rowKey = "7d86f464b4ba459cac828cdd3772b2ba"; try { Result result = HBaseUtils.getByRowKey(tableName, rowKey); StringBuilder recordStr = new StringBuilder(String.format("rowKey:%s", Bytes.toString(result.getRow()))); result.listCells().forEach(cell -> recordStr.append(String.format("\n%s:%s--》%s", Bytes.toString(CellUtil.cloneFamily(cell)), Bytes.toString(CellUtil.cloneQualifier(cell)), Bytes.toString(CellUtil.cloneValue(cell))))); System.out.println(recordStr); } catch (IOException e) { e.printStackTrace(); } } @Test public void testDeleteByRowKey() { String tableName = "blacklist_customer_info"; String rowKey = "7d86f464b4ba459cac828cdd3772b2ba"; try { HBaseUtils.deleteByRowKey(tableName, rowKey); } catch (IOException e) { e.printStackTrace(); } } @Test public void testBatchDeleteByRowKey() { String tableName = "blacklist_customer_info"; List<String> rowKeys = Lists.newArrayList("423e209fd0d84985a161bbc5a808d67b", "ce6ee0f16b7944f6abbba7762ab177cb"); try { HBaseUtils.batchDeleteByRowKey(tableName, rowKeys); } catch (IOException e) { e.printStackTrace(); } } @Test public void testDeleteColumnOfRow() { String tableName = "blacklist_customer_info"; String rowKey = "10e21b2a08614daca6de0d3a4c2d0fd0"; try { HBaseUtils.deleteColumnOfRow(tableName, rowKey, "cf1", "idcard"); } catch (IOException e) { e.printStackTrace(); } } }

