BigData大数据应用开发学习笔记(06)实时检索--HBase
一.关于实时检索
1.核心诉求
检索性能要求高:秒级响应,不承担复杂查询和统计类查询
高并发查询:大于100的并发
数据量大:PB级数据量,集群规模在1000节点以上。图数据库场景,点个数在10亿以上,边个数在100亿以上
支持结构化和非结构化:需要同时保存结构化数据和非结构化数据,经常用来对图片等小文件进行检索
高效的数据加载:每小时可加载TB级数据
支持图检索:支持检索图数据,支持图标准查询接口
2.实时检索解决方案
根据关键词进行即时、快速搜索,实现即搜即得的效果,强调的是实时低延迟。
文件数据批量加载(Loader、Flume、Spark、第三方加载),流式数据实时加载(Spark Streaming、第三方采集),图数据(GraphBase导入工具)。
实时检索引擎(HBASE、ElasticSearch),GraphBase(可选)
业务应用:轨迹查询,日志查询,话费查询
二.HBase
1.HBase简介
HBase是一个分布式的NoSQL数据库,其特点高可靠、高性能、面向列、可伸缩。
适合存储大表数据,并且可实时读写大表数据。
表结构稀疏
数据底层存储于Hadoop HDFS分布式文件系统
利用ZooKeeper作为协同服务
2.HBase应用场景
海量数据(TB、PB)
不需要完全拥有传统关系型数据库所具备的ACID特性。
高吞吐量
需要在海量数据中实现高效的随机读取。
需要很好的性能伸缩能力
能够同时处理结构化和非结构化的数据
3.HBase系统架构
Client -> ZooKeeper -> HMaster -> HBase -> DFS Client -> HDFS -> DataNode
4.HBase存储模型
底层数据以KeyValue的形式存在,KeyValue具有特定的格式,KeyValue中拥有时间戳、类型等关键信息。
同一个Key值可以关联多个Value,每个KeyValue都拥有一个Qualifier标识。
即使是Key值相同,Qualifier也想通的多个KeyValue,也可能有多个版本,此时使用时间戳来区分,这就是同一条数据记录的多版本。
ID Name Phone Address
Key-01 -> Value-ID01 Key-01 -> Value-Name01
Key-01 -> Value-Phone01 Key-01 -> Value-Address01
5.HBase缓存机制
两种类型的缓存结构:MemStore,BlockCache
MemStore:HBase数据先写入HLog之中,并同时写入MemStore,待满足一定条件后将MemStore中数据刷到磁盘,能提升HBase的写性能和读性能。
BlockCache:HBase会将一次文件查找的Block块缓存到Cache中,以便后续同一请求或者相邻数据查找请求,可以直接从内存中获取,避免IO操作。
6.HBase BloomFilter
BloomFilter用来优化一些随机读取的场景,即Get场景。可以被用来快速判断一条数据在一个大的数据集合中是否存在。
BloomFilter在判断一个数据是否存在时,拥有一定的误判率。但对于"该条数据不存在"的判断结果是可信的。
HBase的BloomFilter的相关数据,被保存在HFile中。
7.HBase客户端
客户端命令对HBase数据库进行各种操作,增删改查,表快照备份等。
进入HBase客户端
hbase shell
查看帮助命令
help
查看列表信息
list
创建表,指导列族
create 'my_tb', 'info'
创建命名空间
create_namespace 'ns'
查看命名空间的表
list_namespace_tables 'ns'
插入数据
put
'my_tb', '20190501', 'info:name', 'ez'
扫描表数据
scan 'my_tb'
get查询数据
get 'my_tb', '20190501'
8.SQL On HBase
Apache Phoenix将SQL查询编译为一系列HBase扫描。可以为小型查询提供毫秒级的性能,或者为数千万行提供数秒的性能。
Phoenix SQL支持的部分语法:
SELECT | UPSERT VALUES | UPSERT SELECT
DELETE | CREATE TABLE | DROP TABLE |
CREATE FUNCTION | DROP FUNCTION | CREATE VIEW
DROP VIEW | ALTER | CREATE INDEX
DROP INDEX | ALTER INDEX | EXPLAIN |
UPDATE STATISTICS | CREATE SCHEMA | USE
DROP SCHEMA | GRANT | REVOKE
例如:
SELECT * FROM TEST LIMIT 1000;
CREATE TABLE my schema.my table (
id BIGINT not null primary key,
date Date
) ;
DELETE FROM TEST WHERE ID=123;
Phoenix SQL语法参考:
http://phoenix.apache.org/language
9.API使用
(1).创建删除表
通过org.apache.hadoop.hbase.client.Admin实例的createTable方法来创建表,并指定表名、列族名。
Admin admin = conn.getAdmin();
admin.createTable(tableName);
通过org.apache.hadoop.hbase.client.Admin实例的createTable方法来删除表
Admin admin = conn.getAdmin();
// 先停用表
admin.disableTable(tableName)
// 执行删除
admin.deleteTable(tableName)
(2).插入删除数据
HBase通过Table实例的put方法来插入数据,可以是一行数据也可以是数据集。
Table table = conn.getTable(tableName);
List<Put> puts = new ArrayList<Put>();
Put put = new Put(Bytes.toBytes("012005000201"));
put.addColumn(familyName, qualifiers[0], Bytes.toBytes("Zhang San"));
puts.add(put);
table.put(puts);
HBase通过Table实例的delete方法来Delete数据,可以是一行数据也可以是数据集。
byte[] rowKey = Bytes.toBytes("012005000201");
Table table = conn.getTable(tableName);
// 创建一个Delete对象
Delete delete = new Delete(rowKey);
// 表对象的delete方法传入delete对象为参数,提交删除请求
table.delete(delete);
(3).Get读取数据
要从表中读取一条数据,首先需要实例化该表对应的Table实例,然后创建一个Get对象。也可以为Get对象设定参数值,如列族的名称和列的名称。查询到的行数据存储在Result对象中,Result中可以存储多个Cell。
byte[] familyName = Bytes.toBytes("info");
byte[][] qualifier = { Bytes.toBytes("name"), Bytes.toBytes("address") };
byte[] rowKey = Bytes.toBytes("012005000201");
Table table = conn.getTable(tableName);
Get get = new Get(rowKey);
get.addColumn(familyName, qualifier[0]);
get.addColumn(familyName, qualifier[1]);
Result result = table.get(get);
for (Cell cell : result.rawCells()) { Example }
(4).Scan读取数据
要从表中读取数据,首先需要实例化该表对应的Table实例,然后创建一个Scan对象,并针对查询条件设置Scan对象的参数值,为了提高查询效率,最好指定StartRow和StopRow。查询结果的多行数据保存在ResultScanner对象中,每行数据以Result对象形式存储,Result中存储了多个Cell。
Table table = conn.getTable(tableName);
Scan scan = new Scan();
// 添加列族和列名
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
// 设置缓存大小,也可设置起始结束的rowKey等
scan.setCaching(1000);
// 提交Scan请求
ResultScanner rScanner = table.getScanner(scan);
// 解析处理结果
for (Result r = rScanner.next(); r != null; r = rScanner.next())
{for (Cell cell : r.rawCells()) { Example }}
(5).过滤器Filter
HBase Filter主要在Scan和Get过程中进行数据过滤,通过设置一些过滤条件来实现,如设置RowKey,列名或者列值的过滤条件。
Table table = conn.getTable(tableName);
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
// 创建过滤对象,单列值过滤器,参数为列族、列名、过滤列值"Xu Bing"
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("info"), Bytes.toBytes("name"), CompareOp.EQUAL, Bytes.toBytes("Xu Bing"));
// 为scan对象设置过滤器对象,即扫描设置过滤条件
scan.setFilter(filter);
// 提交扫描请求
ResultScanner rScanner = table.getScanner(scan);
// 解析处理结果
for (Result r = rScanner.next(); r != null; r = rScanner.next())
{for (Cell cell : r.rawCells()) { Example }
}