开发者学堂课程【HBase 入门与实战:基于 HBase 的海量数据查询与检索解析】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/lear08/detail/13895
基于 HBase 的海量数据查询与检索解析
内容介绍:
一、HBase 回顾
二、HBase 查询原理
三、Phoenix 入门
四、查询加速
五、总结
一、HBase 回顾
1、开源历史
Google 三驾马车:
分布式文件系统 GFS、分布式计算框架MapReduce 分布式列式 NoSQL 数据库 BigTable;(2003~2006)
开源 Hadoop 三件套:分布式文件系统 HDFS 分布式计算框架MapReduce 分布式列式 NoSQL 数据库 HBase;(2006~2009)
HBase:高可靠、高性能、高扩展性的分布式存储系统,可承载 PB级的数据存储,亿次/每秒的读写请求
HBase 的历史通过开源的网站或者网上的业务应该有所了解。HBase 的历史,首先起源于 Google 的三驾马车,Big Table 是在零六年左右发布的一篇论文,讲述了分布式当中 NoSQL 数据库的具体的实现,在这个基础上,Hadoop 开源社区在零九年左右开源了分布式列式 NoSQL 数据库 HBase 也是沿用了 Big Table的一些重要的思想,HBase 从零九年到现在发展十多年,已经成为一个高可靠、高性能以及高扩展的分布式存储系统,可以承载 PB 级的数据存储,而且每秒可以达到亿次级的读写请求。
2、适用场景
用户画像、实时推荐、实时风控、时序监控、社交 Feed 流
车联网、航空物流、广告行业、游戏行业、通用行业
那X这么强大的一些个性能以及存储,它主要应用在哪些场景中呢? HBase 应用的场景非常广泛,比方用户画像,实时推荐,实时风控,还有社交 Feed 流,应用的行业也非常广泛车联网物流以及广告行业、游戏行业等。HBase 最主要的场景,用 HBase 的时候,只要数据是是一个大数据的场景,选用 HBase 是比较好的一种选择,HBase 可以应用在大数据的场景中主要有一些特点,第一个是存储成本非常的低,正是因为它成本低,在海量数据存储的时候价格就相对来说比较便宜,用的机器也非常的少。
第二个是它扩展性非常好,随着数据量的增加,只要简单的扩机器就可以,HBase 数据可以横向的拓展到单个表或多个问题的访问。
还有一个是 Schema Free 不像关系数据库一样事先定义好表的结构,它只需要创建表的时候指定表和列族名字就可以,想写什么列就可以写入什么列,这个列是动态生成的。
第四个是它有很好的容错恢复的功能,比方这么多的分布式节点,单个节点宕机之后,可以快速的将这个计算计资源迁移到其他节点上去,可以提供服务,在客户端这一层感知到的异常基本上都可以做到自动的恢复。
同时它还可以支持 TTL、多版本的特性。比如海量数据下的一些历史数据的淘汰可以直接用 TTL,多半是一个业务场景中,单个列可能有多个版本,可以使用多方面的特性存储多个版本的数据。
二、HBase 查询原理
1、数据模型
基本概念
·Table:表名。
·Rowkey:行唯一键,也叫主键 Primary Key,字典序排序存储。
·Column Family:列族,同一列族的数据集中存储,单个表可包含多列族,TTL、高效压缩
·Column:列名.动态列,Schema Free,底层统一 byte [] 存储。
·Timestamp:每个列的时间戳。多版本,按照时间战最新原则排序。
常见查询
·主键查询。Rowkey Get
·范围查询。Rowkey Scan
·条件过滤。Rowkey Get/Scan+Filter
·多语言访问:Java/Python/C++/Go/PHP/nodejs等。
HBase 的数据模型有几个基本的概念,首先HBase 像关系数据库一样需要有表的名字,同一个表里面存储的是一样的数据,然后不同业务的数据可以存入不同的表,单个集群可以承载非常多的表。
第二个就是 RowKey 跟关系数据库的组件一样,唯一确定了 HBase 中单行的一行记录,同一 RowKey 数据会相互覆盖,数据也是按照字典去排序存储的,相当于按 ABC 顺序来存储,不会按照写入的数据存储。
第三个是列族的概念,相当于是在 HBase 里面同一个列族的数据是在同一个文件里面存储,可以确保在同一个场景的数据是集中存储的,写入和查询的时候效率高,同时列族也可以指定 TTL 和压缩的属性,属性不同的列族可以指定不同的 TTL 和不同的压缩数据。
第四个是列名,有了列族之后,每个列族下面可以有多个列名,列是一个动态列,相当于同一个列族下面的列的个数不固定,可以一直增加,同时这个列的类型没有定义,写入 HBase 中的时候,列的值需要把它转换成大的数字来进行存储。
第五个是时间戳,时间戳的概念相当于是每个列都会在写入到 HBase 中,默认的时间戳是当前系统时间的毫秒表示,业务一层也可以自己定义时间戳,时间戳主要应用于多版本,比如假设定义的例子版本,假设多版本是三个这个数据保存三份,然后按照时间戳最新的放在最前面,默认在查询的时候,查询出来的数据只有最新版本。
下面是一个简单的表格,表格记录了一个基础的样例,通过这个样例,加深一下对这几个基本概念的理解,第一个整个就是一个结构化的表,它有一个名字,首先 ID 其实就是 RowKey 组件,是一个一个数字来表示的,1001、1002、1003是按这个顺序来存储的,真实的数据也是按照这个数据存储的,比如1001最后写入,在数据存储的时候1001的数据也是排在1002和1003的前面。
列族 Info 和 data 是两个不同的列族名字, Info 列里面有很多个列,比如姓名,年龄,职业,性别是 column 列的名字, date 下面有两个列的名字, value 是每个列对应的值,20是年龄,小王是姓名列的值,需要注意的一点是动态列的概念,在列族里面数是不确定的,可以是不固定的,不需要事先定义好,假设在 info 这个列组里面再加一个列,直接在写数据的时候写,然后再写一个列X, X就会在这个表里面,不需要事先定义好,这是动态列的一个特点。还有一个特性是时间戳,比如例子中定义的城市列还有三个时间戳,杭州时间戳2019,北京值对应的时间戳2016,厦门对应的时间戳是2012,时间戳可以在自己写入值的时候写好也可以不写,不写的时候时间戳会以当前系统的时间来设置好,三个版本会同时在列里面存在,比如在检索1001的这个城市值的时候,默认只会返回最新的版本,如果想把多版本都返回需要再减少告诉说需要做几个版本,几个版本的数据都会返回来,这就是 HBase 的基本数据模型,通过数据模型也可以看到首先如果可以自点去排序,可以很方便的进行范围查询,比如去检索 ID 从1001 到 1003 的数据,可以直接用 Get 语句就可以把这几条数据全部返回,同时数据是按行来存储的,比如指定 ID 1001 可以快速的把这整行数据都取出,所以可以看到在 HBase 中最常见的几个查询场景,第一个是主键查询,相当于基于 Rowkey 值可以快速的把这一行数据给拿到,第二个是范围查询,可以指定 Rowkey 的范围,把符合范围的数据全部取出来,还有一种=是条件过滤,比如在 get或者 scan 这个数据的时候,还想指定某个列值等于某个条件的,比如检索范围是1001到1003的,年龄等于20的这个数据,它只会把这一行数据给检测出来,因为其他行这个列是没有的值的,不会把数据给牵扯出来,是 scan 加 filter, filter 相当于是过滤条件,除了指定 Rowkey 的范围之外,可以制定一个单独的条件,把满足条件的数据可以减少出来,同时上面三个查询是 HBase 中最常用的查询,而且是效率性能最高的查询模式。第四个是在查询的时候,可以使用多语言去查询,除了 HBase 衍生支持的除了 shell 以外和Java API 之外,还支持各种多语言的访问。
(1)举个例子(HBase Shell)
·建表:create'myTable,Y
·表名:myTable
·列族:f
·建表时必需的参数:表名和列族名。
·表预分区:建表时设置分区个数、分区范围,预分区是防止数据出现热点的最佳实践。
·列族属性:TTL、多版本、压缩、编码属性等。
·写数据:put 'myTable,1001,'fname,alice
·表名:myTable· RowKey:1001
·列族+列名:fname·值:alice
介绍如何通过 HBase 的 Shell 去创建一个表、写入数据以及通过 Shell 把数据检索出来,在这个例子中直接写了一条 HBase Shell 的语句, HBase Shell是开源提供的命令行工具,语法是自定义的语法,和 SQL 的语法不太一样,在后面过程中比如有了自己的环境之后,可以直接安装 HBase 的 Shell,它是一个客户端的 Shell 命令,在自己的环境中安装之后,可以直接进入这个命令操作,比如这边给了一个例子,创建了一个表,表名字是 myTable,列族是 F ,只要执行这条语句之后表就创建成功了,需要注意的是在创建表的时候,表名和列族名必须要指定,其他参数不需要指定,其他还有非常多的参数,在自己操作的时候可以直接输入 create 命令就可以看到帮助。
下需要强调一点是表的预分区,比如在创建表的时候,可以设置表有多少个分区以及它的分区范围的样子,因为在 HBase 中数据是按分区存储的,比方如拿上面这个例子,1001到1003是一个范围,可以定义比如101到 2000是一个分区, 2000到3000是另外一个分区,同一个分区的数据是在同一个节点内存储的,利用分布式的节点,可以定义很多个分区,相当于很多个分区可以分布到不同的节点上去提高写入和查询的方式称为预分区,相当于在建表的时候,提前把分区定义好,数据就可以很快速的分散到各个节点上去,是解决数据热点的一个最佳实践,比如像上面直接创建了这个表之后,分期客服里相当于只有一个节点可以提供服务,让数据写入。
撕裂的成两个分区可能会分布到两个不同的节点,随着数据不断的写入,两个分区可能会分成八个,相当于在刚开始的写入阶段,随着数据写入的不断增加,然后才会有更多,如果事先把分区设置好,相当于刚开始就有很多个节点提供服务。
还有一个是在创建表的时候,可以设置个表的列族,比方上面定义的列族的名字叫 F 。
TTL相当于比如这个列祖,定义在它整个列读下面的数据, TTL 可以保存一年两年,相当于可以定义每个列的版本保存多少个,默认情况下只有一个,同时定义数据压缩,压缩是采用什么样的压缩算法,还可以定义编码属性,都是列族的属性,上面分区类似于表的属性,可以对这个表设置多少个分区,同时对列族设置属性,不同的列族可以设置不同的属性,创建表的语句,同时在创建完之后,可以执行 Put 命令,可以把数据比如指定了表名指定 RowKey 比如这里举的这个子, RowKey 是1001后面就是列族和列,最后是值相当于把 RowKEY 等于1001,列族等于 F ,列名等于 name 的写入 alice ,需要注意的一点是在写入数据的时候,列名字不能唯一的确定一个列,需要列族和列名唯一确定一个列,这个表的属性,比如 info 和 data 是两个不同的列族,但是下面的列是独立的,有可能在 info 和 dat a里面会有相同的列的名字,相当于列名字,不能一直列名之后,不容易确定,需要和列族唯一确定一个列的名字,写出一条数据,在里面写了几条数据,相当于写了三行数据1001,1002,1003他分别写了三个列。
(2)举个例子(查询)
·主键查询:get myTable,1002
·范围查询:scan‘myTable ,(ISTARTROW=>’1002‘,STPROW =>‘1004’ }
·条件过滤:scan’myTable,(STARTROW=>‘1002’,STOPROW=>’1004’FILTER=>"SingleColumnValueFilter(‘f’,‘name’,=,‘binary:bob’)"}
需要去做查询看数据怎么样去查证出来,第一种比较快速的方式就是get 基于 rock 逐渐去把组件的整行数据检测出来,可以使用 get命令后面跟着表名字,然后在跟 RowKey 可以把这行数据给取到了。
下面是范围查询,可以通过 scan 命令,可以 Scan 这个表名字然后指定一个范围, STOPROW 是 HBase Shell 定义的关键字,比如会把1002和1004的数据给检索出来,需要注意的一点是 STOP 1002 是闭区间,1004是个开区间,相当于取出的数据是1002、1003、假设数据里面有1004,数据不会被检索出来的,因为右边是开区间。
第三个查询是条件过滤,相当于指定的一个范围,跟上面一样指定了一个1002、1004,还可以指定一个条件,比如这个范围内的数据有很多,但是符合条件的数据非常少,后面就跟一个 future, future 是一个过滤条件,是 name=bob 的这个列,这个用法是 HBase Shell 用法,后面在自己验证过程中可以直接输入这个 list futures就可以把当前所有支持的列出来,然后自己去测试,只是 HBase Shell 定义的这个用法,在真实的使用过程中用法更简单一点,不会像现在写的复杂。通过 HBase Shell 可以看出来,比如写了数据之后,然后可以通过 get、scan 把符合条件的数据给检测出来。
(3)Jave API 访问(Demo)
try
{
Table table
=
connection.gotTable(TableNane.valueO
f("myTable")
}}
{
//插入数据
Put put =nem Put(Bytes.tolytes(“1001)
};
put.adeColurn(Bytes.tobytes(“f"),Bytes.toBytes("na
m
e"),Bytes.toBytes("alice"))
;
table.put(put);
// 单行读取
Get get
=
nem Get(Bytes.tobytes(“1001")
}
;
Result res =table.
get<get>;
//scan 范围数据
Scan scan=neu 5can(Bytes.toBytes("181”),Bytes.toBytes
("1803")); Result
Scanner scanner
=
tablegotS
canner(scan); for (Result result :scanner){
//处理查询结果 result
// ...
}
scanner.close
();
}
除了上面讲的 HBase Shell这种查询语法之外,HBase 原生支持的是 Java API的访问,通过Java API 可以快速的取到某一行数据或者scan某些问题。
首先可以指定一个表名,获取一个 connection,然后 connection 相当于获取表的连接,然后再用一个 put 对象相当于要写一行数据,这一行数据在new put 的时候会指定 RowKey 是什么,这里指定的是1001,数据写的时候首先要指定列族再指定列的名字,然后指定列的值,相当于在写一行数据的时候,这几个条件必须指定内幕,它是无法确定的,必须要指定它的例子,然后就可以把这行数据给写进去,接下来就可以直接执行方法,比如指定数据拿到了,然后如果想范围查询,那 scan 指定一个范围,就可以把数据符合,符合条件的数据就拿到了,还有很多丰富的语法可以通过链接里面看到详细的使用方法。
通过 HBase 查询章节介绍了如何理解HBase 的一个基本的概念以及理解。
理解了 HBase 数据模型之后可以很方便的把数据按照 HBase 的概念去写入进去,通过全程支持这个语法把数据给检索出来。
三、Phoenix 入门
1、Phoenix 简介
Phoenix: OLTP and operational analytics for Apache Hadoop.
·Salesforce 公司主导的Apache开源项目,致力于“put the SQL back in NoSQL”,提升 HBase 的使用体验,赋予 HBase OLTP 和轻量级 OLAP 的能力,遵循 ANSISOL-92 标准,支持 JDBC API、Transactions、UDF、Secondary Indexes、Salt Tables等
·语法丰富,支持group by/order by/join/subquery/function等(Phoenix Grammar)。
·豪秒级交互式体验,MPP并行执行,充分利用 HBase Coprocessor实现计算下推。
Phoenix 是 Apache 开源的软件,Salesforce 公司主导的开源项目,其实最主要的应用场景是作为 HBase 的 SQL 层,可以让 HBase 具备 OLTP 的能力以及轻量级的 OLAP 的分析能力,同时分离,它其实是兼容 SQL 的标准,可以直接用 GDP 接口直接访问HBase ,Phoenix 还支持UDF、Secondary Indexes、Salt Tables等高级特性,扩展了 HBase 的使用场景,同时 Phoenix 的语法也非常的丰富,跟标准思路一样也支持 group by、order by、 joinsubquery 以及 function。可以在 Phoenix 的官网上去看一下详尽的语法。
Phoenix 是在 HBase 的基础上加了一层 SQL,从图中也可以看到,加了一个 SQL 的引擎层,Phoenix 的性能也是非常非常的快的,可以毫秒级的去获取到,比如某一行的的 Skip 查询,包括分析的查询,MPP 的架构可以正常的去执行,还能非常充分的利用 HBase 性能处理器的特性,将计算下推相当于数据不需要移动,只需要计算下推到 HBase 的这一层,就可以加速查询和计算,这是Phoenix 一个基本的特性,有了 Phoenix 之后操作 HBase 就非常的简单了,可以像普通的 SQL 一样去操控表和数据。
2、Phoenix SQL
(1)Phoenix SQL(一)
基本使用(Phoenix Sqlline)
·建表: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‘);
Phoenix SQL 如何操作 HBase ,Phoenix 有专门的 Sqlline,下载 Sqlline 之后也是一个客户端的程序,可以通过 Sqlline 连接到 Phoenix 集群,可以在上面直接创建表去读写数据。比如创建了一个表,同样表名是 my table ,列是 ID 是 VARCHAR ,primary key 是主键,然后 name 列,age 列和 sex 列是列名字,然后表的名字逐渐每个列的类型也是可以在创建表的时候指定的。在创建完表之后,可以直接去把想象的数据直接 upsert 进去,这也是一种标准的 mysql 的语句,第一个是主键 id 1001后面跟着一行的值写进去,介绍了几个例子,比如把三行数据写进去,再通过Sky 的操作,可以把表的数据给检测出来,表的数据按照字典的顺序有序的存放。
(2)Phoenix SQL(二)
基本使用
·主键查询: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 Shell 去检索一行数据或者范围查询,通过Phoenix SQL 也可以去获取一行数据,进行简单的范围查询,比如第一个就是 select 行,From table,然后where条件后面跟的是一个主键,取出来就是一行数据。第二个是范围查询,把1002到1004的数据来查询,符合条件的数据检测出来,然后也可以看到它检测的数据是1002、1003。第三个查询就是一种过滤的条件,比如这两个数据里面,想把 name 预报的数据检测出来,就可以通过这条语句给检测出来,这是一种范围查询的使用,通过 SQL 语句操作,HBase 会更加的简单对于开发人员来说也是更加简单的应用。
(3)Phoenix SQL(三)
Phoenix 语法也非常的丰富,在 Phoenix 的官网也可以看到语法的列表,通过语法列表可以看到它基本上涵盖了类似于 Circle92 所有的语法,每个语法的使用都可以详尽地看到如何去使用。
比如是线上的查询的场景,也可以做到两个不同表的做障碍查询,这是一种非常常见的语法,Phoenix 可以高效的去支持语法,这一节主要介绍通过 Phoenix 如何如何使用 SQL 来操作 HBase 让开发和运维更加的简单。
四、查询加速
1、多样化的查询
来源于业务的真实需求
·多维查询.即席查询,一般是不固定的列随机组合。
·count 计数.获取数据表的总行数,或者返回一次查询命中的数据条数。
·指定列排序.按照指定列降序或升序,比方说按照订单时间降序输出结果。
·分词检索.支持文本字段的分词检索,返回相关性较高的结果数据。
·统计聚合.按照某个字段进行聚类统计,求取 sum/max/min/avq 等,或者返回去年后的结果集。
·模糊查询.查询以“中国”开头的数据,可以四配出“中国人民”的结果集,类似 MySOL 的 like 语法。
解决方案
·协处理器,计算下推,服务端执行逻辑。
·二级索引,变换数据存储格式,加速非主键查询。
·全文索引。引入搜索引掌解决查询难题。
除了 HBase 支持的主键查询,范围查询,过滤之外,随着数据量增加业务的场景会更加的多样化,来源于真实的业务的需求,第一个是多维的查询,相当于指定可能是不同的多个非主键列去进行检索,这是一种查询条件,而不是简简单单的指定一个主键,指定的是一个非主键。第二个是 count 计数,比如要检索出来符合条件的条数有多少个,因为 HBase 的 get 查询和 scan 查询只能把结果取到,并不能真正的取得技术的条件,也可以通过分离一切处理器处理,第三个,比如指定列的排序原生的的 HBase 不支持排序的,只能是按照主键排序,因为主键在存储的时候已经按照字典序来排序,在查询的时候返回的数据自然就按照字典序来排序,但是如果想指定那一列的排序是不支持的。
还有一种场景是分词的检索,比如写入的数据可能是一种文本字,进行分词检索也是一种经常见的需求。
还有一种统计的聚合,比如想进入某个字段进行依据一些距离统计,要统计它的 sum、max 最小值和平均值等。还有一种比如需要模糊检索的功能,类似于输入一个条件,然后把符合条件的数据检索出,面对这些需求,在使用 HBase 中的时候同样的解决方案我,给大家详细介绍一下:第一个是协处理器,是 HBase 开源本身就支持的方式,主要的逻辑像计算下推,让运算的逻辑在服务端执行相当于很多场景下,不需要把数据拿到客户端来计算,只需要写一个协处理器,让这个逻辑在服务端运行就可以,速度比单纯的把数据拖到客户端来说,会快非常多。
第二个是二级索引,比方说前面讲的非主键查询,因为它是和数据的存储格式是完全不一样的,因此查询的性能会非常的低,有了二级索引之后就可以把数据进行一些重写相当于按照把非主键放到主键里面去,这样在查询的时候效率会非常的高。第三个通用的解决方案,是全文索引,可以引入一些搜索引擎,将 HBase 的数据建立索引,加快查询。
(1)协处理器
计算下推
·协处理器 Coprocessor,逻辑在服务端运行,避免移动数据,加速处理。
Observer,与数据库的触发器类似,在一些特定事件发生时执行回调函数。HBase 服务端的内核逻辑已经在固定的流程中埋点,例如在 put写数据前执行一段通数 prePut,put 写数据后执行一段角数postPut。
Endpoint,与数据库的存储过程类似,客户端远程调用服务端的代码,例如 HBase 原生支持的聚合 Aggregate,求 max/min/avg。
协处理器是 HBase 元成就支持的,逻辑是在服务端运行的,主要是避免数据的移动,加速数据的处理,通常客户端到服务端的网络一般情况下是不会太高,但是服务端内部之间的网络是非常高的,客户端拿到自己一端来计算,效率非常低,所以协处理器之后,可以自己实现一个协处理器,将逻辑运行在服务端。
HBase 的协处理器有两种模式,第一种就是 Observer 类似于数据库的触发器,是在 HBase 服务端的代码里面,先把回调函数已经进行了买点,在写入流程 put或者 scan 流程里面前后都加一些买点,业务想写一个 Observer 可以继承一个激烈的 Observer, Observer 重写 preput 或者postput 两个接口,相当于一条数据在写进去会首先调 preput ,然后调到逻辑里面去,最后的时候再调一下你的逻辑,就可以在自己的逻辑加一些特殊的处理,比如把这个数据进行一次、二次处理,这就是 Observer 基本的实现。还有一种协处理器的实现叫 Endpoint ,它的实现和数据库的存储过程是类似的,相当于客户端远程调用服务端的一些代码,让代码在服务端运行,HBase 的 Endpoint 也相当于是 MPP 的执行,可以在多个节点多个 lead 并发的去执行,比如说原生支持聚合的功能,求最大值、最小值,就可以使用 Endpoint 协处理器,加载到某个表上去之后就可以直接调用协处理器,然后让服务端按照某个条件去执行查询,这是协处理器的简单介绍。
2、二级引索
(1)非主键索引
·非主键查询,扫描所有数据过滤数据查找 name 列值为 'bob的所有数据
scan
‘myTable’,(FILTER=>‘SingleColumnValueFilter( ’f‘’name‘,=,’binary:bob)"}
数据量大的场景,查询耗费资源,可能还会超时
二级索引首先介绍一下非主键查询,前面讲的主要是主键 Row Key 的查询或者主键 Row Key 的范围查询,如果在条件里面单纯的指定一个列去查询,就没有指定主键,相当于里面介绍的一个例子,扫描 My Table 这个表条件是 name=bob 的数据,如果表的数据非常大,需要把所有的数据都扫描出来,然后一个一个去判断 bob ,如果是的话符合,如果不符合就跳到下一条数据,这种查询条件会非常消耗资源,因为它每一套数据都要进行扫描,没有逐渐的,而且这种扫描有可能会超过设置的时间,基本上就导致了查询不可用,面对这种场景最通用的解决方案是用 HBase 的二级索引,比如右边查询的模型右边是主表的查询,有 RowKey 有列,RowKey 是按顺序存储的,如果想检索 COLUMN2 条件里面只有二,就可以建一个二级,所以左边就是一个二级,所以表是一个单独的表,表的主键就是 COLUMN2 和 RowKey 组成,相当于通过COLUMN2 和 RowKey 唯一确定索引表的一行数据,在检索条件等于 COLUMN2 的时候,因为索引表主键里面有 COLUMN2 可以快速地去检索出符合条件的数据,这就是二级索引的这样一个实现原理
(2)基于协处理器实现二级索引
·基于 Observer 实现二级索引
·在 put/delete 流程中解析写入的数据,构造索引数据,写入到索引表中
·在 scan 流程中解析查询语法,命中索引,则查询索引表,没有命中索引,则查询原表
Phoenix 通过协处理器来实现的,是一个简单的实现原理。可以实现一个 observer ,可以在 put delete 或者其他的接口里面加入处理函数,收到一条数据的时候可以构造所引数据。
比如在例子里面,假设写入了一行数据,在收到这一行数据的时候,就可以拼接出索引数据 Col2 、RowKey 写到索引表里面去,相当于这一行数据在写的时候,协处理器自动把数据写到索引表里面,正常的行数据还是写到主表里面去,逻辑执行完之后,业务端虽然写了一条数据,但其实在主表和索引表里面有两条数据,在检索 Scan 的时候,也会掉到 observer 协处理器,因为可以在 Scan 的逻辑里面加入自己的逻辑,然后判断一下这个条件里面是否带 Col2 的条件,比如只带了 Col2,就可以直接通过索引表快速的把数据检索出来,通过协助一些observer 然后快速实现了二级的方案,比如在使用 HBase 的过程,没有使用 Phoenix 组件可以自己去实现一个 observer,observer类似于可以实现一个简单的二级索引。
3、全文引索(HBase+Elasticsearch)
业务双写
·简单,业务快速落地
·开发成本高:应用同时与 HBase 和 Elasticsearch 交互
·维护复杂:熟悉 HBase 和 Elasticsearch 技术栈
·数据不一致。
数据自动同步
·无需双写,只需双读,开发成本降低
·数据最终一致
·维护复杂:熟悉 HBase 和 Elasticsearch 技术栈、数据同步服务
Observer
触发器
·仅与 HBase 交互,应用开发成本进一步降低,但要额外开发Observer 程序
·维护复杂:熟悉 HBase 和 Elasticsearch 技术栈,Observer 容易引起系统不稳定
·写入延迟:Elasticsearch 写入阻塞全局
全文索引 HBase+Elasticsearch 解决方案也是很多人会使用的一个方案,通过 HBase 的高效查询,再通过 Elasticsearch 的全文索引,满足多样化的查询场景, HBase+Elasticsearch 方案也是有非常多的,首先 HBase+Elasticsearch 第一种比较通用的方案是业务的双写,比如可以在前端接入一个消息队列,数据在来的时候可以同时写 HBase 和 Elasticsearch ,这种方案非常的简单可以快速的去落地,在查询的时候也是可以比如查询 Elasticsearch 也可以去查询 HBase,对于开发来说可能需要掌握两个组件 API 的使用,同时还要维护两个不同的组件,这种方案比较大的一个缺陷是数据的一致性不好保证,因为在数据写入的时候可能某一个组件写入成功,某一个组件写入失败,需要一些重试或者其他额外的处理,假设没有做处理可能数据就会不一致。
第二种比较常用的方案是 HBase+Elasticsearch 中间加一个消息通道,消息通道可以利用 HBase Occasion的一个协议,将 HBase中的数据实时的同步到 Elasticsearch 中去。对于开发者层面来说只需要关心 Elasticsearch 的查询,不需要再去双写到 Elasticsearch 。因为只要把数据写到 HBase 里面去之后,HBase 就会生成 log,log 会通过education 借助学习通道同步到 Elasticsearch 中去。这是写入流程,消息通道大部分情况下可能是需要自己去写一个维护服务,开源也有比如 HBase 有一种开源的index 可以将 HBase 的数据实时同步到 scar 中去。
还有一种方案是利用 HBase 协处理器来实现写入和查询的自动处理,上面一层业务直接就接触 HBase 就可以。比如查询和写入只写 HBase,Elasticsearch 是一个透明的组件,只需要实现一个 HBase的协处理器。这个协处理器就可以自动在有数据的时候把数据同步到Elasticsearch 查询的时候就会从 Elasticsearch 查询出来,这是协处理器的实现。类似于二级索引,所需的时间也是类似的。这种实现最主要的成本是要开发协处理器,程序需要开发的健壮一点,因为协处理器一旦挂载之后,会影响整个的写入流程,一条数据写入之后,协处理器执行完之后,请求才真正的返回给客户端。假设协处理器写的不够健壮可能会影响原始写入的性能。
三个通用的 HBase+Elasticsearch 方案,通过这几个方案可以完全的满足多样化的查询,Elasticsearch 加二级索引通过额外的索引解决了 HBase 原生不支持的比方如 ady、排序还有多维的 ad hoc 查询。
五、总结
01 HBase 回顾
开源历史
适用场景
02 HBase 查询原理
数据模型
主键查询
范围查询
条件过滤
03 Phoenix 入门
Phoenix 简介
Phoenix SQL
04查询加速
协处理器
二级索引
全文索引
前面介绍了 HBase 比如在遇到其他多样化的产业的时候,如何去解决的基本方案,回顾一下整个课程,首先讲了 HBase 的历史、开源的历史以及 HBase 可以用到的场景,在用到 HBase 之后如何去做 HBase 数据的检索、查询,首先讲 HBase 的数据模型,通过 HBase 的数据模型介绍 HBase 表、rock、列族、列以及时间戳组成,rock是按照字典序来排序的,一个列族和列确定列真实的数据,检索的时候可以直接指定 rock 或者指定范围查询,还有是指定一个条件把符合条件的数据检索出来。第三个讲了通过 SQL 操作 HBase开发更加的简单和应用,同时 Phoenix 支持一些高阶的功能,弥补了 HBase 的原始功能的缺陷。
第四讲了在 HBase 的使用过程中,如果面对复杂的查询如何去解决,可以通过 HBase 延伸的协处理器,或者 HBase 的二级索引以及引入其他的搜索引擎来实现全文索引,满足业务场景。