说明在CDH环境中,如何使用CDH公司提供hbase-indexers对HBase进行二级索引。

HBase Indexers

HBase的二级索引方案特别多,其中使用Solr建立二级索引是用的比较多的。

CDH集成了Key-Value Store Indexer服务,该服务能够为HBase动态更新Solr上的索引!这个服务在Github上的项目名叫hbase-indexer。

HBase Indexers在CDH中主要用来和 Cloudera Search 配套使用,但是我经过尝试后发现,脱离Search这个东西实际上可以独立使用。

HBase Indexer使用HBase的备份接口拦截对表的读写请求,并异步通知Solr更新索引。由于整个过程交互是异步的,因此使用这个方案不会对HBase产生性能影响,但是Solr上建立索引的时效性可能会延后。Cloudera官方给出的时延级别是秒级!

Key-Value Store Indexer服务依赖Zookeeper实现高可用、以及配置同步,Zookeeper上的Znode节点是hbaseindexer

使用说明

我们需要安装:Solr、HBase、Key-Value Store Indexer三个服务。

创建HBase表

假设我们的HBase表结构是下面这样的:

1
2
3
4
5
6
7
# HBase 中dict_app表
#
#
# 天涯论坛 | 16 | 0 | 博客·论坛 |天涯论坛
# rowkey | app_class_id |is_loan| app_class |app_abbr
#
# 表中所有字段属于info列族,类型都是字符串

我们在创建dict_app表时需要打开表的备份功能:

1
create 'dict_app', {NAME=> 'info', REPLICATION_SCOPE=> 1}

创建Solr上的Collection

使用solrctl命令我们创建集合dict_app,这个Collection用来保存dict_app表的索引。

1
2
3
4
5
6
7
8
9
10
# 创建本地配置文件
solrctl instancedir --generate dict_app_config

# 修改schema文件

# 上传配置文件到Zookeeper
solrctl instancedir --create dict_app_config dict_app_config

# 创建Collection
solrctl collection --create dict_app -s 2 -c dict_app_config

我们在创建dict_app前,需要修改 dict_app_config/conf/managed-schema 文件,预先定义相关的字段。

1
2
3
4
5
6
7
<!--
我们将dict_app表除row key以外的列都定义成索引,row key是集合的ID
-->
<field name="app_class_id" type="text_general" indexed="true" stored="true"/>
<field name="is_loan" type="text_general" indexed="true" stored="true"/>
<field name="app_class" type="text_general" indexed="true" stored="true"/>
<field name="app_abbr" type="text_general" indexed="true" stored="true"/>

创建Indexer

我们可以使用hbase-indexer命令创建索引,但是创建之前我们需要编辑两个文件!

indexer.xml 这个文件告诉hbase-indexer我们为哪张表创建索引,以及morphlines.conf文件的位置!

1
2
3
4
5
6
<?xml version="1.0"?>
<indexer table="dict_app" mapper="com.ngdata.hbaseindexer.morphline.MorphlineResultToSolrMapper">

<param name="morphlineFile" value="/etc/hbase-solr/conf/morphlines.conf"/>

</indexer>

morphlines.conf 这个文件将Collection的字段信息和HBase列对应起来,每个Indexer都要能在同样的节点访问到这个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
morphlines : [
{
id : morphline1
importCommands : ["org.kitesdk.morphline.**", "com.ngdata.**"]

commands : [
{
extractHBaseCells {
mappings : [
{
inputColumn : "info:app_class_id"
outputField : "app_class_id"
type : string
source : value
},
{
inputColumn : "info:is_loan"
outputField : "is_loan"
type : string
source : value
},
{
inputColumn : "info:app_class"
outputField : "app_class"
type : string
source : value
},
{
inputColumn : "info:app_abbr"
outputField : "app_abbr"
type : string
source : value
}
]
}
}

{ logTrace { format : "output record: {}", args : ["@{}"] } }
]
}
]

分发命令后使用以下命令创建Indexer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建Indexer
hbase-indexer add-indexer \
--name dict_app \
--indexer-conf indexer.xml \
--connection-param solr.zk=bdnode1:2181,bdnode2:2181,bdnode3:2181/solr \
--connection-param solr.collection=dict_app \
--zookeeper bdnode1:2181,bdnode2:2181,bdnode3:2181

# 改动配置文件后更新Indexer
hbase-indexer update-indexer -n myIndexer -c indexer.xml

# 列出所有Indexer
hbase-indexer list-indexers

# 查看indexer状态
hbase-indexer replication-status

存在的问题

  • 直接truncate表示,索引似乎不会自动更新。
  • indexer服务退出可能造成部分行写入时没有进行索引,并且当服务恢复以后,需要手工运行MR任务来重建索引!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 先从HBase捞出数据到HDFS上,然后将HDFS中的数据发到solr
export HADOOP_USER_NAME=solr; \
HADOOP_CLIENT_OPTS='-DmaxConnectionsPerHost=10000 -DmaxConnections=10000'; \
hadoop --config /etc/hadoop/conf \
jar /opt/cloudera/parcels/CDH/lib/hbase-solr/tools/hbase-indexer-mr-*-job.jar \
--conf /etc/hbase/conf/hbase-site.xml \
-D 'mapred.child.java.opts=-Xmx500m' \
--hbase-indexer-file indexer.xml \
--zk-host bdnode1:2181,bdnode2:2181,bdnode3:2181/solr \
--collection staSyslog \
--go-live \
--output-dir hdfs://nameservice1/hbase_test/offline_indexer/staSyslog \ # 这个目录要属于solr用户,并且solr可以访问
--overwrite-output-dir \
--clear-index \
--log4j /etc/hbase-solr/conf/log4j.properties

# 直接将Hbase中的数据发到Solr
HADOOP_CLIENT_OPTS='-DmaxConnectionsPerHost=10000 -DmaxConnections=10000'; \
hadoop --config /etc/hadoop/conf \
jar /opt/cloudera/parcels/CDH/lib/hbase-solr/tools/hbase-indexer-mr-*-job.jar \
--conf /etc/hbase/conf/hbase-site.xml \
-D 'mapred.child.java.opts=-Xmx500m' \
--hbase-indexer-file indexer.xml \
--zk-host bdnode1:2181,bdnode2:2181,bdnode3:2181/solr \
--collection staSyslog \
--reducers 0 \
--clear-index \
--log4j /etc/hbase-solr/conf/log4j.properties

参考

hbase-indexer
官网
Lily HBase Near Real Time Indexing for Cloudera Search
Lily HBase Batch Indexing for Cloudera Search