JAVA连接HBase客户端
接着上篇文章进行代码的实践,从JAVA 客户端对 HBase的客户端进行一系列操作
工具类:HbaseUtil
静态代码块一次性创建连接对象 并赋值
返回连接对象 Connection
Table对象的创建
Admin对象的创建
数据的展示
package cn._doit19.hbase.utils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
/**
* @author:tom
* @Date:Created in 16:36 2020/11/24
* 工具类
*/
public class HbaseUtil {
static Connection conn = null;
static {
//创建连接对象
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "linux01:2181,linux02:2181,linux03:2181");
try {
conn = ConnectionFactory.createConnection(conf);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Table getTable(String tableName) throws Exception {
TableName tbName = TableName.valueOf(tableName);
return conn.getTable(tbName);
}
public static Connection getConn() {
return conn;
}
public static void showData(Result result) {
while (result.advance()) {
Cell cell = result.current();
String row = Bytes.toString(CellUtil.cloneRow(cell));
String cf = Bytes.toString(CellUtil.cloneFamily(cell));
String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));
String val = Bytes.toString(CellUtil.cloneValue(cell));
System.out.println(row + "--->" + cf + "--->" + qualifier + "--->" + val);
}
}
public static Admin getAdmin() throws Exception {
return conn.getAdmin();
}
}
创建表
package cn._doit19.hbase.day01;
import cn._doit19.hbase.utils.HbaseUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
/**
* @author:tom
* @Date:Created in 17:44 2020/11/24
* 创建表
*/
public class Demo03 {
public static void main(String[] args) throws Exception {
Admin admin = HbaseUtil.getAdmin();
TableDescriptorBuilder tb_builder = TableDescriptorBuilder.newBuilder(TableName.valueOf("test_a".getBytes()));
ColumnFamilyDescriptorBuilder cf_builder = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
ColumnFamilyDescriptor cf_desc = cf_builder.build();
tb_builder.setColumnFamily(cf_desc);
TableDescriptor tb_desc = tb_builder.build();
admin.createTable(tb_desc);
}
}
Scan 'table_name' 扫描表 数据 可添加参数 精准扫描查询
package cn._doit19.hbase.day01;
import cn._doit19.hbase.utils.HbaseUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import java.util.Iterator;
/**
* @author:tom
* @Date:Created in 11:56 2020/11/25
* scan ‘tab_name’
*/
public class Demo04 {
public static void main(String[] args) throws Exception {
//获取表对象
Table table = HbaseUtil.getTable("tb_imp");
//scan 扫描表,获取所有的数据
Scan scan = new Scan();
//添加了列族和属性 只要表中所有的 info列族的age属性
scan.addColumn("info".getBytes(), "age".getBytes());
ResultScanner scanner = table.getScanner(scan);
Iterator<Result> iterator = scanner.iterator();
while (iterator.hasNext()) {
Result res = iterator.next();
HbaseUtil.showData(res);
}
}
}
put 时的数据结构 put 'table_name','rowKey','cf_name:qualifier','value'
package cn._doit19.hbase.day01;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Put;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
/**
* @author:tom
* @Date:Created in 15:58 2020/11/25
* put 数据结构
*/
public class PutDetails {
public static void main(String[] args) throws Exception {
//put方法
//put 'a','rk001','cf1:qualifier','value'
//一个rowKey 对应多个单元格 List<Cell> 单元格(cf:qualifier)
// Table tb_user = HbaseUtil.getTable("tb_user");
Put put = new Put("rk001".getBytes());
NavigableMap<byte[], List<Cell>> familyCellMap = put.getFamilyCellMap();
Set<Map.Entry<byte[], List<Cell>>> entries = familyCellMap.entrySet();
//k,v 一个rowKey 对应多个单元格 List<Cell>
for (Map.Entry<byte[], List<Cell>> entry : entries) {
//列族
String cfName = new String(entry.getKey());
List<Cell> cells = entry.getValue();
for (Cell cell : cells) {
//每个单元格的属性
String qualifier = new String(CellUtil.cloneQualifier(cell));
//每个单元格的值
String value = new String(CellUtil.cloneValue(cell));
}
}
// tb_user.put(put);
}
}
HBase写入数据原理解析
写入数据原理图
步骤解析
put 'a','rk001','cf:age',21 客户端要向Hbase中写入数据
1) 客户端向Zookeeper(以下简称zk)发送请求向habse中的a表(default命名空间下)中写入数据
2)zk向客户端返回元数据表meta的位置 (具体在哪个regionserver上)
3)客户端向指定regionserver请求元数据表meta
4)客户端下载缓存到自己的本地(下次就不必再找zk和regionserver要了)
5)客户端进行解析meta表, 解析出rk001所在的hostname和regionname
6)请求指定的机器上的regionserver写数据
7)regionserver接收到数据,并不是马上就写到hdfs中,首先数据是列式存储,每一个列族都有一个store(cf)---->regionserver接收到客户端传入的数据并写入到内存memorystore中
8)memorystore内存中的数据达到128M或者人为强制的进行flush时,它将写入到store file并通过HDFS写入到hdfs的文件当中。store file即hfile
注意点:
1)flush的时机
- 单个的MemoryStore的内存达到128M
- 手动强制进行flush
- 机器的内存达到阈值 所有的memorystore将会被flush走
- 次数达到阈值
2)hbase在hdfs中真实存在的路径为
/hbase/data/namespace/table_name/region_name/cf_name/hfile
HBase读取数据原理解析
读取数据原理图
步骤解析
get 'a','rk001'
1) 向zk集群请求读取数据
2)zk返回元数据meta表的位置
3)客户端向指定regionserver请求下载元数据
4)接收下载存储元数据
5)解析
6)请求对应的regionserver的region读取数据
7)region先从自己的数据块缓存blockCache和内存memoryStore中找值,找到就直接返回
8)找不到,去到HDFS中找,利用布隆过滤器进行查询,往自己的blockCache和memorystore中存储一份,客户端直接从内存中获取。