一种基于UDH Search的HBase二级索引构建方案
作者 : 费英林
目录
本文实现了一种 HBase 二级索引的构建方案,通过该方案,用户可以方便的实现 HBase 中单列或多列数据的索引创建及查询。为了实现分布式索引的创建和查询,该方案利用 CDH Search 、 HBase 主从集群以及索引读取 Coprocessor 来实现索引的生成与读取。该系统有效的结合了批处理和实时处理两种方式,充分利用了 HBase Coprocessor 的工作机制,系统本身具有很好的扩展性,可以快速方便的扩展计算能力和存储容量。
1. 系统概要
1.1. 背景介绍
HBase 是一个列存数据库,每行数据只有一个主键 -RowKey ,无法依据指定列的数据进行检索。查询时需要通过 RowKey 进行检索,然后查看指定列的数据是什么,效率低下。在实际应用中,我们经常需要根据指定列进行检索,或者几个列进行组合检索,这就提出了建立 HBase 二级索引的需求。
目前的 HBase 二级索引构建方案主要有两种。第一种方案是将索引数据单独存储为一张表,通过 HBase Coprocessor 生成并访问索引数据。第二种方案是将索引数据与源数据存储在相同的 Region 里,索引数据定义为一个单独的列族,也是利用 Coprocessor 来生成并访问索引数据。对于第一种方案,源数据表与索引表的数据一致性很难保证,访问两张不同的表也会增加 IO 开销和远程调用的次数。对于第二种方案,单表的数据容量会急剧增加,对同一 Region 里的多个列族进行 Split 或 Merge 等操作时可能会造成数据丢失或不一致。
1.2. 系统架构
本方案针对已有 HBase 二级索引构建方案中的不足,提出了基于 UDH Search 、 HBase 主从集群以及 HBase Coprocessor 的分布式索引构建方案。该方案分离了索引的创建和读取过程,将索引文件与 HBase 数据文件分开存储,提高了系统的 IO 性能,充分结合了批处理和实时处理两种流程,解决了数据一致性问题,减少了索引中的冗余数据。基于 Hadoop 的整体设计也保证了系统的高可用性和高可扩展性。
1.3. 系统构成
1) 主 HBase 集群:使用 UDH 部署的 Hadoop 集群。主集群用于满足高速读写的需求,同时以异步的方式将接收到的数据复制到从集群。
2 )从 HBase 集群:使用 UDH 部署的 Hadoop 集群。用于数据备份及索引创建,也可以作为分布式索引服务器。
3 ) Lily HBase NRT Indexer :是 UDH 的一个实时索引创建服务,部署在从集群。
4 ) Lily HBase Batch Indexer :是 UDH 的一个基于 MapReduce 计算模型的批量索引创建服务,部署在从集群。
5 ) HDFS : Indexer 生成的索引文件存储在 HDFS 里, Search 服务器读取并缓存这些索引数据。
6 ) UDH Search 服务:是一个索引创建与检索服务,它与 UDH 高度集成,核心系统是 Apache Solr- 包括 Apache Lucene , SolrCloud , Apache Tika 和 Solr Cell 。
7 ) Index Read Coprocessor :是 HBase 的插件。
2. 系统安装与配置
2.1. HBase Replication集群配置
参见“技术分享 - 如何配置 UDH HBase Replication 集群”一文,用 UDH 分别部署主集群和从集群。在主集群上对数据进行增删改操作,检查从集群上的数据情况,应与主集群数据一致。
2.2. UDH Search服务安装
在从集群上部署 UDH Search 服务,参见“专题 -UDH Search 系统构建及其应用”一文。需要配置 Lily HBase Batch Indexer 和 Lily HBase NRT Indexer ,分别用于索引的批量创建和实时创建,其中索引的实时创建是利用 HBase 的 Replication 机制实现的。
3. 索引创建 – 写路径
Search 有两种索引创建方式,即批量创建和实时创建。
3.1. 配置文件
配置 Solr Collection 的配置文件 schema.xml 和 M orphline 的相关文件,对 RowKey 和列族中相关列建立索引。例如,我们希望对列族 colfam1 的列 col1 和 col2 建立索引,相应的配置项应为:
1 ) Morphline 配置文件:
morphlines : [
{
id : morphline1
importCommands : ["org.kitesdk.morphline.**", "com.ngdata.**"]
commands : [
{
extractHBaseCells {
mappings : [
{
inputColumn : " colfam1 : col1 "
outputField : " colfam1_col1 "
type : string
source : value
}
{
inputColumn : " colfam1 : col2 "
outputField : " colfam1_col2 "
type : string
source : value
}
]
}
}
{ logTrace { format : "output record: {}", args : ["@{}"] } }
]
}
]
注: RowKey 字段默认对应 Solr Schema 中的 id 字段,不需要显式配置。
2 ) Solr 配置文件片段:
<field name=" colfam1_col1 " type="text_general" indexed="true" stored="true" />
<field name=" colfam1_col2 " type="text_general" indexed="true" stored="true" />
3.2. 数据流
索引生成有两种方式。
1 )批处理模式
步骤 1 :客户端输入数据到主集群
步骤 2 :主集群复制数据到从集群
步骤 3 :在某时间点启动 Lily HBase Batch Indexer 作业,生成索引数据
步骤 4 :索引数据加载到 Search 服务器
2 )实时模式
步骤 1 :客户端输入数据到主集群
步骤 2 :主集群复制数据到从集群
步骤 3 :从集群向 Lily HBase NRT Indexer 服务中写入数据,生成索引数据
步骤 4 :索引数据加载到 Search 服务器
4. 索引读取 – 读路径
读路径只有一种,即通过 Coprocessor 插件实现索引数据的查询。
4.1. Coprocessor实现
我们需要实现一个 Solr 索引读取的 Coprocessor ,它要继承 RegionObserver 接口。在实现类里加入 RowKey 解析及 Solr 索引数据读取的逻辑。
4.2. 部署
通过 HBase Shell 客户端将我们的 Coprocessor 部署到对应的 HBase 表里,重启表。
4.3. 数据流
索引读取流程:
步骤 1 :客户端构造新的 RowKey ,将索引列作为 RowKey 的一部分,比如将 colfam1_col1 的值加入新的 RowKey
步骤 2 :客户端以新的 RowKey 向主集群发起查询
步骤 3 :主集群调用 Coprocessor ,根据步骤 1 的构造规则检查 RowKey 中是否存在索引列,即检查是否存在 colfam1_col1 的数据
步骤 4 :如果存在索引列 colfam1_col1 ,调用 Solr API ,根据 colfam1_col1 的值读取相关的原始 RowKey ,即索引数据中的 id 字段
步骤 5 :如果不存在索引列,则认为传入的数据就是原始的 RowKey ,不需要检索 Solr 数据
步骤 6 :依据 4 或 5 的处理结果执行查询
Attachments:
专题_基于UDH的一种实时查询系统构建方案.docx (application/vnd.openxmlformats-officedocument.wordprocessingml.document)
图1.png (image/png)
图2.png (image/png)
图3.png (image/png)
图4.png (image/png)
专题-一种基于UDH Search的HBase二级索引构建方案.docx (application/vnd.openxmlformats-officedocument.wordprocessingml.document)
专题-一种基于UDH Search的HBase二级索引构建方案.docx (application/vnd.openxmlformats-officedocument.wordprocessingml.document)
专题-一种基于UDH Search的HBase二级索引构建方案.docx (application/vnd.openxmlformats-officedocument.wordprocessingml.document)