如何解决 Elasticsearch 中未分配的分片

转至
1.https://www.datadoghq.com/blog/elasticsearch-unassigned-shards/#reason-1-shard-allocation-is-purposefully-delayed

2.https://wklken.me/posts/2015/05/23/elasticsearch-issues.html

原因一:Shard分配被故意延迟

当节点离开集群时,主节点会暂时延迟分片重新分配,以避免在重新平衡分片上不必要地浪费资源,以防原始节点能够在一定时间段内(默认为一分钟)恢复。如果是这种情况,您的日志应如下所示:

[TIMESTAMP][INFO][cluster.routing] [PRIMARY NODE NAME] delaying allocation for [54] unassigned shards, next check in [1m]

您可以像这样动态修改延迟时间:

curl -XPUT "localhost:9200/<INDEX_NAME>/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "5m"
  }
}'

替换<INDEX_NAME>为_all将更新集群中所有索引的阈值。

延迟期结束后,您应该开始看到主要分配这些分片。如果没有,请继续阅读以探索其他潜在原因的解决方案。

原因二:分片太多,节点不够

当节点加入和离开集群时,主节点会自动重新分配分片,确保分片的多个副本不会分配给同一个节点。换句话说,主节点不会将主分片分配给与其副本相同的节点,也不会将同一分片的两个副本分配给同一节点。如果没有足够的节点来相应地分配分片,分片可能会处于未分配状态。

为避免此问题,请遵循以下公式,确保集群中的每个索引初始化时每个主分片的副本数少于集群中的节点数:

N >= R + 1

其中 N 是集群中的节点数,R 是集群中所有索引的最大分片复制因子。

在下面的屏幕截图中,many-shards索引存储在四个主分片上,每个主分片有四个副本。索引的 20 个分片中有 8 个未分配,因为我们的集群仅包含三个节点。尚未分配每个主分片的两个副本,因为三个节点中的每一个都已包含该分片的副本。
要解决此问题,您可以向集群添加更多数据节点或减少副本数量。在我们的例子中,我们要么需要在集群中添加至少两个节点或者 将复制因子减少到两个,如下所示:

curl -XPUT "localhost:9200/<INDEX_NAME>/_settings?pretty" -H 'Content-Type: application/json' -d' { "number_of_replicas": 2 }'

原因3:您需要重新启用分片分配

默认情况下,所有节点上都启用了分片分配,但您可能在某些时候禁用了分片分配(例如,为了执行滚动重启),而忘记重新启用它。

要启用分片分配,请更新Cluster Update Settings API:

curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
    "transient" : {
        "cluster.routing.allocation.enable" : "all"
    }
}
'

如果这解决了问题,您的Kopf或Datadog 仪表板应显示未分配分片的数量随着它们成功分配给节点而减少。

未分配的分片数据狗此 Datadog 时间序列图显示重新启用分片分配后未分配的分片数量减少。
启用分配后未分配的分片更新后的 Kopf 仪表板显示,在重新启用分片分配后,许多以前未分配的分片已被分配。
看起来这解决了我们所有未分配分片的问题,只有一个例外:constant-updates索引的分片 0 。让我们探讨分片仍未分配的其他可能原因。

使用 Datadog 查明并解决未分配的分片和其他 Elasticsearch 问题。

原因4:分片数据不再存在于集群中

在这种情况下,constant-updates索引的主分片 0未分配。它可能是在没有任何副本的节点上创建的(一种用于加速初始索引过程的技术),并且该节点在数据可以复制之前离开了集群。主节点在其全局集群状态文件中检测到分片,但无法在集群中定位分片的数据。

另一种可能性是节点在重新启动时可能遇到了问题。通常,当节点恢复与集群的连接时,它会将有关其磁盘分片的信息中继到主节点,然后主节点将这些分片从“未分配”转换为“已分配/已启动”。当这个过程由于某种原因失败时(例如节点的存储以某种方式损坏),分片可能保持未分配状态。

在这种情况下,您必须决定如何继续:尝试让原始节点恢复并重新加入集群(并执行 不是强制分配主分片),或使用Cluster Reroute API强制分配分片并使用原始数据源或备份重新索引丢失的数据。

如果您决定使用后者(强制分配主分片),需要注意的是您将分配一个“空”分片。如果包含原始主分片数据的节点稍后重新加入集群,则其数据将被新创建的(空)主分片覆盖,因为它将被视为数据的“较新”版本。在继续此操作之前,您可能希望重试分配,这将允许您保留存储在该分片上的数据。

如果您了解其中的含义并且仍想强制分配未分配的主分片,则可以使用该allocate_empty_primary标志来实现。以下命令将constant-updates索引中的主分片 0 重新路由到特定节点:

curl -XPOST "localhost:9200/_cluster/reroute?pretty" -H 'Content-Type: application/json' -d'
{
    "commands" : [
        {
          "allocate_empty_primary" : {
                "index" : "constant-updates", 
                "shard" : 0,
                "node" : "<NODE_NAME>", 
                "accept_data_loss" : "true"
          }
        }
    ]
}
'

请注意,您需要指定"accept_data_loss" : "true"以确认您已准备好丢失分片上的数据。如果不包含此参数,您将看到如下错误:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "remote_transport_exception",
        "reason" : "[NODE_NAME][127.0.0.1:9300][cluster:admin/reroute]"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "[allocate_empty_primary] allocating an empty primary for [constant-updates][0] can result in data loss. Please confirm by setting the accept_data_loss parameter to true"
  },
  "status" : 400
}

您现在需要重新索引丢失的数据,或使用Snapshot and Restore API从备份快照中尽可能多地恢复。

原因5:低磁盘水印

如果没有足够的节点和足够的磁盘空间,主节点可能无法分配分片(它不会为使用超过 85% 的磁盘的节点分配分片)。一旦一个节点达到这个磁盘使用水平,或者 Elasticsearch 称之为“低磁盘水印”,它就不会被分配更多的分片。

您可以通过查询cat API来检查集群中每个节点上的磁盘空间(并查看每个节点上存储了哪些分片):

curl -s ‘localhost:9200/_cat/allocation?v’
如果任何特定节点的磁盘空间不足(删除过时的数据并将其存储在集群外、添加更多节点、升级硬件等),请参阅本文以了解有关如何操作的选项。

如果您的节点具有较大的磁盘容量,则默认的低水位线(85% 的磁盘使用率)可能太低。您可以使用集群更新设置 API来更改cluster.routing.allocation.disk.watermark.low和/或cluster.routing.allocation.disk.watermark.high. 例如,这个Stack Overflow 线程指出,如果你的节点有 5TB 的磁盘容量,你可能可以安全地增加低盘水印 到 90%:

curl -XPUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "90%"
  }
}'

如果您希望您的配置更改在集群重新启动时保持不变,请将“transient”替换为“persistent”,或者在您的配置文件中更新这些值。您可以选择使用字节或百分比值来更新这些设置,但一定要记住Elasticsearch 文档中的这一重要说明:“百分比值是指用过的 磁盘空间,而字节值是指 自由 磁盘空间。”

原因 6:多个 Elasticsearch 版本
这个问题只出现在运行多个版本的 Elasticsearch 的集群中(可能在滚动升级的过程中)。根据Elasticsearch 文档,主节点不会将主分片的副本分配给任何运行旧版本的节点。例如,如果主分片在 1.4 版本上运行,则主节点将无法将该分片的副本分配给运行 1.4 之前任何版本的任何节点。

如果您尝试手动将分片从较新版本节点重新路由到较旧版本节点,您将看到如下错误:

[NO(target node version [XXX] is older than source node version [XXX])]
Elasticsearch不支持回滚到以前的版本,只支持升级。如果这确实是手头的问题,升级运行旧版本的节点应该可以解决问题。

你试过把它关掉再打开吗?
如果上述情况都不适用于您的情况,您仍然可以选择从原始数据源重新索引丢失的数据,或从旧快照恢复受影响的索引,如此处所述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值