别名
SolrCloud 能够通过备用名称查询一个或多个集合。这些集合的备用名称称为别名,当您想要执行以下操作时非常有用:
-
通过重新定义别名,以原子方式切换到使用新(重新)索引的集合,且零停机时间
-
隔离客户端编程,以防止集合名称更改
-
对多个具有相同模式的集合发出单个查询
有两种类型的别名:标准别名和路由别名。在路由别名中,有两种类型:类别路由别名和时间路由别名。本节将讨论这些类型。
可以将集合更新命令发送到别名,但只能发送到那些解析为单个集合的别名,或那些定义多个集合之间路由的别名(路由别名)。在其他情况下,更新命令会被拒绝并出现错误,因为没有逻辑可用于在多个集合之间分配文档。
标准别名
标准别名使用 CREATEALIAS 命令创建和更新。
可以通过 CLUSTERSTATUS 命令验证别名的成员集合的当前列表。
可以通过 LISTALIASES 命令验证所有别名的完整定义,包括关于该别名的元数据(对于路由别名,请参见下文)。
或者,可以通过使用本地 ZooKeeper 客户端或在管理 UI 中云菜单的树形页面中检查 ZooKeeper 中的 /aliases.json
来获得此信息。
可以使用 DELETEALIAS 命令删除别名。删除别名时,底层集合将 不受影响。
任何引用多个集合的别名(标准或路由)都可能会使相关性变得复杂。默认情况下,SolrCloud 会根据每个分片对文档进行评分。 如果别名中有多个集合,这始终是一个问题,因此如果您有一个用例,其中 BM25 或 TF/IDF 相关性很重要,您将需要启用 ExactStatsCache 实现之一。 但是,对于分析用例,其中结果按数字、日期或字母数字字段值排序,而不是相关性计算,这不是问题。 |
路由别名
为了解决与标准别名相关的更新限制并提供额外的有用功能,开发了路由别名的概念。目前有两种类型的路由别名:时间路由和类别路由。这些将在下面详细描述,但有一些共同的行为。
在处理路由别名的更新时,Solr 会像往常一样初始化其 更新请求处理器链,但是当 DistributedUpdateProcessor
(DUP) 初始化时,它会检测到更新的目标是路由别名,并在其前面注入 RoutedAliasUpdateProcessor
(RAUP)。RAUP 与 Overseer 协调,是路由别名的主要部分,并且必须紧挨着 DUP。不可能在 RAUP 和 DUP 之间配置具有其他类型 UpdateRequestProcessors 的自定义链。
理想情况下,作为路由别名的用户,您无需担心集合命名模式的细节,因为可以通过别名完成查询和更新。添加数据时,您通常应将文档定向到别名(例如,引用别名名称而不是任何集合)。Solr 服务器和 CloudSolrClient
会将更新请求定向到别名指向的第一个集合。一旦服务器收到数据,它将执行必要的路由。
对于所有路由别名,非常重要的一点是路由值**不要**更改。使用相同的 ID 但不同的路由值重新索引文档,会导致通过别名访问到两个具有相同 ID 的不同文档。一旦存在重复的 ID,路由别名的所有查询时行为将是未定义的,并且难以预测。 |
将“数据驱动”模式(又名无模式模式)与路由别名一起使用不是一个好主意,因为可能会同时发生重复的模式变更,从而导致错误。 |
时间路由别名
时间路由别名 (TRA) 是一个 SolrCloud 功能,用于管理别名和时间顺序的一系列集合。
它会自动创建新集合,并(可选)删除旧集合,因为它会根据文档的时间戳将文档路由到正确的集合。这种方法允许无限期地索引数据,而不会因单个索引的持续增长而导致性能下降。
如果您需要在 Solr 中存储大量带有时间戳的数据,例如日志或物联网传感器数据,那么此功能可能比创建单个分片哈希路由集合更有意义。
工作原理
首先,使用带有期望路由器设置的 CREATEALIAS 命令创建时间路由别名。大多数设置可以在稍后使用 ALIASPROP 命令进行编辑。
将自动创建第一个集合,以及指向它的别名。TRA 中集合的每个底层 Solr “核心”都具有一个引用别名的特殊核心属性。每个集合的名称由 TRA 名称和开始时间戳 (UTC) 组成,并截断尾随的零和符号。
TRA 的集合列表始终是反向排序的,因此请求的连接路径将路由到引导集合。使用 CloudSolrClient
更可取,因为它可以减少一个底层物理 HTTP 请求的数量。如果您知道要传递的特定文档集将进入特定的旧集合,那么您可以从客户端侧将其定向到那里进行优化,但这并非必要。 CloudSolrClient
(尚未)执行此操作。
RAUP 在初始化时首先从别名属性中读取 TRA 配置。当它看到每个文档时,它会检查 TRA 属性的更改,如果需要,则更新其缓存的配置,然后确定该文档属于哪个集合。
-
如果 RAUP 需要将其发送到由客户端选择与之通信的集合之外的某个时间段表示的集合,那么它将使用与 DUP 共享的机制进行发送。一旦文档被转发到正确的集合(即正确的 TRA 时间段),它将直接跳到目标集合上的 DUP 并正常继续,可能会再次路由到目标集合中的正确分片和副本。
-
如果它属于当前集合(如果处理正在发生的事件,通常是这种情况),则文档会传递到 DUP。DUP 执行其正常的集合级处理,其中可能涉及将文档路由到另一个分片和副本。
-
如果文档上的时间戳比最新的 TRA 段更新,则需要在 TRA 的开头添加新集合。RAUP 将创建此集合,将其添加到别名,然后将文档转发到它刚刚创建的集合。如果需要创建多个集合,则可能会递归发生这种情况。
每次添加新集合时,都会检查 TRA 中最旧的集合是否可能被删除(如果已配置)。所有这些操作都是同步发生的,可能会增加更新请求和索引延迟的时间(秒级别)。
如果配置了
router.preemptiveCreateMath
,并且文档在此窗口内到达,则会异步发生。有关更多信息,请参阅 时间路由别名参数。
任何其他类型的更新(如提交或删除)都由 RAUP 路由到所有集合。一般来说,这不是性能问题。当 Solr 接收到删除或提交操作,而其中没有删除任何内容或不需要提交任何内容时,则开销非常低。
类别路由别名
类别路由别名 (CRA) 是一种根据单个字段的值管理别名和一组相关集合的功能。
CRA 会自动创建新集合,但由于分区是基于类别信息而不是连续的数值,因此没有自动删除的逻辑。这种方法允许简化必须为了集群管理或安全原因而隔离到集合中的数据的索引。
工作原理
首先,使用带有期望路由器设置的 CREATEALIAS 命令创建类别路由别名。大多数设置可以在稍后使用 ALIASPROP 命令进行编辑。
将创建一个带有特殊占位符集合的别名,该集合始终命名为 myAlias__CRA__NEW_CATEGORY_ROUTED_ALIAS_WAITING_FOR_DATA__TEMP
。索引到 CRA 中的第一个文档将创建第二个名为 myAlias__CRA__foo
的集合(对于路由字段值为 foo
)。索引的第二个文档将导致删除临时占位符集合。此后,每当遇到该字段的新值时,都会创建集合。
为了防止失控的集合创建,提供了限制类别总数以及拒绝不匹配的值的选项,并提供了一个正则表达式参数(有关详细信息,请参阅 类别路由别名参数)。 |
+ 请注意,通过为这些选项提供非常大或非常宽松的值,您将承担杂乱的数据可能会创建数千个集合并使您的集群陷入停顿的风险。
字段值(以及集合名称)区分大小写。
与 Solr 中的其他位置一样,预计数据的操作和清理将在数据发送到 Solr 之前由外部进程完成,但有一个例外。在整个 Solr 中,对集合名称中允许的字符存在限制。在计算类别的集合名称时,除了 ASCII 字母数字字符 (A-Za-z0-9
)、连字符 (-
) 或下划线 (_
) 之外的任何字符都将被替换为下划线。对于名为 myAlias
的 CRA,下表显示了如何计算集合名称
值 | CRA 集合名称 |
---|---|
foo |
myAlias__CRA__foo |
Foo |
myAlias__CRA__Foo |
foo bar |
myAlias__CRA__foo_bar |
FOÓB&R |
myAlias__CRA__FO_B_R |
中文的东西 |
myAlias__CRA_______ |
foo__CRA__bar |
导致 400 错误请求 |
<null> |
导致 400 错误请求 |
由于创建集合可能需要 1-3 秒或更长时间,因此应构建在 CRA 中插入数据的系统,以便在创建新集合时处理此类暂停。与时间路由别名不同,无法预测下一个值,因此这种暂停是不可避免的。
没有自动删除类别的方法。如果需要从 CRA 中删除类别,建议执行以下过程
-
通过停止索引或修复传入的数据流,确保不会发送任何具有要删除的类别对应值的文档
-
修改 ZooKeeper 中的别名定义,删除与类别对应的集合。
-
删除与类别对应的集合。请注意,如果首先未从别名中删除该集合,则此步骤将失败。
维度路由别名
对于期望数据隔离与两个字段相关,并且在索引期间组合到一个字段中是不切实际的情况,或者需要跨多个类别的 TRA 行为,可以使用维度路由别名。此功能旨在处理任意数量和组合的类别和时间维度,并按任何顺序排列,但请用户仔细考虑由此配置产生的集合总数。数百或数千个集合的数量开始对 ZooKeeper 构成重大挑战。
DRA 是一项新功能,目前仅支持 2 个维度。未来将支持更多维度(有关进度,请参阅 https://issues.apache.org/jira/browse/SOLR-13628)。 |
工作原理
首先,您需要为每个维度创建一个具有所需路由器设置的维度路由别名(DRA)。有关如何指定每个维度的配置的详细信息,请参阅 CREATEALIAS 命令文档。典型的集合名称将采用以下形式(例如,类别 x 时间的示例,时间间隔为 30 分钟):
myalias__CRA__someCategory__TRA__2019-07-01_00_30
请注意,初始集合将是任何包含基于类别的维度的 DRA 的临时占位符。集合名称的每个子部分的名称生成与组件维度类型的相应部分相同(例如,类别值生成 CRA 或 TRA 仍然会产生错误)。
之前关于使用不同路由值重新索引文档的警告适用于 DRA 的每个维度。对于用于路由的类别或时间戳将发生更改的文档,DRA 是不合适的(当然,这也适用于未来 RA 类型中的其他路由值)。 |
与所有路由别名一样,如果您的数据不符合预期,DRA 会产生一些成本。除了每个组件维度的正常注意事项外,还需要注意在 DRA 运行一段时间后发送新类别。有序维度(时间)的行为与无序维度(类别)略有不同。有序维度依赖于别名中集合的迭代顺序,因此无法容忍生成乱序的集合名称。这意味着,当有序维度(例如时间)是 DRA 的组件,并且 DRA 接收到具有新类别且时间值与时间维度的起始时间片不同的文档时,需要创建多个集合才能索引该文档。这种“新类别效应”与您选择过早的开始日期时 TRA 的行为相同。
例如,给定一个时间为 2019-07-01T00:00:00Z 的 Dimensional[时间,类别] DRA,为 4 个文档创建的集合模式可能如下所示:
没有文档
别名集合
myalias__TRA__2019-07-01__CRA__NEW_CATEGORY_ROUTED_ALIAS_WAITING_FOR_DATA_TEMP
文档 1
-
时间:2019-07-01T00:00:00Z
-
类别:someCategory
别名集合
myalias__TRA__2019-07-01__CRA__NEW_CATEGORY_ROUTED_ALIAS_WAITING_FOR_DATA_TEMP
myalias__TRA__2019-07-01__CRA__someCategory
文档 2
-
时间:2019-07-02T00:04:00Z
-
类别:otherCategory
别名集合
myalias__TRA__2019-07-01__CRA__someCategory
myalias__TRA__2019-07-01__CRA__otherCategory // 2 collections created in one update
myalias__TRA__2019-07-02__CRA__otherCategory
文档 3
-
时间:2019-07-03T00:12:00Z
-
类别:thirdCategory
别名集合
myalias__TRA__2019-07-01__CRA__someCategory
myalias__TRA__2019-07-01__CRA__otherCategory
myalias__TRA__2019-07-02__CRA__otherCategory
myalias__TRA__2019-07-01__CRA__thirdCategory // 3 collections created in one update!
myalias__TRA__2019-07-02__CRA__thirdCategory
myalias__TRA__2019-07-03__CRA__thirdCategory
文档 4
-
时间:2019-07-03T00:12:00Z
-
类别:someCategory
别名集合
myalias__TRA__2019-07-01__CRA__someCategory
myalias__TRA__2019-07-01__CRA__otherCategory
myalias__TRA__2019-07-02__CRA__otherCategory
myalias__TRA__2019-07-01__CRA__thirdCategory
myalias__TRA__2019-07-02__CRA__thirdCategory
myalias__TRA__2019-07-03__CRA__thirdCategory
myalias__TRA__2019-07-02__CRA__someCategory // 2 collections created in one update
myalias__TRA__2019-07-03__CRA__someCategory
因此,DRA 的最佳应用场景是对于一组维度标准化的且不会发生变化的,并且会定期出现所有排列组合的数据集。如果稍后引入新类别并且索引延迟是一个重要的 SLA 功能,则可以采取以下几种策略来缓解此影响:
-
如果要创建的额外时间片数量不多,则可以从常规索引中发送单个文档,并等待集合创建完成,然后再允许通过 SLA 约束的流程发送新类别。
-
如果上述过程可能创建大量集合,并且已知新类别中最可能的文档时间,可以使用 ALIASPROP 命令调整时间维度的开始时间。
改进的可能性
路由别名是 SolrCloud 中一个相对较新的功能,有望得到改进。一些可能的改进领域,尚未实现,如下所示:
-
TRAs:具有时间过滤器的搜索应仅定向到适用的集合。
-
TRAs:自动优化(或减少资源)不期望收到更多更新且可能搜索需求较少的较旧集合的方法。
-
CRAs:通过 Base64 编码对非英语文本的内在支持。
-
CRAs:在预先知道的情况下,提供初始值列表,以减少索引期间的暂停。
-
DRAs:支持超过 2 个维度。
-
CloudSolrClient
可以根据路由值将文档路由到正确的集合,而不是始终选择最新/第一个集合。 -
目前,只有更新会被路由,查询会分发到别名中的所有集合,但未来的功能可能会允许将查询路由到单个合适的集合,基于特殊参数或者对路由字段的过滤。
-
集合的大小可能受到限制,而不是时间或类别值。这可以作为另一种类型的路由别名实现,或者作为现有路由别名的选项实现。
-
可以选择删除别名,同时一步删除底层集合。在初始测试期间,路由别名可能会快速创建比预期更多的集合。在这种事件发生后删除它们会过于繁琐。
一如既往,欢迎提交补丁和拉取请求!
集合命令和别名
SolrCloud 支持在通常需要集合名称的集合命令中使用别名。这仅在满足以下条件时才有效:
-
使用请求参数
followAliases=true
-
一个别名不得引用多个集合
-
一个别名不得引用路由别名
如果满足所有条件,则该命令将解析所有别名,并对别名引用的集合执行操作,就像使用集合名称调用一样。否则,该命令将不会执行,并且会抛出异常。
应该谨慎使用 followAliases=true
参数,以确保解析的目标确实是预期的目标。对于多级别名或影子别名(与现有集合具有相同名称但指向其他集合的别名),强烈建议不要使用此选项,因为效果可能难以正确预测。