使用solr构建hbase二级索引

使用solr构建hbase二级索引

@(HBASE)[hbase, solr]

一、概述

正常情况下,hbase适合用于根据rowkey取得一个value的应用场景,但如果是反过来的需求,如根据value值搜索有哪些rowkey满足这个条件,类似于RDBMS的操作,则不是hbase擅长的领域,因为这会导致全表扫描。

(一)业务场景描述

有一些数据记录了用户的一些行为,比如是否玩过某款游戏,是否买过某本书,是否看过某个视频等。现在需要查询以下内容:
(1)根据用户+标签作为查询条件,查询用户是否存在这个标签。这个标签可能是一个视频名称。
(2)根据用户查询该用户的所有标签。
(3)根据标签条件,搜索符合某些标签条件的用户。
前2个应用场景需要实时快速查询,最后一个场景可以离线查询。
这是最典型的应用。其中前2个场景一般用于向用户推荐商品,而第3个场景是搜索符合某些条件的用户,然后进行广告投放。

即:
(1)为用户推荐时根据用户id获取用户的信息,然后进行推荐,由于已经确认rowkey,此时进行hbase get操作是非常高效的。
(2)进行广告投放时,先根据某些条件搜索hbase中的value值,得出符合条件的rowkey,然后进行投放。如果不是所有信息索引的话,还需要根据rowkey回hbase取出完整的用户信息。
image

(二)技术方案

1、技术方案一

方案描述:由于应用场景1是最常用的场景,即判断用户的某个标签是否存在。将用户信息+标签作为rowkey,这可以最快速的进行查询。对于场景2可以通过Scan#setRowPrefixFilter(用户id)来获取某个用户的所有标签。对于场景3,将通过把hbase信息索引到solr,然后搜索某些符合标签条件的所有用户。
问题:为了将hbase中的内容添加至索引,需要将标签名称也作为内容保存到qualifier的value中,这会导致信息的冗余。

2、技术方案二

方案:另一个方案是直接以用户id作为rowkey,每个标签作为一个qualifier。对于场景1和2都可以直接get就行了,对于场景3同样通过solr作索引。
问题:但用户标签可能很多,过百万、千万,有可能一行超过HFILE大小(默认10G,虽然可能性很小)。另外就是即使对于应用场景1,也需要将整行读取出来,再选取其中的部分内容,这会将大量无用信息读取到内存,很容易触发GC。还有就是这种情形下将以标签作为qualifier,这个标签的名称是无法事先确定的,而solr与hbase的结合只能以cf:qulifier与solr的一个Field作映射(当然这可以通过自己开发模块去将整个cf索引,但这需要较多的人力。不存在这个问题了,已经可以索引整个cf)
建议:如果标签类别数量较少,比如1000以内,则可以使用本方案,此时上面所述的三个问题都不存在了。而且这是一个比较典型的用户画像应用,建议通过归类、聚类等算法更好控制标签的数量。大量的推荐、广告投放等应用均是使用类似的架构。缺点是信息经过整合后会丢失细节,但这部分数据可以保存在hdfs中,以备随时重新提取有效信息。

3、关于索引的建议

(1)【强烈不建议】如果直接使用hbase来查询,不管是否加上filter,这必需要进行全表Scan,虽然可以使用离线分析,但也会导致hbase需要将全表数据加载到内存,从而频繁GC,导致集群负载过高。
(2)【可测试,无需引入solr,但性能待定】另一方式是为hbase表建倒排索引,重新索引回hbase中,以标签作rowkey,以用户id作值。此表可专用于应用场景3。
(3)【可测试,自由度高,最灵活,但工作量较大】使用coprocessor将数据索引至solr。
(4)【可测试】使用solr-index等开源工具将数据索引至solr。
CDH有一个hbase-solr的模块,它是基于开源项目hbase-indexer的。问题是hbase-indexer基于0.94与0.98的,不清楚cdh是否有改进,没文档说明。但一般而言,它与CDH5.6同时发布,应该是不存在兼容性问题的。

二、使用hbase-indexer构建hbase二级索引

以下介绍如何使用hbase-indexer将hbase中的数据同步索引至solr中。
其基本原理是根据hbase的log来将操作重写在solr中执行一次。

(一) 安装环境准备

本文在现有的集群环境上进行部署,jdk版本选用1.7,其中hbase集群使用的版本为hbase-1.0.0-cdh5.6.0

solr与hbase整合需要的软件如下:

  • 1、solr-4.10.3-cdh5.6.0
  • 2、hbase-solr-1.5-cdh5.6.0

(二) 配置solr

将solr解压,cd到exampe目录下,使用solrCloud模式在每台节点上执行:

java -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DzkHost={zk_host}/solr -jar start.jar

即可启动solr,上面命令会将solr中的配置文件上传到zk中,供集群其他节点读取使用。
其中,conf目录下有collection1的配置文件,主要有两个可能需要修改的文件:

① schema.xml文件
② solrconfig.xml文件

其中,在schema.xml文件中,可以定义一些自己的field, fieldType,分词器,copyField
solrconfig.xml文件中对应对索引进行一些通用设置,比如设置软、硬提交

启动之后,可以访问http://{your_host}:8983/solr/,进入solr查询页面。

(三) 配置hbase-solr

解压habse-solr之后,需要做一些配置,才能使用,否则启动出错。

(1)修改conf/hbase-indexer-site.xml文件,添加内容如下:

<property>
  <name>hbaseindexer.zookeeper.connectstring</name>
  <value>zookeeperhost</value>
</property>
<property>
  <name>hbase.zookeeper.quorum</name>
  <value>zookeeperhost</value>
</property>

(2)配置hbase,开启habse的replication功能,在hbase的hbase-site.xml文件中,修改内容如下:

<!-- added by hwyn3816 on 2016/07/04 -->
  <property>
    <name>hbase.replication</name>
    <value>true</value>
    <description>SEP is basically replication, so enable it</description>
  </property>

  <property>
    <name>replication.source.ratio</name>
    <value>1.0</value>
    <description>Source ratio of 100% makes sure that each SEP consumer is actually used (otherwise, some can sit idle, especially with small clusters)</description>
  </property>

  <property>
    <name>replication.source.nb.capacity</name>
    <value>1000</value>
    <description>Maximum number of hlog entries to replicate in one go. If this is large, and a consumer takes a while to process the events, the HBase rpc call will time out.</description>
  </property>

  <property>
    <name>replication.replicationsource.implementation</name>
    <value>com.ngdata.sep.impl.SepReplicationSource</value>
    <description>A custom replication source that fixes a few things and adds some functionality (doesn't interfere with normal replication usage).</description>
  </property>

(3)复制一些额外的jar到habse中的lib目录下,

cp lib/hbase-sep-* $HBASE_HOME/lib

(4)重启hbase集群,使得配置生效,执行:

cd ${HBASE_HOME}
bin/rolling-restart.sh 

(5)启动habse-index服务

bin/hbase-indexer server

(四)测试

1、hbase中创建测试表

$ hbase shell
hbase> create 'indexdemo-user', { NAME => 'info', REPLICATION_SCOPE => '1' }

# 在表中添加一些数据
hbase> put 'indexdemo-user', 'row1', 'info:firstname', 'John'
hbase> put 'indexdemo-user', 'row1', 'info:lastname', 'Smith'

2、添加配置文件,用于将solr中的field映射为hbase中的qualifier

<?xml version="1.0"?>
<indexer table="indexdemo-user">
  <field name="firstname_s" value="info:firstname"/>
  <field name="lastname_s" value="info:lastname"/>
  <field name="age_i" value="info:age" type="int"/>
</indexer>

注意,上面两个字段名,还需要在solr的schema.xml文件事先定义,才能使用。

3、添加索引

定义好上面文件后,在solr-hbase中创建indexer,执行:

./bin/hbase-indexer add-indexer -n myindexer -c indexdemo-indexer.xml \
        -cp solr.zk={zk_host}/solr -cp solr.collection=collection1 -z {zk_host}

4、搜索

执行完成后,如果没有出错,就可以去solr查询页面中,查询到已经对habse定义的字段数据进行了索引:

{
  "responseHeader": {
    "status": 0,
    "QTime": 1,
    "params": {
      "indent": "true",
      "q": "*:*",
      "_": "1467685845733",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 3,
    "start": 0,
    "docs": [
      {
        "firstname_s": "hwyn3816",
        "lastname_s": "huanghe",
        "id": "row1",
        "_version_": 1538978729496150000
      },
      {
        "firstname_s": "John",
        "lastname_s": "Smith",
        "id": "row2",
        "_version_": 1538978814854430700
      },
      {
        "firstname_s": "John",
        "lastname_s": "Smith",
        "id": "row3",
        "_version_": 1538979512969068500
      }
    ]
  }
}

(五)使用solrJ搜素

三、使用coprocessor构建hbase二级索引

见另一篇文章

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值