hbase shell命令与hbase API的调用
HBase
HBase shell
-
Region信息观察
create 'namespace:tb','cf'
查看命名空间里的所有表
list_namespace_tables 'n1'
查看region中的某列族数据
hbase hfile -p -f //hbase/data/default/tbl_user/...
刷新数据:flush 'tb'
合并数据:major_compact 'tb'
-
查看表的所有region
list_regions '表名'
-
强制将表切分出来一个region
split '表名','行键'
-
查看某一行在哪个region中
locate_region '表名','行键'
-
-
预分region解决热点问题
在默认的拆分策略中 ,region的大小达到一定的阈值以后才会进行拆分,并且拆分的region在同一个regionserver中 ,只有达到负载均衡的时机时才会进行region重分配!并且开始如果有大量的数据进行插入操作,那么并发就会集中在单个RS中, 形成热点问题,所以如果有并发插入的时候尽量避免热点问题 ,应当预划分 Region的rowkeyRange范围 ,在建表的时候就指定预region范围
实现思路:
- 分析数据分布:首先,需要分析和预测数据的分布模式。了解数据的键值范围和写入频率是关键。
- 预定义分区点:根据分析结果,确定适当的分区点。这些分区点将用于初始Region的划分。
- 创建预分区Region:在表创建时使用预定义的分区点,创建多个初始Region。
- 数据导入和均衡:在数据导入过程中,确保数据按照预定义的分区点写入相应的Region,并监控Region的负载情况。
- 动态调整:在运行过程中,动态监控数据分布和访问模式,必要时进行Region的拆分或合并。
-
日志查看
-- 日志目录 /.../hbase-版本号/logs
-
scan使用
查看所有的命名空间
list_namespace
查看某个命名空间下的所有表
list_namespace_tables 'namespace'
修改命名空间,设置一个属性
alter_namespace 'namespace',{METHOD=>'set',author=>'yulu'}
查看命名空间属性
describe_namespace 'namespace'
删除一个属性
alter_namespace 'namespace',{METHOD=>'unset',NAME=>'author'}
删除一个命名空间
drop_namespace 'namespace'
显示三行数据
scan 'tb_name',{LIMIT=>3}
从后三行查
scan 'tb_name',{LIMIT=>3,REVERSED=>true}
查看指定的列
scan 'tb_name',{LIMTT=>3,COLUMNS=>['cf:name']} --简化写法 scan 'tb_name',LIMTT=>3,COLUMNS=>['cf:name']
在已有的值后面追加值
append 'tb_name','行键','列族:列属性','追加值'
-
get的使用
简单使用,获取某一行数据
get 'tb_name','rowkey'
获取某一行的某个列族
get 'tb_name','rowkey','cf'
获取某一行的某一列(属性)
get 'tb_name','rowkey','cf:colname'
查看历史版本
修改表可以存储多个版本
alter 'tb_name',NAME=>'cf',VERSIONS=>N
修改列族的过期时间TTL单位是秒,这个时间是与插入的时间比较,而不是现在开始6 0s
alter 'tb_name',{NAME=>'cf2',TTL=>'10'}
-
插入时间指定时间戳
put 'tb_name','rowkey','info:colname','value',1718356919312
数据时间:数据产生那一刻的时间
事务时间(操作时间):接收到数据并处理的那一刻时间
-
delete删除
delete(只能删除一个单元格,不能删除列簇)
delete 'tb_name','rowkey','cf:colname'
deleteall(删除不了某个列簇,但是可以删除多个单元格)
- 删除一行,如果不指定列簇,删除的是一行中的所有列簇
- deleteall 'tb_name','rowkey'
- 删除单元格
- deleteall 'tb_name','rowkey','cf:colname','cf2:colname2'
-
获取region的分割点,清除数据,快照
获取region的分割点
get_splits 'tb_name'
清除表数据
truncate 'tb_name'
拍摄快照
snapshot 'tb_name','快照名'
列出所有快照
list_table_snapshots 'tb_name'
恢复快照
disable 'tb_split' restore_snapshot '快照名' enable ' tb_name'
Java API
java操作数据的步骤:
- 注册驱动
- 创建数据连接对象
- 创建数据操作对象
- 进行增删改查
- 如果时查询的话,可以对查询的结果进行分析
- 释放资源
//先设置成员变量
private Connection conn;
private Admin admin;
// 在写方法之前要创建数据连接对象、创建数据操作对象
@Before
public void connection() {
try {
//创建hbase的运行环境对象
//旧版本的写法,已弃用
// HBaseConfiguration conf = new HBaseConfiguration();
//新版本创建配置文件对象的方式
Configuration conf = HBaseConfiguration.create();
//设置zookeeper的节点信息
conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
//创建hbase连接对象
conn = ConnectionFactory.createConnection(conf);
//创建数据库操作对象
// HBaseAdmin hBaseAdmin = new HBaseAdmin(conn);
admin = conn.getAdmin();
System.out.println("成功获取数据库连接对象:" + conn);
System.out.println("成功获取数据库操作对象:" + admin);
System.out.println("=================================================");
} catch (Exception e) {
e.printStackTrace();
}
}
// 之后要关闭连接对象,释放资源
@After
public void close() {
if (admin != null) {
try {
admin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建一张表
public void createOneTable() {
/**
*在hbase中,表和列族需要分开创建并设置,然后再将列族对象添加到表中
* 1、创建一个表的描述对象
* 将表名封装成Tablename的对象
*/
TableName name = TableName.valueOf("students");
// 创建表描述器
TableDescriptorBuilder test2 = TableDescriptorBuilder.newBuilder(name);
//创建一个表描述器对象
try {
ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of("info");
//将一个列族添加到表描述器中
test2.setColumnFamily(info);
//判断表是否存在
if (admin.tableExists(name)) {
System.out.println(Bytes.toString(name.getName()) + "表已经存在!!");
return;
}
admin.createTable(test2.build());
System.out.println(Bytes.toString(test2.build().getTableName().getName()) + "表创建成功!!");
} catch (IOException e) {
System.out.println(Bytes.toString(test2.build().getTableName().getName()) + "表创建失败!!");
e.printStackTrace();
}
}
删除一张表
public void deleteOneTable() {
// 将表名封装成一个TableName对象
try {
TableName name = TableName.valueOf("students");
//判断表是否存在
if (!admin.tableExists(name)) {
System.out.println(Bytes.toString(name.getName()) + "表不存在,无法删除");
return;
}
// 禁用表
admin.disableTable(name);
// 删除表
admin.deleteTable(name);
System.out.println(Bytes.toString(name.getName()) + "表删除成功!!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
添加一条数据
public void setOneColData() {
try {
// 将表名封装成一个TableName对象
TableName name = TableName.valueOf("students");
//判断表是否存在
if (!admin.tableExists(name)) {
System.out.println(Bytes.toString(name.getName()) + "表不存在");
}
//获取表实例对象
Table test2 = conn.getTable(name);
// 将一列数据封装成一个put对象,传入一个行键,需要传入的行键变成一个字节数组格式
Put put = new Put(Bytes.toBytes("1500100001"));
//设置列族,列名和列值
// 设置方法1:
/*TODO
Put put1 = put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("xxx"));
test2.put(put1);
*/
//设置方式2:
KeyValue keyValue = new KeyValue(Bytes.toBytes("1500100001"),
Bytes.toBytes("info"),
Bytes.toBytes("name"),
Bytes.toBytes("xxx"));
put.add(keyValue);
test2.put(put);
System.out.println("一列数据已经添加完毕!!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
添加多条数据
public void putMoreData() {
ArrayList<Put> list = new ArrayList<>();
try {
TableName tablename = TableName.valueOf("students");
//判断表是否存在
if (!admin.tableExists(tablename)) {
System.out.println(Bytes.toString(tablename.getName()) + "表不存在");
}
// 获取表的实例对象
Table students = conn.getTable(tablename);
// 创建一个字符缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("data/students.txt"));
String line = null;
Put put = null;
while ((line = br.readLine()) != null) {
//1500100001,xxx,22,女,文科六班
String[] info = line.split(",");
byte[] rk = Bytes.toBytes(info[0]);
byte[] name = Bytes.toBytes(info[1]);
put = new Put(rk);
put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), name);
list.add(put);
byte[] age = Bytes.toBytes(info[2]);
put = new Put(rk);
put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"), age);
list.add(put);
byte[] gender = Bytes.toBytes(info[3]);
put = new Put(rk);
put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("gender"), gender);
list.add(put);
byte[] clazz = Bytes.toBytes(info[4]);
put = new Put(rk);
put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("clazz"), clazz);
list.add(put);
}
students.put(list);
System.out.println(Bytes.toString(tablename.getName())+"所有数据添加完成!!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
获取一条数据
public void getOneData(){
try {
TableName tablename = TableName.valueOf("students");
//判断表是否存在
if (!admin.tableExists(tablename)) {
System.out.println(Bytes.toString(tablename.getName()) + "表不存在");
}
// 获取表的实例对象
Table students = conn.getTable(tablename);
// 创建一个Get对象
Get get = new Get(Bytes.toBytes("1500100001"));
Result result = students.get(get);
/**
*HBase中Result类常用的方法:
* getRow()获取行键的字节数组形式
* getValue(byte [] family, byte [] qualifier) 获取某一列的字节数组形式
* listCells()获取所有列单元格组成的List集合
*/
// 第一种方式:列单独取出,但是获取一列数据的前提是知道列名和列族
// 1500100001,xxx,22,女,文科六班
/*TODO
String id = Bytes.toString(result.getRow());
String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
System.out.println("学号:"+id+",姓名:"+name+",年龄:"+age+",性别:"+gender+",班级:"+clazz);
*/
// 第二种方式:listCells()
List<Cell> cells = result.listCells();
for (Cell cell : cells) {
String id = Bytes.toString(CellUtil.cloneRow(cell));
String cf = Bytes.toString(CellUtil.cloneFamily(cell));
String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
String colValue = Bytes.toString(CellUtil.cloneValue(cell));
System.out.println("行键:"+id+"列族:"+cf+"列名:"+colName+"列值:"+colValue);
System.out.println("-------------------------------------------------");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
获取多条数据
public void getMoreData(){
try {
TableName tablename = TableName.valueOf("students");
//判断表是否存在
if (!admin.tableExists(tablename)) {
System.out.println(Bytes.toString(tablename.getName()) + "表不存在");
}
// 获取表的实例对象
Table students = conn.getTable(tablename);
// 创建一个Scan对象
Scan scan = new Scan();
ResultScanner resultScanner = students.getScanner(scan);
Iterator<Result> resultIterator = resultScanner.iterator();
StringBuilder sb = null;
while (resultIterator.hasNext()){
Result result = resultIterator.next();
String id = Bytes.toString(result.getRow());
/*TODO
String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
System.out.println("学号:"+id+",姓名:"+name+",年龄:"+age+",性别:"+gender+",班级:"+clazz);
*/
List<Cell> cells = result.listCells();
sb = new StringBuilder();
sb.append(id).append(",");
for (int i = 0; i < cells.size(); i++) {
String colName = Bytes.toString(CellUtil.cloneQualifier(cells.get(i)));
String colValue = Bytes.toString(CellUtil.cloneValue(cells.get(i)));
if (i != cells.size()-1){
sb.append(colName).append(":").append(colValue).append(",");
}else {
sb.append(colName).append(":").append(colValue);
}
}
System.out.println(sb);
System.out.println("------------------------------");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
创建预分region表
public void createSplitTable(){
TableName name = TableName.valueOf("splitTable");
TableDescriptorBuilder test2 = TableDescriptorBuilder.newBuilder(name);
try {
ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of("info");
test2.setColumnFamily(info);
if(admin.tableExists(name)){
System.out.println(Bytes.toString(name.getName())+"表已经存在");
}
byte[][] splitKeys={
Bytes.toBytes("e"),
Bytes.toBytes("h"),
Bytes.toBytes("l"),
Bytes.toBytes("r")
};
admin.createTable(test2.build(),splitKeys);
System.out.println(Bytes.toString(test2.build().getTableName().getName())+"表创建成功");
} catch (IOException e) {
System.out.println(Bytes.toString(test2.build().getTableName().getName())+"表创建失败");
throw new RuntimeException(e);
}
}