CDH5.3.2中的Key-Value Indexer使用的是Lily HBase NRT Indexer服务,Lily HBase Indexer是一款灵活的、可扩展的、高容错的、事务性的,并且近实时的处理HBase列索引数据的分布式服务软件。它是NGDATA公司开发的Lily系统的一部分,已开放源代码。Lily HBase Indexer使用SolrCloud来存储HBase的索引数据,当HBase执行写入、更新或删除操作时,Indexer通过HBase的replication功能来把这些操作抽象成一系列的Event事件,并用来保证写入Solr中的HBase索引数据的一致性。并且Indexer支持用户自定义的抽取,转换规则来索引HBase列数据。Solr搜索结果会包含用户自定义的columnfamily:qualifier字段结果,这样应用程序就可以直接访问HBase的列数据。而且Indexer索引和搜索不会影响HBase运行的稳定性和HBase数据写入的吞吐量,因为索引和搜索过程是完全分开并且异步的。Lily HBase Indexer在CDH5中运行必须依赖HBase、SolrCloud和Zookeeper服务。
使用Lily HBase做近实时索引处理。
创建HBase表时启动列族的replication功能。使用如下命令:
create 'table',{NAME => 'cf', REPLICATION_SCOPE => 1} #其中1表示开启replication功能,0表示不开启,默认为0
如果是对于已创建的表,可以使用如下命令:
disable 'table'
alter 'table',{NAME => 'cf', REPLICATION_SCOPE => 1}
enable 'table'
创建流程参看:http://blog.csdn.net/kissmelove01/article/details/45043955。需要说明的是,在schema.xml中uniqueKey必须为rowkey,而rowkey使用'id'字段表示,所以<field>中必须要有id字段,这个在Cloudera Search文档中并没有说明,查了很多资料才找到相关说明。其它需要索引字段根据用户需要自定义即可。
在HBase-Solr的安装目录/usr/lib/hbase-solr/下,创建morphline-hbase-mapper.xml文件,文件内容如下:
$ cat $HOME/morphline-hbase-mapper.xml
<?xml version="1.0"?>
<indexer table="record" mapper="com.ngdata.hbaseindexer.morphline.MorphlineResultToSolrMapper">
<!-- The relative or absolute path on the local file system to the morphline configuration file. -->
<!-- Use relative path "morphlines.conf" for morphlines managed by Cloudera Manager -->
<param name="morphlineFile" value="morphlines.conf"/>
<!-- The optional morphlineId identifies a morphline if there are multiple morphlines in morphlines.conf -->
<!-- <param name="morphlineId" value="morphline1"/> -->
</indexer>
Morphlines是一款开源的,用来减少构建hadoop ETL数据流程时间的应用程序。它可以替代传统的通过MapReduce来抽取、转换、加载数据的过程,提供了一系列的命令工具,具体可以参见:http://kitesdk.org/docs/0.13.0/kite-morphlines/morphlinesReferenceGuide.html。对于HBase的其提供了extractHBaseCells命令来读取HBase的列数据。我们采用Cloudera Manager来管理morphlines.conf文件,使用CM来管理morphlines.conf文件除了上面提到的好处之外,还有一个好处就是当我们需要增加索引列的时候,如果采用本地路径方式将需要重新注册Lily HBase Indexer的配置文件,而采用CM管理的话只需要修改morphlines.conf文件后重启Key-Value HBase Indexer服务即可。具体操作为:进入Key-Value Store Indexer面板->配置->服务范围->Morphlines->Morphlines文件。在该选项加入如下配置:
morphlines : [
{
id : morphline1
importCommands : ["org.kitesdk.morphline.**", "com.ngdata.**"]
commands : [
{
extractHBaseCells {
mappings : [
{
inputColumn : "data:opcode"
outputField : "opcode"
type : string
source : value
}
{
inputColumn : "data:source_id"
outputField : "source_id"
type : string
source : value
}
{
inputColumn : "data:source_seq"
outputField : "source_seq"
type : long
source : value
}
{
inputColumn : "data:username"
outputField : "username"
type : string
source : value
}
{
inputColumn : "data:account_id"
outputField : "account_id"
type : string
source : value
}
{
inputColumn : "data:product_id"
outputField : "product_id"
type : string
source : value
}
#{
# inputColumn : "data:item"
# outputField : "_attachment_body"
# type : "byte[]"
# source : value
#}
]
}
}
#for avro use with type : "byte[]" in extractHBaseCells mapping above
#{ readAvroContainer {} }
#{
# extractAvroPaths {
# paths : {
# data : /user_name
# }
# }
#}
{ logTrace { format : "output record: {}", args : ["@{}"] } }
]
}
]
importCommands:需要引入的命令包地址。
extractHBaseCells:该命令用来读取HBase列数据并写入到SolrInputDocument对象中,该命令必须包含零个或者多个mappings命令对象。
mappings:用来指定HBase列限定符的字段映射。
inputColumn:需要写入到solr中的HBase列字段。值包含列族和列限定符,并用‘ : ’分开。其中列限定符也可以使用通配符‘*’来表示,譬如可以使用data:*表示读取只要列族为data的所有hbase列数据,也可以通过data:my*来表示读取列族为data列限定符已my开头的字段值。
outputField:用来表示morphline读取的记录需要输出的数据字段名称,该名称必须和solr中的schema.xml文件的字段名称保持一致,否则写入不正确。
type:用来定义读取HBase数据的数据类型,我们知道HBase中的数据都是以byte[]的形式保存,但是所有的内容在Solr中索引为text形式,所以需要一个方法来把byte[]类型转换为实际的数据类型。type参数的值就是用来做这件事情的。现在支持的数据类型有:byte[](原封不动的拷贝hbase中的byte[]数据),int,long,string,boolean,float,double,short和bigdecimal。当然你也可以指定自定的数据类型,只需要实现com.ngdata.hbaseindexer.parse.ByteArrayValueMapper接口即可。
source:用来指定HBase的KeyValue那一部分作为索引输入数据,可选的有‘value’和'qualifier',当为value的时候表示使用HBase的列值作为索引输入,当为qualifier的时候表示使用HBase的列限定符作为索引输入。
当前面的所有步骤完成之后,我们需要把Lily HBase Indexer的配置文件注册到Zookeeper中,使用如下命令:
hbase-indexer add-indexer -n batchrecordIndexer -c $HOME/morphline-hbase-mapper.xml --connection-param solr.zk=xhadoop1:2181,xhadoop2:2181,xhadoop3:2181,xhadoop4:2181,xhadoop5:2181/solr --connection-param solr.collection=batchrecord --zookeeper xhadoop1:2181,xhadoop2:2181,xhadoop3:2181,xhadoop4:21281,xhadoop5:2181
向HBase中配置的索引表写入数据,如下:
put 'record','row1','data:opcode','20035'
put 'record','row1','data:source_id','p-sx1z1'
put 'record','row2','data:opcode','20036'
put 'record','row2','data:username','zhangsan'
当写入数据后,稍过几秒我们可以在相对于的solr中查询到该插入的数据,表明配置已经成功。
上面介绍了使用Lily HBase Indexer做近实时处理的流程,但是有些情况下我们可能HBase之前采用的别的二级索引机制,现在要迁移到Lily HBase Indexer上,或者由于人为的误操作导致配置schema.xml文件的时候少写入了一个索引字段,而这个时候HBase已经写入数据了,这种情况下该如何处理呢?那就需要用到Lily HBase Indexer的批处理索引功能了。使用步骤同Lily HBase NRT Indexer使用流程前4步。
Lily HBase Indexer提供了通过MapReduce来批量构建索引的方式,使用如下命令:
hadoop jar $HOME/tools/hbase-indexer-mr-1.5-cdh5.3.2-job.jar -D 'mapred.child.java.opts=-Xmx500M' --hbase-indexer-file $HOME/morphline-hbase-mapper.xml --zk-host xhadoop1:2181,xhadoop2:2181,xhadoop3:2181,xhadoop4:2181,xhadoop5:2181/solr --collection batchrecord --go-live
运行以上命令需要值得说明的是:1.如果在批处理索引文件之前已经有索引数据写入到solr中,那么运行批处理文件之后,Solr索引数据会正常写入,但是当查询solr指定的rows小于整体索引的数据条目时,其返回的numFound值不准确,但是数据结果是正常的,如果想要numFound返回的值正常,可以采用先清空Solr索引,然后再执行批处理的方式。2.在批处理索引的过程中,我尝试同时向HBase中写入数据用来近实时索引,发现数据能写入HBase正常,但是索引数据没有的情况,并且容易导致Key-Value HBase Indexer的服务异常停止,我怀疑是否和服务器性能有关,后面还需要测试,如果有人测试验证可行的话,还望告知一下。
以上即为Lily HBase Indexer的使用整理情况。