基于HBase的海量数据查询与检索解析

Java
355
0
0
2024-01-12
标签   HBase

1. HBase回顾

1.1. HBase的历史

基于HBase的海量数据查询与检索解析

HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于Bigtable的能力。HBase是 Apache 的Hadoop项目的子项目。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。

Google三驾马车 :分布式文件系统 GFS 、分布式计算框架 MapReduce 、分布式列式 NoSQL 数据库BigTable; (2003~2006)

开源Hadoop三件套 :分布式文件系统 HDFS 、分布式计算框架MapReduce、分布式列式NoSQL数据库HBase; (2006~2009)

HBase :高可靠、高性能、高扩展性的 分布式存储 系统。可承载PB级的数据存储,亿次/每秒的读写请求。

1.2. HBase应用场景

HBase应用的场景与行业非常的广泛,主要侧重于大数据量场景。

基于HBase的海量数据查询与检索解析

HBase与大数据量场景如此契合的原因有许多,首先,HBase存储成本低,海量数据存储的成本相对较低,所需机器也非常少。

基于HBase的海量数据查询与检索解析

其次,HBase扩展性非常好,随着数据量的增加,只要简单地扩机器即可,HBase单个表的访问可以横向扩展到多个机器上进行访问。

此外,HBase是 Schema Free,它不像关系数据库一样事先定义好表的结构,它只需要创建表的时候,指定表和列名字就可以,列是动态生成的。

HBase有很好的容错恢复能力,比方这么多的分布式节点,单个节点宕机之后,它可以快速地将计算的资源迁移到其他节点上继续提供服务,做到用户无感知的自动恢复。

同时它还支持TTL与多版本特性,比如淘汰海量数据下的一些历史数据,可以直接使用TTL操作。当遇到一个业务场景中单个列有多个版本,可以使用多版本的特性存储多个版本的数据。

2. HBase查询原理

2.1 HBase数据模型

1> 基本概念

  • Table:表名。
  • Rowkey:行唯一键,也叫主键Primary Key,字典序排序存储。
  • Column Family:列族,同一列族的数据集中存储,单个表可包含多列族,TTL、高效压缩。
  • Column:列名。动态列,Schema Free,底层统一 byte [ ]存储。
  • Timestamp :每个列的时间戳。多版本,按照时间戳最新原则排序。

2> 常见查询

  • 主键查询:Rowkey Get
  • 范围查询:Rowkey Scan
  • 条件过滤:Rowkey Get/Scan+ Filter
  • 多语言访问: Java / Python /C++/ Go /PHP/ node.js 等。

3> 范例

基于HBase的海量数据查询与检索解析

上方为一个普通的结构化表,ID也就是主键Rowkey,用数字表示,按顺序存储的,即使1001在1002和1003之后写入,写入后仍会按照数字顺序排在最前面。

Info和Date是两个不同列族(Cloumn Family)的名字,两个列族里包含许多列。Value表示每个列对应的值,比如小王是姓名列的值。在列族里,列的个数不是固定的,假如想在Info列组里面再加一个列,直接在列族里添加即可,这就是动态列的特点。

还有一个特性是时间戳,例子中定义了城市列和三个时间戳,杭州时间戳2019,北京时间戳2016, 厦门 时间戳2012,用户可以在写入值的时候填入时间戳,否则系统会自动按照当前时间设置时间戳。这三个版本的值会同时存在列里,如果检索1001的城市值,默认返回最新的版本。如果想把多版本都返回,则需要在检索的时候告诉系统需要几个版本,则系统会根据要求返回相应版本的数据,这就是HBase基本的数据模型。

通过这个数据模型可以看到,首先是按字典序排序存储,就可以很方便地进行范围查询,比如检索ID 1001~1003的数据,用一个Scan语句就可以把这几条数据全部返回。同时,数据是按行存储,比如指定ID 1001,可以快速地把这整行数据都取出。

HBase中有几个常见的查询场景,第一个是主键查询,基于Rowkey值,可以快速拿到某一行数据。 第二个是范围查询,可以指定Rowkey的范围,把符合条件的数据全部取出来。

第三个是条件过滤,在Get/Scan数据的时候,还想指定某个列值等于某个条件的,比方说检索范围是1001~1003,年龄等于20的数据,则系统只会把1001的数据给检测出来。

Filter相当于是过滤条件。除了指定 Rowkey的范围之外,可以指定一个单独的条件,把满足条件的数据检索出来。 HBase支持使用多语言查询,除了HBase原生支持的语言以外,还支持多种语言访问。

2.2. HBase数据查询

1> HBase Shell

基于HBase的海量数据查询与检索解析

下面介绍如何通过HBase的 Shell 创建一个表并写入数据,以及通过Shell把数据检索出来。 表的名字为“myTable”,列族为“f”,执行建表命令create ‘myTable’,’f’即可成功创建。

建表时还需注意以下几点:

1)建表时必需的参数:表名和列族名

2)表预分区:建表时设置分区个数、分区范围,预分区是防止数据出现热点的最佳实践。

3)列族属性:TTL、多版本、压缩、编码属性等。

建表完成后可以开始写数据。

  • 写数据: put ‘myTable’,’1001′,’f:name’,’alice’
  • 表名:myTable
  • RowKey:1001
  • 列族+列名:f:name
  • 值:alice

这条命令相当于把数据alice写入Rowkey等于1001,列族等于f,列名等于name的地方。

这里需要注意的地方是,HBase在写入数据时,无法通过单独的列名确定写入的地方,需要列族+列名。这是由于表中可能存在不同的列族中有相同的列名,因此无法单独通过列名来确定列。

2> 查询

在写入数据之后,需要做数据查询,主要有以下三种方法。

主键查询 :get ‘myTable’,’1002’

范围查询 :scan ‘myTable’,{STARTROW => ‘1002’, STOPROW => ‘1004’}

条件过滤 :scan ‘myTable’,{STARTROW => ‘1002’, STOPROW => ‘1004’, FILTER=>”SingleColumnValueFilter(‘f’, ‘name’,=,’binary:bob’)”}

这里需要注意的一点是,范围查询里的STARTROW => ‘1002’是个闭区间,STOPROW => ‘1004’是个开区间,相当于取出的数据是1002和1003的数据。假设表中有1004的数据,这个数据是不会被检测出来的。

条件过滤相当于指定了一个范围外加一个条件,例如1002和1004,范围内的数据有很多,但是符合条件的数据非常少,后面跟一个过滤条件Filter,过滤的条件是’name’,=,’binary:bob’的一行数据。

以上是HBase Shell的用法,用户可以通过输入 List Filters得到当前支持的所有filter。

3> Java API 访问

除了HBase Shell这种查询的语法之外, HBase原生支持的就是 Java API访问。通过Java API我们可以快速取到某一行数据或者Scan某些数据。

上图为一个简单的Demo。

首先指定一个表名,然后new Put一个对象,相当于要写一行数据,这一行数据在new Put的时候会指定Rowkey是1001。接着指定列族、列的名字,以及列的值,然后就可以完成数据写入。

接下来可以直接执行get方法,比如指定Rowkey就可以拿到相应数据。如果想范围查询,就通过Scan指定一个范围,也可以拿到相应数据。

3. Phoenix入门

SQL 是大部分数据库通用的语言,HBase通过Phoenix组件支持SQL操作。接下来阐述除了通过Shell与Java API之外, 如何通过SQL操作HBase。

3.1. Phoenix介绍

Phoenix:OLTP and operational analytics for Apache Hadoop.

Phoenix是Salesforce公司主导的Apache开源项目,致力于“put the SQL back in NoSQL”,提升HBase的使用体验,赋予HBase OLTP和轻量级OLAP的能力。

Phoenix遵循 ANSI SQL-92标准,支持 JDBC API、Transactions、UDF、Secondary Indexes、Salt Tables等。 Phoenix语法丰富,支持group by/order by/join/subquery/function等(Phoenix Grammar)。

Phoenix具备毫秒级交互式体验,MPP并行执行,充分利用HBase Coprocessor实现计算下推。

3.2. Phoenix SQL基本使用

1> Phoenix Sqlline

下面介绍Phoenix的SQL如何操作HBase。

Phoenix有专门的Sqlline,下载之后也是一个客户端的程序,通过Sqlline连接到Phoenix集群,就可以在上面直接创建表,然后读写数据。

下面举例说明。

建表 : create table myTable(id VARCHAR primary key, name CHAR(20), age INTEGER, sex CHAR(10));’

表名 :myTable

列名和列类型 :id 主键,name 字符串类型,age 整数类型,sex 字符串类型

写数据 :upsert into myTable values(‘1001′,’alice’,18,’male’);

基于HBase的海量数据查询与检索解析

2> Phoenix Sqlline查询

前面介绍了HBase通过Shell检索某行数据或范围查询,Phoenix Sqlline也可以获取某行数据与简单的范围查询,如下所示。

  • 主键查询:select * from myTable where id=’1002′;
  • 范围查询:select * from myTable where id>=’1002′ and id<=’1004′ limit 10;
  • 过滤查询:select * from myTable where id>=’1002′ and id<=’1004′ and name=’bob’ limit 10;

基于HBase的海量数据查询与检索解析

可以看到,通过 SQL语句 操作HBase会更加地简单,对于开发人员而言也是更加简单易用。

3> 丰富的语法支持

Phoenix的语法非常丰富,在官网可以看到它语法的列表,它基本涵盖类似于SQL92的所有语法,可以看到详尽的语法使用方法。

基于HBase的海量数据查询与检索解析 丰富的语法

基于HBase的海量数据查询与检索解析

上方为线上的一个查询场景,它也可以做到两个不同表的查询,这也是非常常见的一种语法。

3. 查询加速

3.1. 多样化的查询

在HBase的使用过程中,除了上文讲到的HBase支持的查询之外,随着数据量的增加,业务的查询场景会更加多样化,下面简单介绍了几个来源于业务的真实需求。

多维查询:即席查询,一般是不固定的列随机组合。

count计数:获取数据表的总行数,或者返回一次查询命中的数据条数。

指定列排序:按照指定列降序或升序,比方说按照订单时间降序输出结果。

分词检索:支持文本字段的分词检索,返回相关性较高的结果数据。

统计聚合:按照某个字段进行聚类统计,求取sum/max/min/avg等,或者返回去重后的结果集。

模糊查询:查询以“中国”开头的数据,可以匹配出“中国人民”的结果集,类似 MySQL 的like语法。

通用解决方案

1. 协处理器:计算下推,服务端执行逻辑。

2. 二级索引:变换数据存储格式,加速非主键查询。

3. 全文索引 :引入搜索引擎解决查询难题。

3.2. 协处理器

HBase原生协处理器Coprocessor,逻辑在服务端运行,避免移动数据,加速处理。

协处理器Coprocessor有两种模式:

1. Observer

与数据库的触发器类似,在一些特定事件发生时执行 回调函数 。HBase服务端的内核逻辑已经在固定的流程中埋点,例如在put写数据前执行一段函数prePut,put写数据后执行一段函数postPut。

2. Endpoint

与数据库的存储过程类似,客户端远程调用服务端的代码,例如HBase原生支持的聚合Aggregate,求max/min/avg。

3.3. 二级索引 – 非主键索引

前文主要阐述了主键Rowkey的查询,如果检索条件是指定一个列去查询,其实就没有指定主键了,需要通过二级索引的非主键索引解决,下面举例说明。

基于HBase的海量数据查询与检索解析

如上方所示,扫描表myTable,检索条件是’name’,=,’binary:bob’。

如果表的数据非常大,需要把所有的数据都扫描出来,这种查询非常消耗资源,并且由于逐步扫描,可能会超时。

面对这种场景,最通用的解决方案就是用HBase的二级索引,下图为HBase二级索引的查询模型。

基于HBase的海量数据查询与检索解析

如上图所示,右边是主表的查询,包含按顺序存储的Rowkey与几个列。 如果检索条件只有Col2,就可以建一个二级索引。

左边是一个二级索引表,它是一个单独的表,表的主键由Col2和Rowkey组成,唯一确定了索引表的一行数据,可以快速检测出符合条件的数据。

3.4. 二级索引的实现

Phoenix基于协处理器实现二级索引。

上方为是基于Observer实现二级索引的一个例子。

在Put/Delete流程中解析写入的数据,构造索引数据,写入到 索引 表中。在Scan流程中解析查询语法,命中索引,则查询索引表,没有命中索引,则查询原表。

基于HBase的海量数据查询与检索解析

3.5. 全文索引(HBase+Elasticsearch)

还有一种通用的解决方案是全文索引(HBase+Elasticsearch),通过HBase的高效查询与Elasticsearch的全文索引, 可以满足多样化的查询场景。

全文索引(HBase+Elasticsearch)有许多方案,如业务双写、数据自动同步、Observer触发器等。

1.业务双写

基于HBase的海量数据查询与检索解析


  • 简单,业务快速落地。
  • 开发成本高:应用同时与HBase和 Elasticsearch交互。
  • 维护复杂:熟悉HBase和Elasticsearch 技术栈。
  • 数据不一致。

2.数据自动同步

  • 无需双写,只需双读,开发成本降低。
  • 数据最终一致。
  • 维护复杂:熟悉HBase和Elasticsearch 技术栈、数据同步服务。

3. Observer触发器

  • 仅与HBase交互,应用开发成本进一步 降低,但要额外开发Observer程序。
  • 维护复杂:熟悉HBase和Elasticsearch 技术栈,Observer容易引起系统不稳定。
  • 写入延迟:Elasticsearch写入阻塞全局。

4. 总结

如下图所示,整个HBase的数据生态十分丰富,可以看到有很多开源产品,首先上游APP、日志、数据库等高并发写入 到HBase之后, Spark 、Flink等可以直接读取HBase数据做分析。同时它们的结果也可以批量写入/Bulkload到HBase。

然后通过同步工具,如LTS、 Kettle 等,可以把HBase的数据全量同步到离线分析系统。 也可以通过增量订阅工具,如LTS、Replication,订阅到消息队列,下游再对接实时计算的产品,如Flink、Spark。 以上就是HBase的大致生态环境。

HBase数据生态