HBase学习

Hbase

WHTA

Hadoop Database

HBase 是Apache的 Hadoop 项目的子项目。

HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统

HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库, HBase基于列的而不是基于行的模式.

HBase的原型是Google的BigTable论文。

WHY

MySQL无法满足海量的数据存储,

MySQL -> 面向行存储

HBase -> 面向行存储

HOW

HBase概念视图

HBase学习_第1张图片

表名:webtable

两行:com.cnn.wwwcom.example.www

三个列族:contentsanchorpeople

对于第一行com.cnn.www

anchor列族包含两列:anchor:cssnsi.comanchor:my.look.ca

{
"com.cnn.www": {
contents: {
t6: contents:html: "..."
t5: contents:html: "..."
t3: contents:html: "..."
}
anchor: {
t9: anchor:cnnsi.com = "CNN"
t8: anchor:my.look.ca = "CNN.com"
}
people: {}
}
"com.example.www": {
contents: {
t5: contents:html: "..."
}
anchor: {}
people: {
t5: people:author: "John Doe"
}
}
}

HBase物理视图

HBase学习_第2张图片

HBase 概念视图中显示的空单元根本不存储

HBase表、行与列族

创建一个HBase表:

create ‘

’,’

HBase中的行是逻辑上的行,物理模型上行时按列族(column family)分别存取的。

列族

Hbase表中的每个列都归属于某个列族,

列名由其 列族前缀 和 限定符 组成,

列的限定符是列族中数据的索引。

eg

列族:course

列名:course:mathcourse:english

cell

由行和列的坐标交叉决定;

单元格是有版本的;

单元格的内容是未解析的字节数组

单元格是由行、列族、列限定符、值和代表值版本的时间戳组成的,

({row key,column( =+),version})

唯一确定单元格。cell中的数据是没有类型的,全部是字节码形式存储。

Name Space

命名空间,类似于关系型数据库的database概念,每个命名空间下有多个表。

HBase有两个自带的命名空间,分别是hbasedefault

  • hbase中存放的是HBase内置的表;
  • default 表是用户默认使用的命名空间。

Row Key

HBase表中的每行数据都是由一个RowKey和多个Column组成,数据是按照RowKey的字典顺序存储的,并且

查询数据时只能根据RowKey进行检索,所以RowKey的设计十分重要。

HBase基本架构

HBase学习_第3张图片

HBase学习_第4张图片

架构角色

  1. Region Server

    Region Server 是 Region的管理者,其实现类为HRegionServer

    主要作用:

    • 对数据的操作:getputdelete
    • 对Region的操作:splitRegioncompactRegion
  2. master

    Master是所有Region Server的管理者,其实现类为HMaster

    主要作用:

    • 对表的操作:create、delete、alter(变更、改变)
    • 对Region Server的操作:分配regions到每个Region Server,监控每个Region Server的状态,负载均衡和故障转移
  3. Zookeeper

    HBase 通过 Zookeeper 来做master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。

  4. HDFS

    HDFSHBase 提供最终的底层数据存储服务,同时为HBase提供高可用的支持。

RegionServer 架构

HBase学习_第5张图片

  • StoreFile:保存实际数据的物理文件,StoreFileHFile的形式存储在HDFS上。每个Store会有一个或多个StoreFileHFile),数据在每个StoreFile中都是有序的。
  • MemStore:写缓存,由于HFile中的数据要求是有序的,所以数据是先存储在Memstore中,排好序后,等到刷写时机才会刷写到HFile,每次刷写都会形成一个新的HFile
  • WAL:由于数据要经MemStore排序后才能刷写到HFile,但把数据保存在内存中会后很高的概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile 的文件中,然后再写入MemStore中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
  • BlockCache:读缓存,每次查询出的数据会缓存在BlockCache中,方便下次查询。

读写流程

HBase学习_第6张图片

HBase学习_第7张图片

HBase学习_第8张图片

将合并后的最终结果返回给客户端(此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete))

HBase操作

进入hbase客户端命令行

$ bin/hbase shell

查看帮助命令

help

NameSpace相关操作

查看当前HBase中有哪些namespace

list_namespace
default # 创建表时未指定命名空间,默认在default下
hbase   # 系统使用的,用来存放系统相关的元数据信息等

创建namespace

creat_namespace 'test'
creat_namespace 'test1',{'author' => 'damin','creat_time' => '2020-11-27 09:20:56'}

查看namespace

describe_namespace 'test1'

修改namespace的信息(添加或修改属性)

alter_namespace 'test1',{METHOD => 'set','author' => 'zzm'}
alter_namespace 'test',{METHOD => 'set','PROPERTY_NAME' => 'PROPERTY_VALUE'}

删除属性

alter_namespace 'test',{METHOD => 'unset',NAME => 'PROPERTY_NAME'}

删除namespace

*要注意删除的namespace必须是空的,其下没有表

drop_namespace 'test'

表的操作

查看当前数据库中有哪些表

list

创建表

creat 'student','info'

向表中插入数据

put 'student','1001','info:name','damin'
put 'student','1001','info:sex','female'
put 'student','1001','info:age','18'

扫描查看表数据

scan 'student'
scan 'student',{STARTROW => '1001',STOPROW => '1001'}
scan 'student',{STARTROW => '1001'}

查看表结构

desctibe 'student'

更新指定字段的数据

put 'student','1001','info:name','damin01'
put 'student','1001','info:age','20'

查看指定 行 或 列族:列 的数据

get 'student','1001'
get 'student','1001','info:name'

统计表数据 行数

count 'student'

删除某 rowkey 的全部数据

deleteall 'student','1001'

删除某 rowkey 的某一列数据

delete 'student','1001','info:age'

清空表数据

此操作之前,应先disable,禁用表

disable 'student'
truncate 'student'

删除表

disable 'student'
drop 'student'

变更表信息

alter 'student',{NAME => 'info',VERSIONS => 3}
get 'student','1001',{COLUMN => 'info:name',VERSIONS => 3}

DDL API

判断表是否存在

public static boolean isTableExist(String tableName) throws IOException {

//创建配置信息并配置
Configuration configuration = HBaseConfiguration.create();
configuration.set("","");
//获取与HBase的链接
Connection connection = ConnectionFactory.createConnection();
//获取DDL操作对象
Admin admin = connection.getAdmin();
//判断表是否存在
boolean exists = admin.tableExists(TableName.valueOf(tableName));
//关闭连接
admin.close();
connection.close();

//返回结果
return exists;
}

创建表

public static void createTable(String tableName,String... columnFamily) throws IOException {
//判断是否存在列族信息
if (columnFamily.length <= 0) {
System.out.println("请先设置列族信息!");
return;
}
//判断表是否存在
if (isTableExist(tableName)) {
System.out.println("表已存在!");
return;
}
//获取链接
//……
//获取DDL操作对象
Admin admin = connection.getAdmin();

//创建表描述器
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
//循环添加列族信息
for (String cf : columnFamily) {
//setCompressionType:设置压缩算法
tableDescriptor.addFamily(new HColumnDescriptor(cf).setCompressionType(Compression.Algorithm.NONE));
}

//执行创建表操作
admin.createTable(tableDescriptor);
}

删除表

public static void dropTable(String tableName) throws IOException {
//判断表是否存在
if (!isTableExist(tableName)) {
System.out.println("该表不存在!");
return;
}
//获取链接
//……
//获取DDL操作对象
Admin admin = connection.getAdmin();

//使表下线
admin.disableTable(TableName.valueOf(tableName));
//删除表
admin.deleteTable(TableName.valueOf(tableName));
}

DML API

插入数据 PUT

public static void putData(String tableName,String rowKey,String columnFamily,String qualifier,String value) throws IOException {
//获取链接
//……
//获取表的链接
Table table = connection.getTable(TableName.valueOf(tableName));

//创建Put对象
Put put = new Put(Bytes.toBytes(rowKey));
//放入数据
put.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(qualifier),Bytes.toBytes(value));
//向表中插入数据
table.put(put);

}

查询单条数据 GET

public static void getDate(String tableName,String rowKey,String columnFamily,String qualifier) throws IOException {
//获取链接
//……
//获取表的链接
Table table = connection.getTable(TableName.valueOf(tableName));

//创建Get对象
Get get = new Get(Bytes.toBytes(rowKey));
//指定列族查询
get.addFamily(Bytes.toBytes(columnFamily));
//指定列族:列查询
get.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(qualifier));

//查询数据
Result result = table.get(get);

//解析result
for (Cell cell : result.rawCells()) {
System.out.println("ColumnFamily:" + Bytes.toString(cell.getFamilyArray()) +
",Qualifier:" + Bytes.toString(cell.getQualifierArray()) +
",Value:" + Bytes.toString(cell.getValueArray()));
}
}

扫描数据 SCAN

public static void scanTable(String tableName) throws IOException {
//获取链接
//……
//获取表的链接
Table table = connection.getTable(TableName.valueOf(tableName));

//扫描数据
ResultScanner results = table.getScanner(new Scan());
//解析数据
for (Result result : results) {
for (Cell cell : result.rawCells()) {
System.out.println(Bytes.toString(CellUtil.cloneRow(cell)) + ":" +
Bytes.toString(CellUtil.cloneFamily(cell)) + ":" +
Bytes.toString(CellUtil.cloneQualifier(cell)) + ":" +
Bytes.toString(CellUtil.cloneValue(cell)));
}
}
}

删除数据 DELETE

public static void deleteData(String tableName,String rowKey,String columnFamily,String qualifier) throws IOException {
//获取链接
//……
//获取表的链接
Table table = connection.getTable(TableName.valueOf(tableName));

//创建Delete对象
Delete delete = new Delete(Bytes.toBytes(rowKey));
//指定列族删除数据
delete.addFamily(Bytes.toBytes(columnFamily));
//指定 列族:列 删除数据 (没有指定时间戳,删除最新版本)
delete.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(qualifier));
//删除<=指定时间戳的所有版本
delete.addColumns(Bytes.toBytes(columnFamily),Bytes.toBytes(qualifier));

//执行删除操作
table.delete(delete);
}

你可能感兴趣的:(hbase-client)