跳到内容

Apache Solr

Solr 具有高度可靠性、可扩展性和容错性,提供分布式索引、复制和负载均衡查询、自动化故障转移和恢复、集中式配置等功能。Solr 为世界上许多大型互联网网站的搜索和导航功能提供支持。

Apache Solr 主页

JanusGraph 支持 Apache Solr 作为索引后端。以下是 JanusGraph 支持的一些 Solr 功能

  • 全文:支持所有 Text 谓词,用于搜索匹配给定单词、前缀或正则表达式的文本属性。
  • 地理:支持所有 Geo 谓词,用于搜索与给定查询几何体相交、在其中、不相交或包含在其中的地理属性。支持点、线和多边形进行索引。支持圆形、框和多边形进行点属性查询,支持所有形状进行非点属性查询。
  • 数字范围:支持 Compare 中的所有数字比较。
  • TTL:支持自动过期索引元素。
  • 时间:毫秒级粒度时间索引。
  • 自定义分析器:选择使用自定义分析器

有关哪些 Solr 版本可与 JanusGraph 配合使用的详细信息,请参阅版本兼容性

Solr 配置概述

JanusGraph 支持 Solr 在 SolrCloud 或 Solr 单机版 (HTTP) 配置中运行,用于混合索引(请参阅混合索引)。所需的连接模式通过参数 mode 进行配置,该参数必须设置为 cloudhttp,前者是默认值。例如,要明确指定 Solr 在 SolrCloud 配置中运行,需要将以下属性指定为 JanusGraph 配置属性

index.search.solr.mode=cloud

以下是一些关键的 Solr 术语

  • Core:单机上的单个索引
  • 配置:定义核心所需的 solrconfig.xmlschema.xml 和其他文件。
  • 集合 (Collection):一个单一的逻辑索引,可以跨不同机器上的多个 core。
  • 配置集 (Configset):可以由多个 core 重复使用的共享配置

连接到 SolrCloud

当通过将 mode 设置为 cloud 连接到 SolrCloud 集群时,必须指定 Zookeeper URL(和可选端口),以便 JanusGraph 可以发现 Solr 集群并与之交互。

index.search.backend=solr
index.search.solr.mode=cloud
index.search.solr.zookeeper-url=localhost:2181

可以配置许多与创建新集合(仅在 SolrCloud 操作模式下支持)相关的附加配置选项,以控制分片行为等。有关这些选项的完整列表,请参阅配置参考

SolrCloud 利用 Zookeeper 在 Solr 服务器之间协调集合和配置集信息。将 Zookeeper 与 SolrCloud 结合使用,可以显著减少将 Solr 用作 JanusGraph 后端索引所需的 manual 配置量。

配置集 (Configset) 配置

创建集合需要配置集。配置集存储在 Zookeeper 中,以便 Solr 服务器可以访问它。

  • 每个集合在创建时都可以提供自己的配置集,因此每个集合可以具有不同的配置。使用这种方法,每个集合必须手动创建。

  • 如果共享配置集将由多个集合重复使用,则可以将其单独上传到 Zookeeper。使用这种方法,JanusGraph 可以通过使用共享配置集自动创建集合。另一个好处是,重复使用配置集可以显著减少存储在 Zookeeper 中的数据量。

使用单独的配置集

在此示例中,使用分发中提供的 Solr 默认 JanusGraph 配置手动创建了一个名为 verticesByAge 的集合。创建集合时,配置将上传到 Zookeeper,并使用相同的集合名称 verticesByAge 作为配置集名称。有关可用参数,请参阅Solr 参考指南

# create the collection
$SOLR_HOME/bin/solr create -c verticesByAge -d $JANUSGRAPH_HOME/conf/solr

使用 JanusGraphManagement 和相同的集合名称定义混合索引。

mgmt = graph.openManagement()
age = mgmt.makePropertyKey("age").dataType(Integer.class).make()
mgmt.buildIndex("verticesByAge", Vertex.class).addKey(age).buildMixedIndex("search")
mgmt.commit()

使用共享配置集

当使用共享配置集时,最方便的方法是首先将配置作为一次性操作上传。在此示例中,使用分发中提供的 Solr 默认 JanusGraph 配置,将名为 janusgraph-configset 的配置集上传到 Zookeeper。有关可用参数,请参阅Solr 参考指南

# upload the shared configset into Zookeeper
# Solr 5
$SOLR_HOME/server/scripts/cloud-scripts/zkcli.sh -cmd upconfig -z localhost:2181 \
    -d $JANUSGRAPH_HOME/conf/solr -n janusgraph-configset
# Solr 6 and higher
$SOLR_HOME/bin/solr zk upconfig -d $JANUSGRAPH_HOME/conf/solr -n janusgraph-configset \
    -z localhost:2181

为 JanusGraph 配置 SolrCloud 索引后端时,请务必使用 index.search.solr.configset 属性提供共享配置集的名称。

index.search.backend=solr
index.search.solr.mode=cloud
index.search.solr.zookeeper-url=localhost:2181
index.search.solr.configset=janusgraph-configset

使用 JanusGraphManagement 和集合名称定义混合索引。

mgmt = graph.openManagement()
age = mgmt.makePropertyKey("age").dataType(Integer.class).make()
mgmt.buildIndex("verticesByAge", Vertex.class).addKey(age).buildMixedIndex("search")
mgmt.commit()

连接到 Solr 单机版 (HTTP)

当通过将 mode 设置为 http 连接到 Solr 单机版时,必须提供 Solr 实例的单个或列表 URL。

index.search.backend=solr
index.search.solr.mode=http
index.search.solr.http-urls=https://:8983/solr

HTTP 模式下还提供了控制最大连接数、连接超时和传输压缩的附加配置选项。有关这些选项的完整列表,请参阅配置参考

Core 配置

Solr 单机版用于单个实例,它将配置信息保存在文件系统上。每个混合索引都必须手动创建一个 core。

要创建 core,需要 core_nameconfiguration 目录。有关可用参数,请参阅Solr 参考指南。在此示例中,使用分发中提供的 Solr 默认 JanusGraph 配置创建了一个名为 verticesByAge 的 core。

$SOLR_HOME/bin/solr create -c verticesByAge -d $JANUSGRAPH_HOME/conf/solr

使用 JanusGraphManagement 和相同的 core 名称定义混合索引。

mgmt = graph.openManagement()
age = mgmt.makePropertyKey("age").dataType(Integer.class).make()
mgmt.buildIndex("verticesByAge", Vertex.class).addKey(age).buildMixedIndex("search")
mgmt.commit()

Kerberos 配置

当连接到受 Kerberos 保护的 Solr 环境时,我们必须指定正在使用 Kerberos 并引用 JAAS 配置文件以正确配置 Solr 客户端。无论 Solr 以何种模式运行(SolrCloud 或 Solr 单机版),当使用 Kerberos 时都需要此配置。

index.search.solr.kerberos-enabled=true

JAAS 配置文件通过确保您设置 Java 系统属性 java.security.auth.login.config 并使用文件的绝对路径来提供。此属性应使用 JVM 选项设置。例如,要运行 gremlin.sh,您需要在运行脚本之前设置 JAVA_OPTIONS 环境变量

export JAVA_OPTIONS="-Djava.security.auth.login.config=/absolute/path/jaas.conf"
$JANUSGRAPH_HOME/bin/gremlin.sh

有关 JAAS 配置文件中所需内容的详细信息,请参阅 https://lucene.apache.org/solr/guide/7_0/kerberos-authentication-plugin.html#define-a-jaas-configuration-file[Solr 参考指南]。

Solr 模式设计

动态字段定义

默认情况下,JanusGraph 使用 Solr 的动态字段功能为所有索引键定义字段类型。这在向 Solr 支持的混合索引添加属性键时无需额外配置,并且比无模式模式提供更好的性能。

JanusGraph 假设在后端 Solr 集合的 schema.xml 文件中定义了以下动态字段标签。请注意,为了使用它们,solr schema.xml 文件中还需要对以下字段进行额外的 xml 定义。有关更多信息,请参阅 JanusGraph 安装中 ./conf/solr/schema.xml 目录中提供的示例 schema.xml 文件。

<dynamicField name="*_i"    type="int"          indexed="true"  stored="true"/>
<dynamicField name="*_s"    type="string"       indexed="true"  stored="true" />
<dynamicField name="*_l"    type="long"         indexed="true"  stored="true"/>
<dynamicField name="*_t"    type="text_general" indexed="true"  stored="true"/>
<dynamicField name="*_b"    type="boolean"      indexed="true" stored="true"/>
<dynamicField name="*_f"    type="float"        indexed="true"  stored="true"/>
<dynamicField name="*_d"    type="double"       indexed="true"  stored="true"/>
<dynamicField name="*_g"    type="geo"          indexed="true"  stored="true"/>
<dynamicField name="*_dt"   type="date"         indexed="true"  stored="true"/>
<dynamicField name="*_uuid" type="uuid"         indexed="true"  stored="true"/>

在 JanusGraph 的默认配置中,属性键名称不必以类型适当的后缀结尾即可利用 Solr 的动态字段功能。JanusGraph 通过编码属性键定义的数字标识符和类型适当的后缀,从属性键名称生成 Solr 字段名称。这意味着 JanusGraph 在后台使用带有类型适当后缀的合成字段名称,而不管使用 JanusGraph 的应用程序代码定义和使用的属性键名称如何。此字段名称映射可以通过非默认配置进行覆盖。这将在下一节中描述。

手动字段定义

如果用户更愿意手动定义集合中每个索引字段的字段类型,则需要禁用配置选项 dyn-fields。在将属性键添加到索引之前,为每个索引属性键定义的字段必须在后端 Solr 模式中定义,这一点很重要。

在这种情况下,建议启用显式属性键名称到字段的映射,以修复其显式定义的字段名称。这可以通过两种方式实现

  1. 通过在将属性键添加到索引时提供 mapped-name 参数来配置字段名称。有关更多信息,请参阅单独字段映射
  2. 通过为 Solr 索引启用 map-name 配置选项,该选项将使用属性键名称作为 Solr 中的字段名称。有关更多信息,请参阅全局字段映射

无模式模式

JanusGraph 还可以与配置为无模式模式的 SolrCloud 集群交互。在这种情况下,应禁用配置选项 dyn-fields,因为 Solr 将从值而不是字段名称推断字段类型。

但是请注意,无模式模式仅建议用于原型设计和初始应用程序开发,不建议用于生产环境。

故障排除

集合不存在

集合(以及所有必需的配置文件)必须在定义的索引使用该集合之前进行初始化。有关更多信息,请参阅连接到 SolrCloud

使用 SolrCloud 时,可以使用 Zookeeper zkCli.sh 命令行工具检查加载到 Zookeeper 中的配置。还要验证默认的 JanusGraph 配置文件是否已复制到 solr 下的正确位置,以及文件复制的目录是否正确。

找不到指定的配置集

使用 SolrCloud 时,需要一个配置集来为 JanusGraph 创建混合索引。有关更多信息,请参阅配置集配置

  • 如果使用单独的配置集,则必须首先手动创建集合。
  • 如果使用共享配置集,则必须首先将配置集上传到 Zookeeper。

您可以验证配置集及其配置文件是否在 Zookeeper 的 /configs 下。有关其他 Zookeeper 操作,请参阅Solr 参考指南

# verify the configset in Zookeeper
# Solr 5
$SOLR_HOME/server/scripts/cloud-scripts/zkcli.sh -cmd list -z localhost:2181
# Solr 6 and higher
$SOLR_HOME/bin/solr zk ls -r /configs/configset-name -z localhost:2181

HTTP 错误 404

在使用 Solr 单机版 (HTTP) 模式时可能会遇到此错误。错误示例

20:01:22 ERROR org.janusgraph.diskstorage.solr.SolrIndex  - Unable to save documents
to Solr as one of the shape objects stored were not compatible with Solr.
org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException: Error from server
at https://:8983/solr: Expected mime type application/octet-stream but got text/html.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 404 Not Found</title>
</head>
<body><h2>HTTP ERROR 404</h2>
<p>Problem accessing /solr/verticesByAge/update. Reason:
<pre>    Not Found</pre></p>
</body>
</html>

在尝试将数据存储到索引中之前,请务必手动创建 core。有关更多信息,请参阅Core 配置

无效的 core 或集合名称

core 或集合名称是一个标识符。它必须完全由句点、下划线、连字符和/或字母数字组成,并且不能以连字符开头。

连接问题

无论操作模式如何,Solr 实例或 Solr 实例集群都必须正在运行并可从 JanusGraph 实例访问,以便 JanusGraph 将 Solr 用作索引后端。检查 Solr 集群是否正常运行,以及它是否可以通过网络(或本地)从 JanusGraph 实例可见和可访问。

Geo 数据出现 JTS ClassNotFoundException

Solr 依赖 Spatial4j 进行地理处理。Spatial4j 声明对 JTS(“JTS Topology Suite”)的可选依赖。JTS 是某些地理字段定义和查询功能所必需的。如果 JTS jar 不在 Solr 守护进程的类路径中,并且 schema.xml 中的字段使用地理类型,则 Solr 可能会对某个缺失的 JTS 类抛出 ClassNotFoundException。此异常可能在 Solr 使用旨在与 JanusGraph 配合使用的 schema.xml 文件启动时出现,也可能在Solr CoreAdmin API 中调用 CREATE 时出现。该异常在客户端和服务器端以略微不同的格式出现,尽管根本原因相同。

以下是 Solr 服务器日志中的一个代表性示例

ERROR [http-8983-exec-5] 2014-10-07 02:54:06, 665 SolrCoreResourceManager.java (line 344) com/vividsolutions/jts/geom/Geometry
java.lang.NoClassDefFoundError: com/vividsolutions/jts/geom/Geometry
    at com.spatial4j.core.context.jts.JtsSpatialContextFactory.newSpatialContext(JtsSpatialContextFactory.java:30)
    at com.spatial4j.core.context.SpatialContextFactory.makeSpatialContext(SpatialContextFactory.java:83)
    at org.apache.solr.schema.AbstractSpatialFieldType.init(AbstractSpatialFieldType.java:95)
    at org.apache.solr.schema.AbstractSpatialPrefixTreeFieldType.init(AbstractSpatialPrefixTreeFieldType.java:43)
    at org.apache.solr.schema.SpatialRecursivePrefixTreeFieldType.init(SpatialRecursivePrefixTreeFieldType.java:37)
    at org.apache.solr.schema.FieldType.setArgs(FieldType.java:164)
    at org.apache.solr.schema.FieldTypePluginLoader.init(FieldTypePluginLoader.java:141)
    at org.apache.solr.schema.FieldTypePluginLoader.init(FieldTypePluginLoader.java:43)
    at org.apache.solr.util.plugin.AbstractPluginLoader.load(AbstractPluginLoader.java:190)
    at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:470)
    at com.datastax.bdp.search.solr.CassandraIndexSchema.readSchema(CassandraIndexSchema.java:72)
    at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:168)
    at com.datastax.bdp.search.solr.CassandraIndexSchema.<init>(CassandraIndexSchema.java:54)
    at com.datastax.bdp.search.solr.core.CassandraCoreContainer.create(CassandraCoreContainer.java:210)
    at com.datastax.bdp.search.solr.core.SolrCoreResourceManager.createCore(SolrCoreResourceManager.java:256)
    at com.datastax.bdp.search.solr.handler.admin.CassandraCoreAdminHandler.handleCreateAction(CassandraCoreAdminHandler.java:117)
    ...

以下是通常出现在向 CoreAdmin API 发出相关 CREATE 命令的客户端输出中的内容

org.apache.solr.common.SolrException: com/vividsolutions/jts/geom/Geometry
    at com.datastax.bdp.search.solr.core.SolrCoreResourceManager.createCore(SolrCoreResourceManager.java:345)
    at com.datastax.bdp.search.solr.handler.admin.CassandraCoreAdminHandler.handleCreateAction(CassandraCoreAdminHandler.java:117)
    at org.apache.solr.handler.admin.CoreAdminHandler.handleRequestBody(CoreAdminHandler.java:152)
    ...

这可以通过将 JTS jar 添加到 JanusGraph 和/或 Solr 服务器的类路径中来解决。由于其 LGPL 许可证,JTS 默认不包含在 JanusGraph 分发版中。用户必须单独下载 JTS jar 文件并将其复制到 JanusGraph 和/或 Solr 服务器的 lib 目录中。如果使用 Solr 内置的 Web 服务器,可以将 JTS jar 复制到 example/solr-webapp/webapp/WEB-INF/lib 目录以将其包含在类路径中。Solr 可以重新启动,异常应该会消失。Solr 必须首先使用正确的 schema.xml 文件启动一次,以便 example/solr-webapp/webapp/WEB-INF/lib 目录存在。

要确定 Solr 服务器的理想 JTS 版本,首先检查 Solr 集群使用的 Spatial4j 版本,然后确定该 Spatial4j 版本编译时所针对的 JTS 版本。Spatial4j 在 com.spatial4j:spatial4j 工件的 pom 中声明其目标 JTS 版本。将 JTS jar 复制到 Solr 安装的 server/solr-webapp/webapp/WEB-INF/lib 目录。

高级 Solr 配置

本节介绍 JanusGraph 与 DataStax Enterprise (DSE) Search 的安装和配置。安装 DSE 的方法有多种,但本节重点介绍 DSE 在 Linux 上的二进制 tarball 安装选项。本节中的大多数步骤可以推广到 DSE 的其他安装选项。

按照页面使用二进制 tarball 安装 DataStax Enterprise 的指示安装 DataStax Enterprise。

在 shell 环境中导出 DSE_HOME 并追加到 PATH。这是一个使用 Bash 语法的示例

export DSE_HOME=/path/to/dse-version.number
export PATH="$DSE_HOME"/bin:"$PATH"

为 Solr 安装 JTS。合适的版本因 Spatial4j 版本而异。截至 DSE 4.5.2,合适的版本是 1.13。

cd $DSE_HOME/resources/solr/lib
curl -O 'http://central.maven.org/maven2/com/vividsolutions/jts/1.13/jts-1.13.jar'

在单个后台守护程序中启动 DSE Cassandra 和 Solr

# The "dse-data" path below was chosen to match the
# "Installing DataStax Enterprise using the binary tarball"
# documentation page from DataStax.  The exact path is not
# significant.
dse cassandra -s -Ddse.solr.data.dir="$DSE_HOME"/dse-data/solr

上一个命令会将一些启动信息写入控制台和 $DSE_HOME/resources/cassandra/conf/log4j2-server.xml 中配置的日志文件路径 log4j.appender.R.File

一旦 DSE 与 Cassandra 和 Solr 正常启动,使用 nodetool status 检查集群健康状况。单实例环应显示一个带有 *U*p 和 *N*ormal 标志的节点

nodetool status
Note: Ownership information does not include topology; for complete information, specify a keyspace
= Datacenter: Solr
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address    Load       Owns   Host ID                               Token                                    Rack
UN  127.0.0.1  99.89 KB   100.0%  5484ef7b-ebce-4560-80f0-cbdcd9e9f496  -7317038863489909889                     rack1

接下来,切换到 Gremlin Console 并针对 DSE 实例打开 JanusGraph 数据库。这将创建 JanusGraph 的键空间和列族。

cd $JANUSGRAPH_HOME
bin/gremlin.sh

         \,,,/
         (o o)
-----oOOo-(3)-oOOo-----
gremlin> graph = JanusGraphFactory.open('conf/janusgraph-cql-solr.properties')
==>janusgraph[cql:[127.0.0.1]]
gremlin> g = graph.traversal()
==>graphtraversalsource[janusgraph[cql:[127.0.0.1]], standard]
gremlin>

保持 Gremlin Console 打开。我们现在休息一下,安装一个 Solr core。然后我们回到这个控制台加载一些示例数据。

接下来,上传 JanusGraph Solr 集合的配置文件,然后在 DSE 中创建 core

# Change to the directory where JanusGraph was extracted.  Later commands
# use relative paths to the Solr config files shipped with the JanusGraph
# distribution.
cd $JANUSGRAPH_HOME

# The name must be URL safe and should contain one dot/full-stop
# character. The part of the name after the dot must not conflict with
# any of JanusGraph's internal CF names.  Starting the part after the dot
# "solr" will avoid a conflict with JanusGraph's internal CF names.
CORE_NAME=janusgraph.solr1
# Where to upload collection configuration and send CoreAdmin requests.
SOLR_HOST=localhost:8983

# The value of index.[X].solr.http-urls in JanusGraph's config file
# should match $SOLR_HOST and $CORE_NAME.  For example, given the
# $CORE_NAME and $SOLR_HOST values above, JanusGraph's config file would
# contain (assuming "search" is the desired index alias):
#
# index.search.solr.http-urls=https://:8983/solr/janusgraph.solr1
#
# The stock JanusGraph config file conf/janusgraph-cql-solr.properties
# ships with this http-urls value.

# Upload Solr config files to DSE Search daemon
for xml in conf/solr/{solrconfig, schema, elevate}.xml ; do
    curl -v http://"$SOLR_HOST"/solr/resource/"$CORE_NAME/$xml" \
      --data-binary @"$xml" -H 'Content-type:text/xml; charset=utf-8'
done
for txt in conf/solr/{protwords, stopwords, synonyms}.txt ; do
    curl -v http://"$SOLR_HOST"/solr/resource/"$CORE_NAME/$txt" \
      --data-binary @"$txt" -H 'Content-type:text/plain; charset=utf-8'
done
sleep 5

# Create core using the Solr config files just uploaded above
curl "http://"$SOLR_HOST"/solr/admin/cores?action=CREATE&name=$CORE_NAME"
sleep 5

# Retrieve and print the status of the core we just created
curl "https://:8983/solr/admin/cores?action=STATUS&core=$CORE_NAME"

现在 JanusGraph 数据库和后端 Solr core 已准备就绪。我们可以使用众神图数据集进行测试。继续上面启动的 Gremlin Console 会话

// Assuming graph = JanusGraphFactory.open('conf/janusgraph-cql-solr.properties')...
gremlin> GraphOfTheGodsFactory.load(graph)
==>null

现在我们可以运行入门中描述的任何查询。涉及文本和地理谓词的查询将由 Solr 提供服务。要获取 JanusGraph 和 Solr 客户端更详细的报告,请运行 gremlin.sh -l DEBUG 并发出一些索引支持的查询。