Elasticsearch從入門到精通- Elasticsearch 分片分配


Elasticsearch 提供無縫擴展體驗的能力的核心在於其跨機器分配工作負載的能力。這是通過Elasticsearch的sharding創建索引時,您為該Elasticsearch 索引設置主分片和副本分片計數。Elasticsearch 將您的數據和請求分布在這些分片之間,以及跨數據節點的分片上。Elasticsearch 集群的容量和性能主要取決於 Elasticsearch 如何在節點上分配分片。如果您的所有流量都流向一兩個節點,因為它們包含Elasticsearch 集群中的活動索引,那么這些節點將顯示出較高的 CPU、RAM、磁盤和網絡使用率。當這幾個節點崩潰時,您的Elasticsearch 集群中可能有數十或數百個節點處於空閑狀態。

在這篇文章中,我將深入探討 Elasticsearch 的分片分配策略,並討論集群中“熱”節點的原因。有了這種理解,您就可以修復根本原因以實現更好的性能和更穩定的Elasticsearch 集群。

在繼續講解之前,先回顧一下以下基本概念~

集群(cluster)
由一個或多個節點組成, 並通過集群名稱與其他Elasticsearch 集群進行區分
節點(node)
單個ElasticSearch實例. 通常一個節點運行在一個隔離的容器或虛擬機中
索引(index)
在ElasticSearch中, 索引是一組文檔的集合
分片(shard)

Elasticsearch 中的數據會整理為索引。每個索引又由一個或多個分片組成。每個分片都是一個 Lucene 索引實例,您可以將其視作一個獨立的搜索引擎,它能夠對 Elasticsearch 集群中的數據子集進行索引並處理相關查詢。

數據寫到分片上之后,會定期發布到磁盤上不可更改的新 Lucene 段中,此時,數據便可用於查詢了。這稱為刷新。相關原理的詳細介紹,請參見 Elasticsearch:權威指南。

隨着段數越來越多,這些段會定期合並為更大的段。這一過程稱為合並。由於所有段都是不可更改的,這意味着在索引期間所用磁盤空間通常會上下浮動,這是因為只有合並后的新段創建完畢之后,它們所替換的那些段才能刪掉。合並是一項極其耗費資源的任務,尤其耗費磁盤 I/O。

分片是 Elasticsearch 在集群內分發數據的單位。Elasticsearch 在對數據進行再平衡(例如發生故障后)時移動分片的速度取決於分片的大小和數量,以及網絡和磁盤性能。

由於段是不可更改的,所以更新文檔時必須要求 Elasticsearch 首先找到既有文檔,然后將其標為已刪除,並添加更新后版本。刪除文檔時同樣也要求先找到文檔,再將其標為已刪除。有鑒於此,已刪除文檔仍將繼續占用磁盤空間和系統資源,直至將它們合並,而合並過程也會消耗大量系統資源。

通過 Elasticsearch,用戶可以十分高效地從文件系統中直接刪除整個索引,而無需單獨刪除所有記錄。這是迄今為止從 Elasticsearch 中刪除數據的最高效方法。


 

注意: 

1.避免Elasticsearch 分片過大,因為這樣會對集群從故障中恢復造成不利影響。盡管並沒有關於分片大小的固定限值,但是人們通常將 50GB 作為Elasticsearch 分片上限,而且這一限值在各種用例中都已得到驗證。

2.但凡可能,盡量使用時序型索引來管理具有數據保留期要求的數據。根據保留期限對數據分組,將它們存儲到索引中。通過時序型索引,用戶還能隨着時間推移輕松調整Elasticsearch 主分片和副本分片的數量,這是因為用戶可針對要生成的下個Elasticsearch 索引進行這方面的更改。這樣便能簡化對不斷變化的數據量和數據要求的適應過程。

 

副本(replica)
ElasticSearch默認為一個索引創建5個主分片, 並分別為其創建一個副本分片. 也就是說每個索引都由5個主分片成本, 而每個主分片都相應的有一個copy.
對於分布式搜索引擎ElasticSearch來說, 分片及副本的分配將是高可用及快速搜索響應的設計核心.主分片與副本都能處理查詢請求, 它們的唯一區別在於只有主分片才能處理索引請求.

謹慎分配你的分片

當在ElasticSearch集群中配置好你的索引后, 你要明白在集群運行中你無法調整分片設置. 既便以后你發現需要調整分片數量, 你也只能新建創建並對數據進行重新索引(reindex)(雖然reindex會比較耗時, 但至少能保證你不會停機).
主分片的配置與硬盤分區很類似, 在對一塊空的硬盤空間進行分區時, 會要求用戶先進行數據備份, 然后配置新的分區, 最后把數據寫到新的Elasticsearch 分區上.

分片傾斜可能導致集群故障

在最佳Elasticsearch 分片分布中,每台機器的資源利用率是一致的:每個分片具有相同的存儲空間,每個請求都由每個分片提供服務,每個請求都平等地使用 CPU、RAM、磁盤和網絡資源。當您垂直或水平擴展時,額外的節點同樣有助於執行Elasticsearch 集群的工作,從而增加其容量。最佳情況就這么多。在實踐中,你在一個Elasticsearch 集群中運行多個索引,數據分布不均勻,請求在不同節點上以不同的速率處理。在之前的一篇文章中,解釋了Elasticsearch 存儲使用是如何出現偏差的。當分片分布出現偏差時,CPU、網絡和磁盤帶寬的使用也會出現偏差。

例如,假設您有一個包含三個索引的Elasticsearch 集群,每個索引有四個主分片,部署在六個節點上,如下圖所示。方形索引的分片都落在兩個節點上,而圓形和圓角矩形索引混合在四個節點上。如果方形索引接收的流量是其他兩個索引的十倍,那么這些節點將需要十倍於其他四個節點的 CPU、磁盤、網絡和 RAM(可能)。您要么需要根據方形索引的要求進行過度擴展,要么如果您已經針對其他索引進行了擴展,那么您的Elasticsearch 集群就會崩潰。

 

 

 

 

正確的分配策略應該做出尊重系統要求的智能決策。這是一個難題,Elasticsearch 很好地解決了這個問題。讓我們深入了解 Elasticsearch 的算法。

ShardsAllocator 找出放置分片的位置

ShardsAllocator是 Elasticsearch 中的一個接口,其實現負責分片放置。當分片因任何原因未分配時,ShardsAllocator決定將它們放置在Elasticsearch 集群中的哪些節點上。

ShardsAllocator在以下條件下確定分片位置:

  • 索引創建——當您向集群添加索引(或從快照恢復索引)時,ShardsAllocator決定將其分片放置在何處。當您增加索引的副本計數時,它會決定新副本副本的位置。
  • 節點故障——如果一個節點從集群中退出,ShardsAllocator找出該節點上的分片的放置位置。
  • 集群調整大小 - 如果從集群中添加或刪除節點,則ShardsAllocator決定如何重新平衡集群。
  • 磁盤高水位線——當節點上的磁盤使用率達到高水位線(默認為 90% 滿)時,Elasticsearch 會參與ShardsAllocator將分片移出該節點。
  • 手動分片路由 - 當您手動路由分片時,ShardsAllocator還會移動其他分片以確保集群保持平衡。
  • 路由相關設置更新——當您更改影響分片路由的集群或索引設置時,例如分配感知、排除或包含節點(通過 ip 或節點屬性),或過濾索引以包含/排除特定節點。

分片放置策略可以分解為兩個較小的子問題:對哪個Elasticsearch 分片進行操作,以及將其放置在哪個目標節點。默認的 Elasticsearch 實現BalancedShardsAllocator將其職責划分為三個主要的代碼路徑:分配未分配的分片、移動分片和重新平衡分片。這些中的每一個都在內部解決了原始子問題並決定了分片的操作:是將其分配到特定節點上,將其從一個節點移動到另一個節點,還是保持原樣。

reroute當存在可能影響分片放置的集群狀態更改時,將調用在 Elasticsearch 中調用的整體放置操作。

節點選擇

Elasticsearch 通過處理一系列 Allocation Decider 來獲取符合條件的節點列表。節點資格可能因分片和節點上的當前分配而異。並非所有節點都有資格接受特定分片。例如,Elasticsearch 不會將副本分片放在與主分片相同的節點上。或者,如果節點的磁盤已滿,Elasticsearch 無法在其上放置另一個分片。

Elasticsearch 遵循一種貪心的分片放置方法:它做出局部最優決策,希望達到全局最優。節點托管分片的資格被抽象為權重函數,然后將每個分片分配給當前最有資格接受它的節點。將此權重函數視為一個數學函數,給定一些參數,它返回節點上分片的權重。分片最符合條件的節點是具有最小權重的節點。

分配未分配

重新路由調用執行的第一個操作是allocateUnassigned每次創建索引時,都會取消分配其Elasticsearch 分片(主分片和副本分片)。當一個節點離開集群時,該節點上的分片就會丟失。對於丟失的主分片,它們幸存的副本(如果有)被提升為主分片(這是由不同的模塊完成的),並且相應的副本被渲染unassigned所有這些都分配給此操作中的節點。

對於allocateUnassigned()BalancedShardsAllocator遍歷所有未分配的分片,找到有資格接受分片的節點子集(分配決策者),並從中選擇權重最小的節點。

Elasticsearch 有一個固定的順序選擇未分配的分片進行分配。它首先選擇主分片,為一個索引分配所有分片,然后再轉移到下一個索引的主分片。要選擇索引,它使用基於索引優先級、創建數據和索引名稱的比較器(請參閱PriorityComparator)。這可確保 Elasticsearch為盡可能多的索引分配所有主索引,而不是創建多個部分分配的索引。一旦 Elasticsearch 分配了所有主索引,它就會移動到每個索引的第一個副本。然后,它移動到每個索引的第二個副本,依此類推。

移動碎片

考慮縮小Elasticsearch 集群時的場景。為應對工作負載的季節性變化,您剛剛度過了一個高流量季節,現在又恢復到中等工作負載。您想通過刪除一些節點來調整Elasticsearch 集群的大小。如果您刪除保存數據的節點太快,您可能會刪除保存主節點及其副本的節點,從而永久丟失該數據。更好的方法是排除節點子集,等待所有Elasticsearch 分片移出,然后終止它們。

或者,考慮一個節點的磁盤已滿並且必須移出一些分片以釋放空間的情況。在這種情況下,必須將分片移出節點。這是由moveShards()操作處理的,在完成后立即觸發allocateUnassigned()

對於“移動分片”,Elasticsearch 會遍歷集群中的每個分片,並檢查它是否可以保留在當前節點上。如果不是,它從合格節點的子集中(由決策者過濾中選擇權重最小的節點作為該分片的。然后觸發從當前節點到目標節點的分片重定位。 target node

移動操作僅適用於STARTED 分片;跳過任何其他狀態的分片。要從Elasticsearch 集群所有節點均勻移動分片,請moveShards使用nodeInterleavedShardIterator此迭代器首先跨節點進行廣度,從每個節點中選擇一個分片,然后是下一個分片,依此類推。因此,所有節點上的所有分片都被評估為移動,而不是優先考慮一個。

重新平衡分片

當您達到工作負載限制時,您可能會決定添加更多節點來擴展集群。Elasticsearch 應該自動檢測這些節點並重新定位分片以實現更好的分布。添加或刪除節點可能並不總是需要移動分片——如果節點的分片很少(比如說只有一個),而額外的節點只是作為一種主動擴展措施而添加的呢?

Elasticsearch 使用分片分配器中的權重函數抽象來概括這個決定。給定節點上的當前分配,權重函數提供節點上分片的權重。與具有較低權重值的節點相比,具有高權重值的節點不太適合放置分片。比較不同節點上的分片權重,Elasticsearch 決定重定位是否可以改善整體權重分布。

對於重新平衡決策,Elasticsearch 計算每個節點上每個索引的權重,以及索引的最小和最大可能權重之間的差異。(這可以在索引級別完成,因為索引中的每個分片在 Elasticsearch 中都被平等對待。)然后按照最不平衡索引的順序首先處理索引。

Elasticsearch 分片移動是一項繁重的操作。在實際重定位之前,Elasticsearch 對重新平衡前后的分片權重進行建模;只有當操作導致權重分布更平衡時,才會重新定位分片。

最后,再平衡是一個優化問題。超過閾值,移動分片的成本開始超過平衡權重的好處。在 Elasticsearch 中,這個閾值目前是一個固定值,可以通過動態設置進行配置cluster.routing.allocation.balance.threshold當計算出的索引權重增量(其跨節點的最小權重和最大權重之間的差異)小於此閾值時,該Elasticsearch 索引被認為是平衡的。

結論

在這篇文章中,我們介紹了在 Elasticsearch 中支持分片放置和平衡決策的算法。每次重新路由調用都會經歷分配未分配的分片、移動必須從當前節點撤出的分片以及盡可能重新平衡分片的過程。它們共同維持着一個穩定平衡的Elasticsearch 集群。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM