Solr部署:别名
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中存储大量时间戳数据,例如日志或IoT传感器数据,那么此功能可能比创建一个分片哈希路由集合更有意义。
工作原理
首先,您使用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接收到没有删除任何内容的删除或没有需要提交的提交时,它相当便宜。
限制和假设
仅支持时间路由别名。
如果您有其他顺序号,您可以将其伪造为时间(例如,假设某个纪元并递增,转换为时间戳)。最小可能间隔是一秒。
不支持其他路由方案,尽管开发此功能时考虑了它可以扩展/改进到其他方案。底层集合形成没有间隙的连续序列。
当底层数据有大间隙时,这将不适合,因为Solr将坚持每个增量都有集合。
这部分是因为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错误请求 |
+ |
导致400错误请求 |
由于集合创建可能需要1-3秒,在CRA中插入数据的系统应该构建为在创建新集合时处理此类暂停。
与时间路由别名不同,没有办法预测下一个值,因此此类暂停是不可避免的。
没有自动删除类别的手段。
如果需要从CRA中删除类别,建议以下过程:
// TODO:这应该有示例说明
- 确保不会发送具有与要删除类别对应值的文档,通过停止索引或修复传入数据流
- 修改ZooKeeper中的别名定义,删除与类别对应的集合。
- 删除与类别对应的集合。
注意如果集合不首先从别名中删除,此步骤将失败。
限制和假设
CRA目前不适用于非英语数据值,由于集合名称的限制。
这可以通过将路由值复制到**URL安全**Base64编码字段并在该值上路由来解决。对
__CRA__
中缀的检查独立于正则表达式验证,并在计算要创建集合的名称之后发生。
它不能被避免,对于支持未来功能是必要的。
维度路由别名
对于所需的数据分离涉及两个字段并且在索引期间组合到单个字段不切实际的情况,或者跨多个类别需要TRA行为的情况,可以使用维度路由别名。
此功能设计为处理任意数量和任何顺序的类别和时间维度组合,但用户被警告要仔细考虑此类配置产生的集合总数。
数百个或1000个左右的集合计数开始对ZooKeeper造成重大挑战。
注意: DRA是新功能,目前只支持2个维度。
未来将支持更多维度(参见https://issues.apache.org/jira/browse/SOLR-13628了解进度)。
工作原理
首先,您为每个维度创建具有所需路由器设置的维度路由别名。
有关如何指定每个维度配置的详细信息,请参见CREATEALIAS命令文档。
典型集合名称将是以下形式(示例为类别x时间示例,30分钟间隔):
1 | 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的维度[time,category] DRA,4个文档的集合创建模式可能如下所示:
没有文档
别名集合:
1 | // temp避免空别名错误条件 |
文档1
- time: 2019-07-01T00:00:00Z
- category: someCategory
别名集合:
1 | // temp保留以避免在与集合创建竞争时出现空别名 |
文档2
- time: 2019-07-02T00:04:00Z
- category: otherCategory
别名集合:
1 | // temp现在可以删除而不会有空别名风险。 |
文档3
- time: 2019-07-03T00:12:00Z
- category: thirdCategory
别名集合:
1 | myalias__TRA__2019-07-01__CRA__someCategory |
文档4
- time: 2019-07-03T00:12:00Z
- category: someCategory
别名集合:
1 | myalias__TRA__2019-07-01__CRA__someCategory |
因此,DRA的最佳点是对于具有标准化维度集且不会改变并且完整排列组合定期发生的数据集。
如果稍后引入新类别并且索引延迟是重要的SLA功能,有几种策略可以减轻这种影响:
如果要创建的额外时间片数量不是很大,则从常规索引中发送单个文档,并在允许新类别通过SLA约束过程发送之前等待集合创建完成。
如果上述过程可能创建极多数量的集合,并且新类别中最早可能文档已知,可以使用ALIASPROP命令调整时间维度的开始时间
改进可能性
路由别名是SolrCloud相对较新的功能,可以预期会改进。
一些**尚未实施**的_潜在_改进领域是:
TRA: 带时间过滤器的搜索应该只到适用的集合。
TRA: 自动优化(或减少资源)较旧集合的方法,这些集合预期不会接收更多更新,并且可能有更少的搜索需求。
CRA: 通过Base64编码对非英语文本的内在支持。
CRA: 为事先知道值的情况提供初始值列表,以减少索引期间的暂停。
DRA: 支持超过2个维度。
CloudSolrClient
可以基于路由值将文档路由到正确集合,而不是总是选择最新/第一个。目前只有更新被路由,查询分发到别名中的所有集合,但未来功能可能支持基于特殊参数或可能对路由字段的过滤器将查询路由到单个适当集合。
集合可能受其大小而非时间或类别值约束。
这可能实施为另一种类型的路由别名,或可能作为现有路由别名的选项删除别名的选项,也在一步中删除底层集合。
路由别名可能在初始测试期间快速创建比预期更多的集合。
在此类事件后删除它们过于繁琐。
一如既往,欢迎补丁和拉取请求!
集合命令和别名
SolrCloud支持在通常需要集合名称的集合命令中使用别名名称。
这仅在满足以下条件时工作:
- 使用请求参数
followAliases=true
- 别名不得引用超过一个集合
- 别名不得引用路由别名
如果满足所有条件,命令将解析所有别名名称并对别名引用的集合进行操作,就好像它是用集合名称调用的一样。
否则命令不会执行并会抛出异常。
应该小心使用followAliases=true
参数,以便解析的目标确实是预期的。
在多级别名或影子别名(与现有集合同名但指向其他集合的别名)的情况下,强烈不建议使用此选项,因为效果可能难以正确预测。