15. 集群級別的分片分配和路由設置

集群級別的分片分配和路由設置

分片分配是將分片分配給節點的過程。這可能發生在初始恢復、副本分配、重新平衡或添加或刪除節點時。

主節點的主要作用之一是決定將哪些分片分配給哪些節點,并在需要重新平衡集群時移動分片之間的節點。

有許多設置可用于控制分片分配過程:

  • 集群級別的分片分配設置控制分配和重新平衡操作。
  • 基于磁盤的分片分配設置解釋了Elasticsearch如何考慮可用磁盤空間,以及相關的設置。
  • 分片分配感知和強制感知控制分片如何分布在不同的機架或可用性區域。
  • 集群級別的分片分配過濾允許排除某些節點或節點組,以便它們可以被停用。

除了這些,還有一些其他雜項的集群級別的設置。

集群級別的分片分配設置

您可以使用以下設置來控制分片分配和恢復:

  • cluster.routing.allocation.enable
    (動態)啟用或禁用特定類型分片的分配:
    • all -(默認)允許為所有類型的分片分配。
    • primaries - 僅允許為主分片分配。
    • new_primaries - 僅允許為新索引的主分片分配。
    • none - 不允許任何索引的任何類型的分片分配。

此設置不影響重新啟動節點時本地主分片的恢復。重新啟動節點如果有未分配的主分片的副本將立即進行恢復,假設其分配ID與集群狀態中的活動分配ID之一匹配。

  • cluster.routing.allocation.node_concurrent_incoming_recoveries
    (動態)在節點上允許發生多少并發的傳入分片恢復。傳入恢復是目標分片(很可能是副本,除非分片正在重定位)分配在節點上的情況。默認為2。
  • cluster.routing.allocation.node_concurrent_outgoing_recoveries
    (動態)在節點上允許發生多少并發的傳出分片恢復。傳出恢復是源分片(很可能是主分片,除非分片正在重定位)分配在節點上的情況。默認為2。
  • cluster.routing.allocation.node_concurrent_recoveries
    (動態)設置cluster.routing.allocation.node_concurrent_incoming_recoveriescluster.routing.allocation.node_concurrent_outgoing_recoveries的快捷方式。默認為2。
  • cluster.routing.allocation.node_initial_primaries_recoveries
    (動態)在副本的恢復發生在網絡上傳輸時,重新啟動節點后未分配的主分片的恢復使用來自本地磁盤的數據。這些應該很快,因此可以在同一節點上并行進行更多的初始主分片恢復。默認為4。
  • cluster.routing.allocation.same_shard.host
    (動態)如果為true,則禁止將同一主機上具有相同網絡地址的不同節點分配為分片的多個副本,即它們具有相同的網絡地址。默認為false,這意味著有時可能將分片的副本分配給同一主機上的節點。此設置僅在每個主機上運行多個節點時才相關。
分片再平衡設置

當集群在每個節點上有相等數量的分片,所有節點需要相等的資源,而不在任何節點上集中任何索引的分片時,集群就是平衡的。Elasticsearch運行一個名為再平衡的自動過程,它在集群中的節點之間移動分片,以改善其平衡。再平衡遵循所有其他分片分配規則,如分配過濾和強制感知,這可能會阻止它完全平衡集群。在這種情況下,再平衡會努力在您配置的規則內實現盡可能平衡的集群。如果您使用數據層次,則Elasticsearch會自動應用分配過濾規則,將每個分片放置在適當的層次中。這些規則意味著均衡器在每個層次內獨立工作。

您可以使用以下設置來控制集群中分片的再平衡:

  • cluster.routing.rebalance.enable
    (動態)啟用或禁用特定類型分片的再平衡:
    • all -(默認)允許所有類型的分片進行平衡。
    • primaries - 僅允許對主分片進行平衡。
    • replicas - 僅允許對副本分片進行平衡。
    • none - 不允許任何索引的任何類型的分片進行平衡。
  • cluster.routing.allocation.allow_rebalance
    (動態)指定何時允許分片再平衡:
    • always - 始終允許再平衡。
    • indices_primaries_active - 僅在集群中分配了所有主分片時。
    • indices_all_active -(默認)僅在集群中分配了所有分片(主分片和副本)時。
  • cluster.routing.allocation.cluster_concurrent_rebalance
    (動態)定義在整個集群中允許多少并發分片再平衡。默認為2。請注意,此設置僅控制由于集群中的不平衡而導致的并發分片重定位的數量。此設置不限制由于分配過濾或強制感知而進行的分片重定位。
  • cluster.routing.allocation.type
    選擇用于計算集群平衡的算法。默認為desired_balance,它選擇所需平衡分配器。此分配器運行一個后臺任務,計算集群中分片的所需平衡。一旦此后臺任務完成,Elasticsearch就會將分片移動到其所需的位置。
    [8.8] 在8.8中棄用。平衡分配器類型已棄用,不再推薦。也可以設置為balanced,以選擇傳統的平衡分配器。這個分配器是Elasticsearch在8.6.0之前版本中的默認分配器。它在前臺運行,阻止主節點并行進行其他工作。它通過選擇一小部分立即改善集群平衡的分片移動,并在這些分片移動完成后再次運行并選擇另外一些分片移動來工作。由于此分配器僅基于集群的當前狀態做出決策,因此在平衡集群時,它有時會多次移動分片。

分片平衡啟發式設置

再平衡通過為每個節點計算其分片分配的權重,然后在節點之間移動分片以減小較重節點的權重并增加較輕節點的權重來實現。當沒有可能的分片移動可以將任何節點的權重與任何其他節點的權重之間的差異大于可配置的閾值時,集群就是平衡的。

節點的權重取決于它持有的分片數量,以及這些分片的總估計資源使用量,以磁盤上的分片大小和支持向分片寫入流量所需的線程數量表示。當數據流的分片在滾動時,Elasticsearch在創建時估算了它們的資源使用情況。新分片的估計磁盤大小是數據流中其他分片的平均大小。新分片的估計寫入負載是數據流中最近分片的實際寫入負載的加權平均值。不屬于數據流寫入索引的分片的估計寫入負載為零。

以下設置控制Elasticsearch如何將這些值組合成每個節點權重的整體度量。

  • cluster.routing.allocation.balance.shard
    (浮點數,動態)定義分配給每個節點的總分片數量的權重因子。默認為0.45f。提高此值會增加Elasticsearch均衡節點之間總分片數量的傾向,超過其他平衡變量。
  • cluster.routing.allocation.balance.index
    (浮點數,動態)定義分配給每個節點的每個索引的分片數量的權重因子。默認為0.55f。提高此值會增加Elasticsearch均衡節點之間每個索引的分片數量的傾向,超過其他平衡變量。
  • cluster.routing.allocation.balance.disk_usage
    (浮點數,動態)定義根據預測的字節大小平衡分片的權重因子。默認為2e-11f。提高此值會增加Elasticsearch均衡節點之間總磁盤使用量的傾向,超過其他平衡變量。
  • cluster.routing.allocation.balance.write_load
    (浮點數,動態)定義每個分片的寫入負載的權重因子,以估計所需的索引線程數量表示。默認為10.
基于磁盤的分片分配設置編輯

基于磁盤的分片分配器確保所有節點具有足夠的磁盤空間,而無需執行比必要更多的分片移動。它根據一對稱為低水位線和高水位線的閾值來分配分片。其主要目標是確保沒有節點超過高水位線,或者至少任何此類超出是暫時的。如果某個節點超過高水位線,Elasticsearch 將通過將其一些分片移動到群集中的其他節點來解決這個問題。

節點不時暫時超過高水位線是正常的。

分片分配器還通過禁止將更多分片分配給超過低水位線的節點來努力保持節點遠離高水位線。重要的是,如果所有節點都超過了低水位線,那么將無法分配新的分片,Elasticsearch 將無法在節點之間移動任何分片,以使磁盤使用率保持在高水位線以下。您必須確保群集總體上具有足夠的磁盤空間,并且始終有一些節點低于低水位線。

由基于磁盤的分片分配器觸發的分片移動還必須符合所有其他分片分配規則,例如分配過濾和強制感知。如果這些規則太嚴格,它們還可能阻止用于保持節點磁盤使用量受控制的分片移動。如果您使用數據層,則 Elasticsearch 會自動配置分配過濾規則,將分片放置在適當的層中,這意味著基于磁盤的分片分配器在每個層內部獨立工作。

如果某個節點的磁盤填滿得比 Elasticsearch 能夠將分片移動到其他位置更快,那么磁盤可能會完全填滿。為防止這種情況,作為最后的手段,一旦磁盤使用量達到洪水階段水印,Elasticsearch 將阻止對受影響節點上具有分片的索引進行寫入。它還將繼續將分片移動到群集中的其他節點。當受影響節點上的磁盤使用量降到高水位線以下時,Elasticsearch 將自動移除寫入阻止。請參閱解決持續水印錯誤以解決持久性水印錯誤。

群集中的節點使用的磁盤空間量可能差異很大是正常的。群集的平衡僅取決于每個節點上的分片數量以及這些分片所屬的索引。它既不考慮這些分片的大小,也不考慮每個節點上的可用磁盤空間,原因如下:

磁盤使用會隨時間變化。平衡每個節點的磁盤使用量將需要更多的分片移動,甚至可能浪費之前的移動。移動分片會消耗 I/O 和網絡帶寬等資源,并可能從文件系統緩存中驅逐數據。最好將這些資源用于處理您的搜索和盡可能處理索引。
每個節點上的磁盤使用相等的群集通常性能不比磁盤使用不均勻的群集好,只要沒有磁盤過滿。
您可以使用以下設置來控制基于磁盤的分配:

cluster.routing.allocation.disk.threshold_enabled
(動態)默認為 true。設置為 false 以禁用磁盤分配決策者。禁用后,它還將刪除任何現有的 index.blocks.read_only_allow_delete 索引塊。
cluster.routing.allocation.disk.watermark.low logo cloud
(動態)控制磁盤使用的低水位線。默認為 85%,這意味著 Elasticsearch 不會將分片分配給磁盤使用率超過 85% 的節點。它還可以設置為比率值,例如 0.85。也可以設置為絕對字節值(如 500mb),以防止 Elasticsearch 在可用空間低于指定量時分配分片。此設置對于新創建的索引的主分片沒有影響,但會阻止其副本的分配。
cluster.routing.allocation.disk.watermark.low.max_headroom
(動態)控制低水位線的最大余地(在百分比/比率值的情況下)。當 cluster.routing.allocation.disk.watermark.low 沒有明確設置時,默認為 200GB。這限制所需的可用空間量。
cluster.routing.allocation.disk.watermark.high logo cloud
(動態)控制高水位線。默認為 90%,這意味著 Elasticsearch 將嘗試將分片從磁盤使用率超過 90% 的節點中重新定位。它還可以設置為比率值,例如 0.9。也可以設置為絕對字節值(類似于低水位線),以在節點的可用空間低于指定量時重新定位分片。此設置影響所有分配的分片,無論之前是否分配。
cluster.routing.allocation.disk.watermark.high.max_headroom
(動態)控制高水位線的最大余地(在百分比/比率值的情況下)。當 cluster.routing.allocation.disk.watermark.high 沒有明確設置時,默認為 150GB。這限制所需的可用空間量。
cluster.routing.allocation.disk.watermark.enable_for_single_data_node
(靜態)在早期版本中,單數據節點群集在進行分配決策

時默認情況下會忽略磁盤水印。自 7.14 版本以來,已棄用此行為,并已在 8.0 版本中刪除。此設置的唯一有效值現在是 true。該設置將在將來的版本中刪除。
cluster.routing.allocation.disk.watermark.flood_stage logo cloud
(動態)控制洪水階段水印,默認為 95%。Elasticsearch 在每個節點上分配了一個或多個分片的每個索引上強制執行只讀索引塊(index.blocks.read_only_allow_delete),并且至少有一個磁盤超過了洪水階段。此設置是防止節點耗盡磁盤空間的最后手段。當磁盤利用率降到高水位線以下時,索引塊會自動釋放。與低水位線和高水位線值類似,它還可以設置為比率值,例如 0.95,或絕對字節值。

重置 my-index-000001 索引上的只讀索引塊的示例:

PUT /my-index-000001/_settings
{
  "index.blocks.read_only_allow_delete": null
}
# 或者使用 curl
curl -X PUT "localhost:9200/my-index-000001/_settings" -H 'Content-Type: application/json' -d '{
  "index.blocks.read_only_allow_delete": null
}'

集群路由分配磁盤水印洪水階段最大余地

(動態)控制洪水階段水印的最大余地(在百分比/比率值的情況下)。當 cluster.routing.allocation.disk.watermark.flood_stage 沒有明確設置時,默認為 100GB。這限制所需的可用空間量。

您不能在 cluster.routing.allocation.disk.watermark.low、cluster.routing.allocation.disk.watermark.high 和 cluster.routing.allocation.disk.watermark.flood_stage 設置中混合使用百分比/比率值和字節值。要么所有值都設置為百分比/比率值,要么所有值都設置為字節值。此強制執行是為了 Elasticsearch 可以驗證這些設置在內部是一致的,確保低磁盤閾值小于高磁盤閾值,高磁盤閾值小于洪水階段閾值。max headroom 值也進行了類似的比較檢查。

(動態)控制專用凍結節點的洪水階段水印,默認為 95%。
(動態)控制專用凍結節點的洪水階段水印的最大余地(在百分比/比率值的情況下)。當 cluster.routing.allocation.disk.watermark.flood_stage.frozen 沒有明確設置時,默認為 20GB。這限制專用凍結節點上所需的可用空間量。

(動態)Elasticsearch 應該多久檢查一次集群中每個節點的磁盤使用情況。默認為 30s。

百分比值是指已用磁盤空間,而字節值是指空閑磁盤空間。這可能會令人困惑,因為它顛倒了高和低的含義。例如,將低水位線設置為 10GB,將高水位線設置為 5GB 是有意義的,但反過來則不是。

將低水位線更新為至少有 100GB 空閑,將高水位線更新為至少有 50GB 空閑,將洪水階段水印更新為至少有 10GB 空閑,并且每分鐘更新一次有關群集的信息的示例:

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "100gb",
    "cluster.routing.allocation.disk.watermark.high": "50gb",
    "cluster.routing.allocation.disk.watermark.flood_stage": "10gb",
    "cluster.info.update.interval": "1m"
  }
}
# 或者使用 curl
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d '{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "100gb",
    "cluster.routing.allocation.disk.watermark.high": "50gb",
    "cluster.routing.allocation.disk.watermark.flood_stage": "10gb",
    "cluster.info.update.interval": "1m"
  }
}'

關于水印的最大余地設置,請注意這僅適用于水印設置為百分比/比率的情況。max headroom 值的目的是限制在達到相應水印之前所需的空閑磁盤空間。這對于具有較大磁盤的服務器特別有用,其中百分比/比率水印可能轉換為大量的免費磁盤空間需求,而 max headroom 可以用于限制所需的免費磁盤空間量。例如,讓我們以洪水水印的默認設置為例。它的默認值是 95%,而洪水最大余地設置的默認值是 100GB。這意味著:

對于較小的磁盤,例如 100GB,洪水水印將在達到 95% 時觸發,即在 5GB 的空閑空間時觸發,因為 5GB 小于 100GB 的最大余地值。
對于較大的磁盤,例如 100TB,洪水水印將在 100GB 的空閑空間時觸發。這是因為 95% 的洪水水印單獨將需要 5TB 的免費磁盤空間,但該值被最大余地設置限制為 100GB。
最后,如果其相應的水印設置沒有明確設置(因此,它們具有默認的百分比值),則 max headroom 設置才具有其默認值。如果水印被明確設置,那么 max headroom 設置就不具有默認值,并且如果需要,則需要明確設置。

Shard allocation awareness(分片分配感知)

您可以使用自定義節點屬性作為感知屬性,以使Elasticsearch在分配分片時考慮到您的物理硬件配置。如果Elasticsearch知道哪些節點位于同一物理服務器、同一機架或同一區域,它可以分發主分片及其副本分片,以最小化在發生故障時丟失所有分片副本的風險。

當使用動態的 cluster.routing.allocation.awareness.attributes 設置啟用分片分配感知時,分片僅分配給為指定感知屬性設置了值的節點。如果使用多個感知屬性,Elasticsearch在分配分片時會分別考慮每個屬性。

屬性值的數量確定在每個位置分配多少個分片副本。如果每個位置的節點數量不平衡,并且有很多副本,可能會導致副本分片無法分配。

啟用分片分配感知

要啟用分片分配感知:

  1. 使用自定義節點屬性指定每個節點的位置。例如,如果您希望Elasticsearch在不同的機架上分發分片,則可以在每個節點的 elasticsearch.yml 配置文件中設置一個名為 rack_id 的感知屬性。
node.attr.rack_id: rack_one

您還可以在啟動節點時設置自定義屬性:

./bin/elasticsearch -Enode.attr.rack_id=rack_one
  1. 通過在每個主節點的 elasticsearch.yml 配置文件中設置 cluster.routing.allocation.awareness.attributes,告訴Elasticsearch在分配分片時考慮一個或多個感知屬性。
cluster.routing.allocation.awareness.attributes: rack_id

將多個屬性指定為逗號分隔的列表。
您還可以使用 cluster-update-settings API 設置或更新群集的感知屬性。
使用此示例配置,如果您啟動兩個節點,并將 node.attr.rack_id 設置為 rack_one,然后創建一個具有 5 個主分片和每個主分片 1 個副本的索引,所有主分片和副本將分配到這兩個節點上。
如果添加兩個 node.attr.rack_id 設置為 rack_two 的節點,Elasticsearch將移動分片到新節點,確保(如果可能)相同分片的兩個副本不在同一機架上。
如果 rack_two 失敗并導致兩個節點都宕機,默認情況下,Elasticsearch將丟失的分片副本分配給 rack_one 中的節點。為了防止在相同位置分配特定分片的多個副本,您可以啟用強制感知。

強制感知

默認情況下,如果一個位置失敗,Elasticsearch會將所有缺失的副本分片分配給其余位置。盡管您可能在所有位置上有足夠的資源來托管主分片和副本分片,但是單個位置可能無法托管所有分片。

為了防止在發生故障時使單個位置超負荷,您可以設置 cluster.routing.allocation.awareness.force,以便在其他位置的節點可用之前不分配任何副本。

例如,如果您有一個名為 zone 的感知屬性,并配置了位于 zone1zone2 的節點,您可以使用強制感知來防止 Elasticsearch 在僅有一個區域可用時分配副本:

cluster.routing.allocation.awareness.attributes: zone
cluster.routing.allocation.awareness.force.zone.values: zone1,zone2

指定感知屬性的所有可能值。

使用此示例配置,如果您啟動兩個節點,并將 node.attr.zone 設置為 zone1,然后創建一個具有 5 個分片和每個分片 1 個副本的索引,Elasticsearch將創建該索引并分配 5 個主分片,但不分配副本。只有在具有 node.attr.zone 設置為 zone2 的節點可用時,才會分配副本。

集群級別的分片分配過濾

您可以使用集群級別的分片分配過濾來控制Elasticsearch從任何索引分配分片的位置。這些集群范圍的過濾器與每個索引的分配過濾器和分配感知一起應用。

分片分配過濾器可以基于自定義節點屬性或內置的 _name、_host_ip、_publish_ip、_ip、_host、_id 和 _tier 屬性。

cluster.routing.allocation 設置是動態的,允許將活動索引從一組節點移動到另一組節點。僅當可以在不違反其他路由約束的情況下進行重新定位分片時,才會重新定位分片,例如永不在同一節點上分配主分片和副本分片。

集群級別的分片分配過濾的最常見用例是當您想要停用節點時。為了在關閉節點之前將分片移出節點,您可以創建一個通過其IP地址排除該節點的過濾器:

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.exclude._ip": "10.0.0.1"
  }
}
集群路由設置
  • cluster.routing.allocation.include.{attribute}(動態)將分片分配給其 {attribute} 具有逗號分隔值之一的節點。
  • cluster.routing.allocation.require.{attribute}(動態)僅將分片分配給其 {attribute} 具有逗號分隔值的所有節點。
  • cluster.routing.allocation.exclude.{attribute}(動態)不要將分片分配給其 {attribute} 具有逗號分隔值之一的節點。

集群分配設置支持以下內置屬性:

_name Match nodes by node name
_host_ip Match nodes by host IP address (IP associated with hostname)
_publish_ip Match nodes by publish IP address
_ip Match either _host_ip or _publish_ip
_host Match nodes by hostname
_id Match nodes by node id
_tier Match nodes by the node’s data tier role

_tier 過濾基于節點角色。只有一部分角色是數據層角色,而通用數據角色將與任何層過濾匹配。有一部分角色是數據層角色,但通用數據角色將與任何層過濾匹配。

在指定屬性值時,您可以使用通配符,例如:

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.exclude._ip": "192.168.2.*"
  }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容