codecamp

SolrCloud:基于规则的副本放置

当Solr需要将节点分配给集合时,它可以自动为它们分配,也可以指定一组节点来创建副本。

对于非常大的群集,很难指定确切的节点名称,但它仍然不能精确地控制如何选择节点。用户应完全控制分配给每个集合、碎片和副本的节点的位置。这有助于在整个群集上优化配置硬件资源。

基于规则的副本分配允许创建规则来确定副本在群集中的位置。将来,此功能将有助于在系统停机或需要更高的吞吐量时自动添加或删除副本。这使得对群集的管理更加不干预。

此功能在以下情况使用:

  • 集合创建
  • 碎片创建
  • 副本创建
  • 碎片分各

常见用例

有以下几种情况可以使用这个功能。下面列出了一些可以实施的规则:

  • 不要将多个副本分配给主机。
  • 将所有副本分配给具有超过100GB可用磁盘空间的节点,或者,在存在更多磁盘空间的情况下分配副本。
  • 不要在给定的主机上分配任何副本,因为我想在那里运行一个overseer。
  • 只在机架中分配一个分片的一个副本。
  • 在承载少于5个核心的节点中分配副本。
  • 在承载最小内核数的节点中分配副本。

规则条件

规则是一个节点必须满足的一组条件,然后才能创建一个副本核心。

有以下三种可能的情况:

  • 碎片:这是一个碎片或通配符的名称(*表示所有碎片)。如果未指定碎片,则该规则适用于整个集合。
  • 副本:这可以是数字或通配符(*表示任何数字从零到无穷大)。
  • 标签:这是集群中可用于规则的节点的属性,例如“freedisk”、“cores”、“rack”、“dc”等。标签名称可以是自定义字符串。如果创建一个自定义标签,则一个告密者负责提供标签和值。下面的Snitches部分描述了如何添加自定义标签,并定义了六个预定义的标签(核心(cores),freedisk,主机(host),端口(port),节点(node)和sysprop)。

规则运算符

条件可以有以下运算符之一来设置规则的参数:

  • 等于(不需要运算符):tag:x 表示标签值必须等于'x'。
  • 大于(>):tag:>x 表示大于'x'的标签值;x必须是一个数字。
  • 小于(<):tag:<x 表示小于'x'的标签值;x必须是一个数字。
  • 不等于(!):tag:!x 表示标签值不能等于'x';对字符串值执行等号检查。

Fuzzy运算符(〜)

这可以用作任何条件的后缀。这将首先试图严格满足规则。如果Solr找不到足够的节点来匹配标准,它会尝试找到下一个可能不符合标准的最佳匹配。例如,如果我们有一个规则:freedisk:>200~,Solr将尝试在具有超过200GB可用磁盘空间的节点上分配此集合的副本。如果这是不可能的,将选择具有最多可用磁盘空间的节点。

在等号间选择

首先对这些节点进行排序,然后使用规则对它们进行排序。这确保即使许多节点匹配规则,最佳节点也被挑选出来用于节点分配。例如,如果存在诸如以下规则:freedisk:>20,则首先在磁盘空间对节点进行降序排序并且首先拾取具有最多磁盘空间的节点。或者,如果规则是:cores:<5,则节点按照核心数量升序排序,并且首先拾取具有最少内核数的节点。

新碎片规则

规则与集合状态一起被保存。所以,当一个新的副本被创建时,系统将分配满足规则的副本。当使用Collection API的CREATESHARD命令创建新的分片时,请确保已经为该分片名称创建了特定的规则。可以使用 MODIFYCOLLECTION命令更改规则。但是,如果规则没有指定明确的分片名称,则不需要这样做。例如,诸如规则:shard:shard1,replica:*,ip_3:168:将不适用于所创建的任何新的碎片。但是,如果你的规则是replica:*,ip_3:168,那么它将适用于任何新创建的碎片。

这同样适用于碎片分割。碎片拆分的处理方式与碎片创建的方式完全相同。即使 shard1_1 和 shard1_2 可能是从 shard1 创建的,规则将它们视为独立、不相关的碎片。

Snitch

标记值来自一个名为Snitch的插件。如果在规则中有一个名为“rack”的标签,那么必须为Snitch提供集群中每个节点的“rack”值。一个小告警实现了Snitch接口。Solr默认提供了一个默认的snitch,它提供了以下标签:

  • 核心(cores):节点中的核心数量
  • freedisk:节点中可用的磁盘空间
  • 主机(host):节点的主机名
  • 端口(port):节点的端口
  • 节点(node):节点名称
  • 角色(role):节点的角色。唯一支持的角色是“overseer”
  • ip_1,ip_2,ip_3,ip_4:这些是每个节点的ip分段。例如,在具有IP 192.168.1.2的主机中:ip_1 = 2,ip_2 =1,ip_3 = 168和`IP_4 = 192`
  • sysprop.{PROPERTY_NAME}:这些是从系统属性可用的值。sysprop.key表示在节点启动时传递给-Dkey=keyValue的节点的值。有可能使用像sysprop.key:expectedVal,shard:*的规则

如何配置Snitches

可以对一组规则使用一个或多个snit。如果规则只需要默认的snitch标签,就不需要显式配置。例如:

snitch=class:fqn.ClassName,key1:val1,key2:val2,key3:val3

如何收集标签值:

  1. 确定规则中的一组标签
  2. 创建指定的Snitches的实例。默认的snitch总是被创建。
  3. 询问每个Snitch是否可以为任何标签提供值。如果存在一个标签没有snitch,分配也会失败。
  4. 在识别出Snitches之后,它们为集群中的每个节点提供标签值。
  5. 如果给定节点没有获得标签的值,则不能参与分配。

副本放置示例

在任何节点上保留少于2个副本(最多1个副本)

对于这个规则,我们用“小于2”的运算符来定义replica条件,并使用预定义的标签node来定义具有任何名称的节点。

replica:<2,node:*
// this is equivalent to replica:<2,node:*,shard:**. We can omit shard:** because ** is the default value of shard

对于给定的分片,在任何节点上保留少于2个副本

对于这个规则,我们使用shard条件来定义任何碎片,replica运算符为“少于2”的条件,最后是一个预定义的标记,node用于定义具有任何名称的节点。

shard:*,replica:<2,node:*

将shard1中的所有副本分配到机架730

此规则将shard条件限制为“shard1”,但将任何数量的副本限制在内。我们还引用了一个名为“rack”的自定义标签。在定义这个规则之前,我们需要配置一个为标签提供值的自定义Snitch rack。

shard:shard1,replica:*,rack:730

在这种情况下,replica的默认值是*(或所有副本)。所以可以省略,规则可以简化为:

shard:shard1,rack:730

仅在少于5个核心的节点中创建副本

此规则使用该replica条件来定义任意数量的副本,但会添加一个预定义的标签“core”,并使用“少于5”的运算符。

replica:*,cores:<5

再次,我们可以简化这个使用replica的默认值,如下所示:

cores:<5

不要在主机192.45.67.3中创建任何副本

此规则仅使用预定义标签host来定义不应放置副本的IP地址。

host:!192.45.67.3

定义规则

规则在集合创建期间被指定为请求参数。在这个例子中,可以指定多个“rule”和“snitch”参数:

snitch=class:EC2Snitch&rule=shard:*,replica:1,dc:dc1&rule=shard:*,replica:<2,dc:dc3

这些规则被保存在ZooKeeper的clusterstate.json中,并且在整个生命周期中都可用。这使系统能够执行任何未来的节点分配而无需用户直接交互。创建集合期间添加的规则可以稍后使用MODIFYCOLLECTION API 进行修改。

使用ConfigSets API
CDCR概述
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

SolrCloud

SolrCloud配置和参数

如何使用AsciiDoc

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }