在“快速入门”小节中,可以体验了创建索引、使用索引的大体流程。本文针对建立索引进行详细说明,描述索引的工作基本原理以及配置映射关系,帮助进一步熟悉全文索引服务的使用。

使用前须知

全文索引功能目前已经全面升级,使用老架构的标准版全文索引服务即将下线,新用户请参见全文索引服务

建立索引详细说明

基本原理描述

如上图所示,demoindex 索引描述了HBase 的 solrdemo 表和 Solr 的 democollection 各个索引列字段映射关系。命令行中 -c democollection 指定了这个 demoindex 关联的 Solr Collection 为 democollection; -f demo.xml 描述了 demoindex 使用的配置文件是 demo.xml 文件;在 demo.xml 文件中,table="solrdemo" 表示此映射关联了 HBase 的 solrdemo 表;demo.xml 文件中,每一行 field 就描述了 HBase 的一个 column 映射到 Solr 的一个 field 字段。例如图中的 field标签,表示 HBase 中 info:name 这个列映射到 Solr 的 name_s,其中 type="string" 表示 HBase的这个 info:name 存储的 byte[] 是 Bytes.toBytes(String) 得到的数据。类似的,type 还有 int、long、double、float、short、boolean,分别对应 HBase 存储的数据是 Bytes.toBytes(int)、Bytes.toBytes(long)、Bytes.toBytes(double)、Bytes.toBytes(float)、Bytes.toBytes(short)、Bytes.toBytes(boolean) 得到的 byte[] 数据。

对于 Solr 来说,存储的类型就是 field 字段在 schema 中描述的类型,这两个类型要对应。比如这里 name_s 其实暗含着这个 name_s 在 Solr 里面是 string 类型。后缀方式暗示类型的预定义都已经在 schema 中默认加上了,如果你需要有不带后缀 _s、_i、_l、_b、_f等的字段名,那么你需要显式在 Solr 的 schema 中配置指定其对应类型。其他 solr 更多动态类型映射,请参考 默认schema中的动态类型

客户端使用详情

由上述小节可以看到,整个链路里面涉及到:HBase Shell 命令建表、solr-indexer 命令管理索引、Solr 命令操作创建 collection,3 个部分的DDL操作。首先我们看对于 HBase Shell 的建表操作,我们需要做什么,如下:

HBase Shell 命令行建表

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

唯一需要修改的地方,就是设置涉及到同步列所在的列簇 infoREPLICATION_SCOPE1,这里不多赘述。

solr-indexer 命令管理索引

Solr 客户端工具包准备

首先需要下载解压客户端:

wget http://public-hbase.oss-cn-hangzhou.aliyuncs.com/installpackage/solr-7.3.1-ali-1.1.tgz
tar zxvf solr-7.3.1-ali-1.1.tgz

修改 solr-7.3.1-ali-1.1/bin/solr.in.sh 文件,去掉 ZK_HOST 前面注释 #,并修改如下:

ZK_HOST="hb-xxxxxx-master2-001.hbase.rds.aliyuncs.com:2181,hb-xxxxxx-master3-001.hbase.rds.aliyuncs.com:2181,hb-xxxxxx-master1-001.hbase.rds.aliyuncs.com:2181/solr"

此地址见solr开通页面的客户端访问地址,如下:

注:上述配置流程中的 ZK 地址是内网地址,如果是想通过公网访问,请填写 ${公网 ZK 地址}/solr 即可。公网 ZK 地址获取,请参考 公网访问方案

Solr 命令上传自定义配置并创建 Collection

如“快速入门” 章节我们创建一个 Solr 的 Collection 时,其实使用的是 Solr WebUI 进行创建的,并且使用的 _indexer_default 的这个 Collection 配置。这个 _indexer_default 配置目录中,其核心包含了 managed-schemasolrconfig.xml 核心的两个配置文件,分别描述了 Collection 的每个字段是什么类型,以及 Collection 的一些系统动作,如cache、autoCommit 等。

下面我们来简单认识下两个配置文件,并通过一个例子,来创建一个具有定制配置的 Collection。为了方便,我们已经把样例的配置放置在了 solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig 目录下,如下:

solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig/conf/managed-schema
solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig/conf/solrconfig.xml
solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig/conf/lang
solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig/conf/stopwords.txt
solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig/conf/... ...

这里我们只需关心 managed-schemasolrconfig.xml 两个配置即可。打开 managed-schemasolrconfig.xml 配置文件,上面有基本的配置项说明描述,详细参考 schema配置相关说明 以及 solrconfig.xml配置说明

接下来我们创建一个 Collection 命名为 democollection2,并声明 name 字段为 string 类型、age为 int 类型,如下:

cp -r solr-7.3.1-ali-1.1/server/solr/configsets/_democonfig solr-7.3.1-ali-1.1/server/solr/configsets/_democollection2
vim solr-7.3.1-ali-1.1/server/solr/configsets/_democollection2/conf/managed-schema

managed-schema 中大概 127 行附近空白处,添加如下行:

<field name="name" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="age" type="pint" indexed="true" stored="true" docValues="true"  multiValued="false" />

注意,managed-schema 里面预定义的 int 类型是用 pint 代表,其他类型也是,可以参见配置文件描述。

这里 name 字段是必需的,在使用此配置时,必需确保 HBase 的一行数据内必需包含 name 对应的列,否则会导致同步失败并阻塞。

接下来我们把刚刚修改的 _democollection 定制配置目录上传到 Solr 集群,执行命令如下:

solr-7.3.1-ali-1.1/bin/solr zk upconfig -d _democollection2 -n democollection2_config

-d _democollection2 指的是刚刚修改的目录名字,注意这个目录默认必须在 solr-7.3.1-ali-1.1/server/solr/configsets/ 下。-n democollection2_config 指的是我们把这个 -d 指定的目录上传到 Solr 上面时,重命名为 democollection2_config,当然你可以写不一样的名字,只要命名合法。

接下来,就是在 Solr WebUI 里面创建 Collection 时,选中对应的 democollection2_config 即可,这样就完成了一个定制 schema 配置的 Collection 创建。如图:

solr-indexer 创建索引

上述创建了HBase 表、自定义的 Collection 之后,接下来就是利用 solr-indexer 命令工具,创建索引把 solrdemo 和这个定制的 schema 配置的 democollection2 关联起来。

首先运行 solr-indexer 把“快速入门”中的 demoindex 删除掉,解除 solrdemo 表和 democollection 的映射关系,然后这里创建一个 demoindex2 索引,让 solrdemo 表和 democollection2 索引关联映射起来。如下:

solr-7.3.1-ali-1.1/bin/solr-indexer delete -n demoindex

此时“快速入门”中创建的 demoindex 已经被我们删除了。接下来就是创建demoindex2 了。

首先编辑准备 demoindexer2.xml 配置,描述 HBase 表 solrdemodemocollection2 的字段映射关系。demoindexer2.xml 配置如下:

<?xml version="1.0"?>
<indexer table="solrdemo">
  <field name="name" value="info:name" type="string"/>
  <field name="age" value="info:age" type="int"/>
  <param name="update_version_l" value="true"/>
</indexer>

然后执行命令如下:

solr-7.3.1-ali-1.1/bin/solr-indexer add -n demoindex2 -f demoindexer2.xml -c democollection2

执行成功之后,可以运行 list 查看是否创建成功。

solr-7.3.1-ali-1.1/bin/solr-indexer list

到这里,我们就完成创建自定义 Collection 配置的索引创建了。

solr-indexer 更新索引

上述我们已经创建好了 Indexer,Indexer 已正常运行。此时若我们需要更新 Indexer,可以使用 solr-indexer 命令来完成。

若我们想增加一个索引列 info:desc,首先修改配置文件 demoindexer2.xml 如下:

<?xml version="1.0"?>
<indexer table="solrdemo">
  <field name="name" value="info:name" type="string"/>
  <field name="age" value="info:age" type="int"/>
  <field name="desc_s" value="info:desc" type="string"/>
  <param name="update_version_l" value="true"/>
</indexer>

运行更新命令如下:

solr-7.3.1-ali-1.1/bin/solr-indexer update -n demoindex2 -f demoindexer2.xml -c democollection2

之后我们查看一下更新是否生效:

solr-7.3.1-ali-1.1/bin/solr-indexer list -dump -t solrdemo

输出如下,可以看到 desc_s 已加入:

demoindex2
......
  + Connection params:
    + solr.zk = ......
    + solr.collection = democollection2
  + Indexer config:
      <?xml version="1.0"?>
      <indexer table="solrdemo">
        <field name="name" value="info:name" type="string"/>
        <field name="age" value="info:age" type="int"/>
        <field name="desc_s" value="info:desc" type="string"/>
        <param name="update_version_l" value="true"/>
      </indexer>
  + Processes
......

Solr 从 HBase 同步数据有一定的提交延迟(默认15s左右),若需要修改此提交延迟,命令如下:

solr-7.3.1-ali-1.1/bin/solr-indexer update -n demoindex2 -f demoindexer2.xml -c democollection2 -w 3000

查看更新是否生效:

solr-7.3.1-ali-1.1/bin/solr-indexer list -dump -t solrdemo

输出如下,可以看到在 Connection params 中已加入了 solr.commitWithin

demoindex2
......
  + Connection params:
    + solr.zk = ......
    + solr.collection = democollection2
    + solr.commitWithin = 3000
  + Indexer config:
      <?xml version="1.0"?>
      <indexer table="solrdemo">
        <field name="name" value="info:name" type="string"/>
        <field name="age" value="info:age" type="int"/>
        <field name="desc_s" value="info:desc" type="string"/>
        <param name="update_version_l" value="true"/>
      </indexer>
  + Processes
......

注意:在更新 indexer 时,配置文件是必须的,若不想修改原来的 indexer 配置,则需要保持 -f 的配置文件内容与之前的配置一致。简而言之,更新 indexer 时,总是用 -f 指定的配置覆盖原有的配置。

solr-indexer 重建索引

由于 Indexer 只能够对启动后的增量数据进行索引,在实际的使用中,若想对存量数据进行索引,需要用到 solr-indexer 的索引重建功能。solr-indexer 关于索引重建的命令有 3 个:rebuild 启动索引重建任务,rebuild-status 查看索引重建任务状态、rebuild-cancel 取消索引重建任务。

在索引重建前,可以在之前的 HBase 表 solrdemo 中插入一些测试数据,并做预分区,以便更好的观察命令效果。

rebuild 命令 help 如下:

rebuild [-z zkConn] <-n indexName> <-t table> <-r maxRetries>
      -z zkConn        zookeeper connection string, such as local:2181/solr
                             if not specified, use ZK_HOST in solr.in.sh env instead
      -n indexName    the rebuild index name
      -t tableName     the rebuild table name
      -r maxReties      the max number of task retries

其中 -z-n-t 参数意义容易理解,注意 -t 指定的表名需要与 -n 指定的 Indexer 配置文件中的表一致-r 指定了本次索引重建任务的失败尝试最大次数,一般情况下设置 10 即可。

执行 rebuild 命令,提交索引重建任务:

solr-7.3.1-ali-1.1/bin/solr-indexer rebuild -n demoindex2 -t solrdemo -r 10

我们还可以通过 rebuild-status 查看索引重建任务状态:

solr-7.3.1-ali-1.1/bin/solr-indexer rebuild-status -n demoindex2 -t solrdemo

输出信息类似如下:

Job Status information of job_solrdemo_demoindex2:

    jobStatus=SUCCEEDED
    jobStartTime=2019-07-xx xx:xx:xx xxx
    jobEndTime=2019-07-xx xx:xx:xx xxx
    completedRows=100000
    tableName=solrdemo
    indexName=demoindex2
    totalTasks=3
    completedTasks=3
    runningTasks=0
    pendingTasks=0

通过 rebuild-cancel 取消索引重建任务:

solr-7.3.1-ali-1.1/bin/solr-indexer rebuild-cancel -n demoindex2 -t solrdemo

再次通过 rebuild-status 查看索引重建任务状态,可以看到 jobStatus=CANCELLED

Job Status information of job_solrdemo_demoindex2:

    jobStatus=CANCELLED
    jobStartTime=2019-07-xx xx:xx:xx xxx
    jobEndTime=2019-07-xx xx:xx:xx xxx
    completedRows=30000
    tableName=solrdemo
    indexName=demoindex2
    totalTasks=3
    completedTasks=3
    runningTasks=0
    pendingTasks=0

如果 rebuild-cancel 命令报错,说明本次索引重建任务已完成或已取消,可以重新执行 rebuild 命令,在任务执行过程中运行 rebuild-cancel

注意:solr-indexer 命令的详细用法请参阅命令 help。请务必仔细阅读 help,并确认命令效果后再执行。

附一:索引映射文件 type 支持的类型

索引映射文件type支持的类型: int/short/long/string/boolean/float/double例如 new_index.xml

<?xml version="1.0"?>
<indexer table="newtest">
  <field name="name" value="info:name" type="string"/>
  <field name="age" value="info:age" type="int"/>
  <field name="man" value="info:man" type="boolean"/>
  <field name="height" value="info:height" type="double"/>
  ... ...
  <param name="update_version_l" value="true"/>
</indexer>

注意,这里描述的 type 指的是在 HBase 中,某个列 value 是以什么样的格式保存的 byte[] 值。比如 info:agetype="int",表示在 HBase 当中,info:age 这个列的值是通过 Bytes.toBytes(int) 得到的 4 个字节 byte[]。如果你写入的是其他类型的 byte[],那么将会解析失败。这里建议用户写入 HBase 的时候,做好类型格式清洗,不要插入错误格式的数据,否则会导致同步失败。

附二:Collection 支持的字段类型

managed-schema 文件,分别支持 string/pint/plong/boolean/pdouble/pfloat 等,其他更多动态类型映射,请参考 默认schema中的动态类型

附三:update_version_l 的作用

update_version_l 为固定写法,表示 Document 的最后更新时间,始终设置为 true

附四:HBase 的 RowKey 映射与 Solr 中 Document 的ID字段

默认情况下,HBase 的 RowKey 是通过 Bytes.toString(byte[]) 得到的 string 值作为 Solr Document 的ID字段值进行保存。现支持两种格式映射关系,如下:

  • string: 默认 HBase的 RowKey 以 Bytes.toString(byte[] rowkey) 转换为 Document id;
  • hex: 提供 commons-codec 包的 Hex.encodeHexString(byte[] rowkey) 转换为 Hex 方式的 Document id。对应反解析即可。

指定方式如下:new_index.xml,指定 unique-key-formatterhex 或者 string,默认是string。指定使用 unique-key-formatter=“hex” 如下:

<indexer table="solrdemo" unique-key-formatter="hex">
  <field name="age" value="info:age" type="int"/>
  ... ...
</indexer>

指定使用 unique-key-formatter=“string” 如下:

<indexer table="solrdemo" unique-key-formatter="string">
  <field name="age" value="info:age" type="int"/>
  ... ...
</indexer>

默认 unique-key-formatter 就是 string,如下:

<indexer table="solrdemo">
  <field name="age" value="info:age" type="int"/>
  ... ...
</indexer>