1 创建Maven项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>doit15-hbase</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>2.0.4</version>
</dependency>
<!-- 使用mr程序操作hbase 数据的导入 -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-mapreduce</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- phoenix 凤凰 用来整合Hbase的工具 -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2 java-API
2.1 客户端连接核心对象
hbase的java客户端连接hbase的时候只需要连接zookeeper集群即可找到Hbase集群的位置
核心对象如下:
- Configuration : HBaseConfiguration.create();
- Connection : ConnectionFactory.createConnection(conf);
- Table : conn.getTable(TableName.valueOf("tb_b")); 可以对表操作 DML
- Admin : conn.getAdmin(); 操作hbase系统 DDL 名称空间 tools ...
package com._51doit.client;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Table;
import java.io.IOException;
/**
* @Auther: 多易教育-行哥
* OBJECT:
* 1 Configuration : HBaseConfiguration.create();
* 2 Connection : ConnectionFactory.createConnection(conf);
* 3 Table : conn.getTable(TableName.valueOf("tb_b")); 可以对表操作 DML
* 4 Admin : conn.getAdmin(); 操作hbase系统 DDL 名称空间 tools ...
*
* @Date: 2020/6/12
* @Description:获取连接hbase的客户端对象
*/
public class ConnectionDemo {
public static void main(String[] args) throws Exception {
// 直接连接ZK集群 就能找到对应的Hbase集群
// 1 创建一个配置信息的对象
Configuration conf = HBaseConfiguration.create();
// 2 设置配置存储 设置ZK集群的位置
conf.set("hbase.zookeeper.quorum" , "linux01:2181,linux02:2181,linux03:2181");
//3 创建连接对象
Connection conn = ConnectionFactory.createConnection(conf);
/**
* conn.getTable() --> Table对象 可以对表操作 DML
* Admin admin = conn.getAdmin() 获取管理对象 操作hbase系统 DDL 名称空间 tools ...
*/
Table tb_b = conn.getTable(TableName.valueOf("tb_b"));
// 获取管理对象
Admin admin = conn.getAdmin();
// 获取系统中所有的用户自定义的表 Hbase中对表的抽象 TableName
TableName[] tableNames = admin.listTableNames() ;
// 变量表
for (TableName tableName : tableNames) {
// 获取表的名称 字节数组
byte[] name = tableName.getName();
// 打印
System.out.println(new String(name));
}
// 释放对象
conn.close();
}
}
2.2 Java-API 名称空间
hbase中的namespace起到是是类似于mysql中数据库的作用
可以将表进行分类别管理 , 在HDFS系统中其实对应不同的文件夹
package com._51doit.client;
import com._51doit.utils.HbaseUtils;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.client.Admin;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: 多易教育-行哥
* @Date: 2020/6/12
* @Description:
* 1 创建一个名称空间 c reateNamespace
* 2 查看系统下所有的名称空间 listNamespaceDescriptors
* 3 修改名称空间 modifyNamespace
* 4 删除 deleteNamespace
*/
public class NameSpaceDemo {
public static void main(String[] args) throws Exception {
// 创建一个名称空间
Admin admin = HbaseUtils.getHbaseAdmin();
admin.deleteNamespace("doit");
admin.close();
}
/**
* 修改名称空间的属性
* @param admin
* @throws IOException
*/
private static void changeNameSpace(Admin admin) throws IOException {
NamespaceDescriptor.Builder doit = NamespaceDescriptor.create("doit");
doit.removeConfiguration("author") ;
doit.addConfiguration("author","JINLONG") ;
NamespaceDescriptor build = doit.build();
// 修改属性
admin.modifyNamespace(build);
}
/**
* 查看系统下所有的名称空间
* 并且查看配置信息
* @param admin
* @throws IOException
*/
private static void getAllNameSpaces(Admin admin) throws IOException {
//查看系统下所有的名称空间
NamespaceDescriptor[] namespaceDescriptors = admin.listNamespaceDescriptors();
// 遍历
for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
// 一个名称空间对象
// 名字
String name = namespaceDescriptor.getName();
// 属性信息
Map<String, String> map = namespaceDescriptor.getConfiguration();
System.out.println(name+"--->"+map.entrySet());
}
}
/**
* 创建名称空间
* @param admin
* @throws IOException
*/
private static void createNameSpace(Admin admin) throws IOException {
// 获取名称空间的构建器
NamespaceDescriptor.Builder doit = NamespaceDescriptor.create("doit");
Map<String,String> map = new HashMap<>() ;
map.put("author" , "DOIT") ;
map.put("desc" ,"my first namespace...");
// 对名称空间的属性设置
doit.addConfiguration(map) ;
//构造名称空间对象
NamespaceDescriptor namespaceDescriptor = doit.build();
// 调用方法 创建
admin.createNamespace(namespaceDescriptor);
}
}
2.3 Java-API 建表
Hbase在建表的时候指定表名和至少一个列族
/**
* @Auther: 多易教育-行哥
* @Date: 2020/6/12
* @Description:
* 1 建表 : 表名和列族是必须
*/
public class TableOperation {
public static void main(String[] args) throws Exception {
Admin admin = HbaseUtils.getHbaseAdmin();
admin.close();
}
/**
* 创建多个列族的表
* @param admin
* @throws IOException
*/
private static void createTableWithMoreColumnFamilies(Admin admin) throws IOException {
//表的构建器 表名 1
TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo3"));
//--------------列族一
// 列族构建器
ColumnFamilyDescriptorBuilder cf1 = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
// 设置数据存储的版本的个数
cf1.setMaxVersions(3) ;
// 设置列族中数据的存储时间 单位秒
cf1.setTimeToLive(240) ;
// 列族的描述对象
ColumnFamilyDescriptor columnFamilyDescriptor1 = cf1.build();
//--------------列族二
// 列族构建器
ColumnFamilyDescriptorBuilder cf2 = ColumnFamilyDescriptorBuilder.newBuilder("cf2".getBytes());
// 设置数据存储的版本的个数
cf2.setMaxVersions(5) ;
// 设置列族中数据的存储时间 单位秒
cf2.setTimeToLive(300) ;
// 列族的描述对象
ColumnFamilyDescriptor columnFamilyDescriptor2 = cf2.build();
// -------存储多个列族
// 存储多个列族对象
List<ColumnFamilyDescriptor> cfs = new ArrayList<>() ;
cfs.add(columnFamilyDescriptor1) ;
cfs.add(columnFamilyDescriptor2) ;
// -------------------表中添加多个列族
// 表的构建器 添加列族
tableDescriptorBuilder.setColumnFamilies(cfs) ;
//表描述对象
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
// 创建表
admin.createTable(tableDescriptor);
}
/**
* 创建一个列族的表
* @param admin
* @throws IOException
*/
private static void createTableWithOnColumnFamily(Admin admin) throws IOException {
//表的构建器 表名
TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo2"));
// 列族构建器
ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
// 设置数据存储的版本的个数
columnFamilyDescriptorBuilder.setMaxVersions(3) ;
// 设置列族中数据的存储时间 单位秒
columnFamilyDescriptorBuilder.setTimeToLive(240) ;
// 列族的描述对象
ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();
// 表中添加列族
// 表的构建器 添加列族
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor) ;
//表描述对象
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
// 创建表
admin.createTable(tableDescriptor);
}
}
2.3.1 预分region表
当创建表以后 .由于表中的数据量比较少所以表默认是一个region , 那么此时在短时间内有大量的插入请求就出现了插入性的热点问题!
我们可以在建表的时候指定多个region来避免这种现象
shell客户端操作
create "tb_spl1" , "cf1" , SPLITS =>['e' , 'm' , 't']
Created table tb_spl1
Took 2.4596 seconds
# 查看表是否进行了预分region操作
hbase(main):010:0> list_regions "tb_spl1"
SERVER_NAME | REGION_NAME | START_KEY | END_KEY | SIZE | REQ | LOCALITY |
--------------------------- | --------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
linux03,16020,1591783680511 | tb_spl1,,1591824125893.63d4e1005eec815e2c6dd3f0b2762631. | | e | 0 | 0 | 0.0 |
linux02,16020,1591783680684 | tb_spl1,e,1591824125893.cfcb6ece7a484e579feb863eb9d0e084. | e | m | 0 | 0 | 0.0 |
linux01,16020,1591783680829 | tb_spl1,m,1591824125893.884c71c0cdca3f52674e39c99d374f38. | m | t | 0 | 0 | 0.0 |
linux02,16020,1591783680684 | tb_spl1,t,1591824125893.3b7eceae97ef9450eee90ca962c4245d. | t | | 0 | 0 | 0.0 |
4 rows
Took 0.0561 seconds
## 查看拆分点key的位置
hbase(main):012:0> locate_region "tb_spl1" , "e"
HOST REGION
linux02:16020 {ENCODED => cfcb6ece7a484e579feb863eb9d0e084, NAME => 'tb_spl1,e,1591824125893.cfcb6ec
e7a484e579feb863eb9d0e084.', STARTKEY => 'e', ENDKEY => 'm'}
1 row(s)
Took 0.0026 seconds
在页面上查看
JAVA-API
public static void main(String[] args) throws Exception {
Admin admin = HbaseUtils.getHbaseAdmin();
// 表的描述器
TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_spl2"));
// 列族的描述器
ColumnFamilyDescriptorBuilder cf = ColumnFamilyDescriptorBuilder.newBuilder("cf".getBytes());
ColumnFamilyDescriptor cfobj = cf.build();
// 添加到表中
tableDescriptorBuilder.setColumnFamily(cfobj);
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
byte[][] keys = new byte[][]{"e".getBytes(), "m".getBytes(),"t".getBytes()} ;
// 建表 指定预分region的key(数组)
admin.createTable(tableDescriptor,keys);
admin.close();
}
2.4 Java-API 修改表结构
-
admin.modifyTable(tableDescriptor); 参数是表对象 可以修改表的列族名 和列族属性 添加删除列族等
-
admin.modifyColumnFamily(TableName.valueOf("tb_demo1"), cfobj); 仅仅可以修改表的某个列族的属性值
/**
* 修改表结构
* @param admin
* @throws IOException
*/
private static void modifyTableDemo(Admin admin) throws IOException {
// TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_demo1"));
ColumnFamilyDescriptorBuilder cf = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
// 仅修改某个列族的属性
cf.setMaxVersions(5);
ColumnFamilyDescriptor cfobj = cf.build();
// 添加到表中
/* tableDescriptorBuilder.setColumnFamily(cfobj);
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
// 添加列族 删除列族
admin.modifyTable(tableDescriptor);
*/
admin.modifyColumnFamily(TableName.valueOf("tb_demo1"), cfobj);
}
2.5 Java-API 删除表 (禁用 是否禁用启用)
- 确定表存在
- 确定表被禁用
/**
* 删除表 先禁用
* @param admin
* @throws IOException
*/
private static void deleteTable(Admin admin) throws IOException {
TableName tn = TableName.valueOf("tb_demo1");
// 如果表存在
if(admin.tableExists(tn)){
admin.disableTable(tn);
if(admin.isTableDisabled(tn)){
admin.deleteTable(tn);
}else{
System.out.println("请先禁用表");
}
}else {
System.out.println("表不存在");
}
}
2.6 Java-API 插入更新数据 put
- put(Put) 插入一行数据
- put(List<Put>) 插入多行数据
- 数据的插入必要的内容 表名 行建 列族:属性 值
public static void main(String[] args) throws Exception {
// 1 获取表对象 DML
Table tb = HbaseUtils.getHbaseTable("tb_spl2");
// tb.getDescriptor().getColumnFamilyNames(); // 获取所有的列族
//2 Put对象 表 行 列族:属性 值
// 参数 行建的值
// Put put = new Put("rk001".getBytes());
/**
* 参数一 列族
* 参数二 属性
* 参数三 值
*/
/* put.addColumn("cf".getBytes(), "uid".getBytes(), "uid001".getBytes());
put.addColumn("cf".getBytes(), "name".getBytes(), "LSS".getBytes());
put.addColumn("cf".getBytes(), "gender".getBytes(), "M".getBytes());*/
// 3 执行嘻插入
// tb.put(put); // rpc请求 一次插入一个属性
List<Put> puts = new ArrayList<>();
Put put1 = new Put("rk002".getBytes());
Put put2 = new Put("rk003".getBytes());
Put put3 = new Put("rk004".getBytes());
put1.addColumn("cf".getBytes(), "uid".getBytes(), "uid002".getBytes());
put1.addColumn("cf".getBytes(), "name".getBytes(), "ZSS".getBytes());
put2.addColumn("cf".getBytes(), "age".getBytes(), "23".getBytes());
put3.addColumn("cf".getBytes(), "addres".getBytes(), "Beijing".getBytes());
put3.addColumn("cf".getBytes(), "name".getBytes(), "gunayu".getBytes());
puts.add(put1);
puts.add(put2);
puts.add(put3);
tb.put(puts);
// 4 释放资源
tb.close();
}
2.6 Java-API 获取数据-get()
- get数据
- 可以获取一行
- 可以获取多行数据List<Get>
- 可以获取列族
- 可以获取列族中的属性
/**
* 获取多行数据
* @param tb
* @throws IOException
*/
private static void getData(Table tb) throws IOException {
Get get1 = new Get("rk001".getBytes()) ;
Get get2 = new Get("rk002".getBytes()) ;
Get get3 = new Get("rk003".getBytes()) ;
// 指定获取数据的 哪个列族的哪个属性
get1.addColumn("cf".getBytes(),"name".getBytes());
// 指定获取哪个列族的数据
get1.addFamily("cf1".getBytes());
List<Get> list = new ArrayList<>() ;
// 将多个get存储在集合中
list.add(get1) ;
list.add(get2) ;
list.add(get3) ;
// 查询多行数据 返回每行组成的数组
Result[] results = tb.get(list);
// 遍历=数组 获取每行数据
for (Result result : results) {
HbaseUtils.showData(result);
}
}
/**
* 获取一行数据
* @param tb
* @throws IOException
*/
private static void getOneRowData(Table tb) throws IOException {
// get对象 代表一行数据 (所有的列族 属性)
Get get = new Get("rk001".getBytes()) ;
// 一行结果数据 有很多单元格 单元格的个数不确定 稀疏性
Result result = tb.get(get);
while(result.advance()){ // 只要有下一个单元格进入循环
// 获取当前的单元格对象
Cell cell = result.current();
/* cell.getFamilyArray() ;//列族
cell.getQualifierArray() ;// 属性
cell.getValueArray() ; // 值*/
byte[] r = CellUtil.cloneRow(cell); // 行
byte[] family = CellUtil.cloneFamily(cell); // 列族
byte[] qualifier = CellUtil.cloneQualifier(cell); // 属性
byte[] value = CellUtil.cloneValue(cell); // 值
System.out.println(" 行: "+new String(r)+" 列族: "+new String(family)+" 属性: "+new String(qualifier)+" 值: "+new String(value));
}
}
封装一个展示数据内容的工具类
/**
* 展示单元格数据
* @param result
*/
public static void showData(Result result){
while(result.advance()){
Cell cell = result.current();
String row = new String(CellUtil.cloneRow(cell));
String family = new String(CellUtil.cloneFamily(cell));
String qualifier = new String(CellUtil.cloneQualifier(cell));
String value = new String(CellUtil.cloneValue(cell));
System.out.println(row+"->"+family+":"+qualifier+"->"+value);
}
}
2.7 Java-API 获取数据-scan()
- 全表扫描数据
- 可以指定扫描范围 scan.withStartRow("rk002".getBytes()) ;// 起始行 包括 scan.withStopRow("rk004".getBytes()); // 结束行不包含
- 可以指定扫面某个列族
- 可以指定扫描某个列族的属性
/**
* 扫面数据
* @param tb
* @throws IOException
*/
private static void scanData(Table tb) throws IOException {
Scan scan = new Scan();// 扫描对象
scan.withStartRow("rk002".getBytes()) ;// 起始行 包括
scan.withStopRow("rk004".getBytes()); // 结束行不包含
ResultScanner scanner = tb.getScanner(scan);
Iterator<Result> iterator = scanner.iterator();
while (iterator.hasNext()){
Result result = iterator.next();
HbaseUtils.showData(result);
}
}
2.8 Java-API 删除数据 delete
- 可以删除一行
- 删除一行的列族
- 删除某一行的列族的属性
- 可以删除多行数据 List<Delete>
public static void main(String[] args) throws Exception {
Table tb = HbaseUtils.getHbaseTable("tb_gy");
// 获取删除对象 指定行
Delete delete = new Delete(Bytes.toBytes("sb001"));
//设置参数 删除某个属性
delete.addFamily(Bytes.toBytes("cf1"));
/* delete.addColumn();
delete.addColumn();*/
// 没有进行任何的参数设置 删除整行数据
tb.delete(delete);
tb.close();
}
来源:oschina
链接:https://my.oschina.net/u/4266314/blog/4311224