大多數ElasticSearch使用者在建立索引時通用會問的一個重要問題是:我需要建立多少個分片?
在本文中, 我将介紹在分片配置設定時的一些權衡以及不同設定帶來的性能影響. 如果想搞清晰你的分片政策以及如何優化,請繼續往下閱讀.
為什麼要考慮分片數
分片配置設定是個很重要的概念, 很多使用者對如何分片都有所疑惑, 當然是為了讓配置設定更合理. 在生産環境中, 随着資料集的增長, 不合理的配置設定政策可能會給系統的擴充帶來嚴重的問題.
同時, 這方面的文檔介紹也非常少. 很多使用者隻想要明确的答案而不僅僅一個數字範圍, 甚至都不關心随意的設定可能帶來的問題.
當然,我也有一些答案. 不過先要看看它的定義和描述, 然後通過幾個通用的案例來分别給出我們的建議.
分片定義
如果你剛接觸ElasticSearch, 那麼弄清楚它的幾個術語和核心概念是非常必要的.
(如果你已經有ES的相關經驗, 可以跳過這部分)
假設ElasticSearch叢集的部署結構如下:

通過該圖, 記住下面的幾個定義:
叢集(cluster):由一個或多個節點組成, 并通過叢集名稱與其他叢集進行區分
節點(node):單個ElasticSearch執行個體. 通常一個節點運作在一個隔離的容器或虛拟機中
索引(index):在ES中, 索引是一組文檔的集合
分片(shard):因為ES是個分布式的搜尋引擎, 是以索引通常都會分解成不同部分, 而這些分布在不同節點的資料就是分片. ES自動管理群組織分片, 并在必要的時候對分片資料進行再平衡配置設定, 是以使用者基本上不用擔心分片的處理細節,一個分片預設最大文檔數量是20億.
副本(replica):ES預設為一個索引建立5個主分片, 并分别為其建立一個副本分片. 也就是說每個索引都由5個主分片成本, 而每個主分片都相應的有一個copy.
對于分布式搜尋引擎來說, 分片及副本的配置設定将是高可用及快速搜尋響應的設計核心.主分片與副本都能處理查詢請求, 它們的唯一差別在于隻有主分片才能處理索引請求.
在上圖示例中, 我們的ElasticSearch叢集有兩個節點, 并使用了預設的分片配置. ES自動把這5個主分片配置設定到2個節點上, 而它們分别對應的副本則在完全不同的節點上. 對,就這是分布式的概念.
請記住, 索引的number_of_shards參數隻對目前索引有效而不是對整個叢集生效.對每個索引來講, 該參數定義了目前索引的主分片數(而不是叢集中所有的主分片數).
關于副本
本文中不會對ElasticSearch的副本做詳細闡述. 如果想單獨了解可參考這篇文章.
副本對搜尋性能非常重要, 同時使用者也可在任何時候添加或删除副本. 正如另篇文章所述, 額外的副本能給你帶來更大的容量, 更高的呑吐能力及更強的故障恢複能力.
謹慎配置設定你的分片
當在ElasticSearch叢集中配置好你的索引後, 你要明白在叢集運作中你無法調整分片設定. 既便以後你發現需要調整分片數量, 你也隻能建立建立并對資料進行重新索引(reindex)(雖然reindex會比較耗時, 但至少能保證你不會停機).
主分片的配置與硬碟分區很類似, 在對一塊空的硬碟空間進行分區時, 會要求使用者先進行資料備份, 然後配置新的分區, 最後把資料寫到新的分區上.
2~3GB的靜态資料集
配置設定分片時主要考慮的你的資料集的增長趨勢.
我們也經常會看到一些不必要的過度分片場景. 從ES社群使用者對這個熱門主題(分片配置)的分享資料來看, 使用者可能認為過度配置設定是個絕對安全的政策(這裡講的過度配置設定是指對特定資料集, 為每個索引配置設定了超出目前資料量(文檔數)所需要的分片數).
Elastic在早期确實鼓吹過這種做法, 然後很多使用者做的更為極端–例如配置設定1000個分片. 事實上, Elastic目前對此持有更謹慎的态度.
稍有富餘是好的, 但過度配置設定分片卻是大錯特錯. 具體定義多少分片很難有定論, 取決于使用者的資料量和使用方式. 100個分片, 即便很少使用也可能是好的;而2個分片, 即便使用非常頻繁, 也可能是多餘的.
要知道, 你配置設定的每個分片都是有額外的成本的:
- 每個分片本質上就是一個Lucene索引, 是以會消耗相應的檔案句柄, 記憶體和CPU資源
- 每個搜尋請求會排程到索引的每個分片中. 如果分片分散在不同的節點倒是問題不太. 但當分片開始競争相同的硬體資源時, 性能便會逐漸下降
- ES使用詞頻統計來計算相關性. 當然這些統計也會配置設定到各個分片上. 如果在大量分片上隻維護了很少的資料, 則将導緻最終的文檔相關性較差
我們的客戶通常認為随着業務的增長, 他們的資料量也會相應的增加, 是以很有必要為此做長期規劃. 很多使用者相信他們将會遇到暴發性增長(盡管大多數甚至都沒有遇到過峰值), 當然也希望避免重新分片并減少可能的停機時間.
如果你真的擔心資料的快速增長, 我們建議你多關心這條限制: ElasticSearch推薦的最大JVM堆空間是30~32G, 是以把你的分片最大容量限制為30GB, 然後再對分片數量做合理估算. 例如, 你認為你的資料能達到200GB, 我們推薦你最多配置設定7到8個分片.
總之, 不要現在就為你可能在三年後才能達到的10TB資料做過多配置設定. 如果真到那一天, 你也會很早感覺到性能變化的.
盡管本部分并未詳細讨論副本分片, 但我們推薦你保持适度的副本數并随時可做相應的增加. 如果你正在部署一個新的環境, 也許你可以參考我們的基于副本的叢集的設計.這個叢集有三個節點組成, 每個分片隻配置設定了副本. 不過随着需求變化, 你可以輕易的調整副本數量.
大規模以及日益增長的資料場景
對大資料集, 我們非常鼓勵你為索引多配置設定些分片–當然也要在合理範圍内. 上面講到的每個分片最好不超過30GB的原則依然使用.
不過, 你最好還是能描述出每個節點上隻放一個索引分片的必要性. 在開始階段, 一個好的方案是根據你的節點數量按照1.5~3倍的原則來建立分片. 例如,如果你有3個節點, 則推薦你建立的分片數最多不超過9(3x3)個.
随着資料量的增加,如果你通過叢集狀态API發現了問題,或者遭遇了性能退化,則隻需要增加額外的節點即可. ES會自動幫你完成分片在不同節點上的分布平衡.
再強調一次, 雖然這裡我們暫未涉及副本節點的介紹, 但上面的指導原則依然使用: 是否有必要在每個節點上隻配置設定一個索引的分片. 另外, 如果給每個分片配置設定1個副本, 你所需的節點數将加倍. 如果需要為每個分片配置設定2個副本, 則需要3倍的節點數. 更多詳情可以參考基于副本的叢集.
Logstash
不知道你是否有基于日期的索引需求, 并且對索引資料的搜尋場景非常少. 也許這些索引量将達到成百上千, 但每個索引的資料量隻有1GB甚至更小. 對于這種類似場景, 我建議你隻需要為索引配置設定1個分片.
如果使用ES的預設配置(5個分片), 并且使用Logstash按天生成索引, 那麼6個月下來, 你擁有的分片數将達到890個. 再多的話, 你的叢集将難以工作–除非你提供了更多(例如15個或更多)的節點.
想一下, 大部分的Logstash使用者并不會頻繁的進行搜尋, 甚至每分鐘都不會有一次查詢. 是以這種場景, 推薦更為經濟使用的設定. 在這種場景下, 搜尋性能并不是第一要素, 是以并不需要很多副本. 維護單個副本用于資料備援已經足夠. 不過資料被不斷載入到記憶體的比例相應也會變高.
如果你的索引隻需要一個分片, 那麼使用Logstash的配置可以在3節點的叢集中維持運作6個月. 當然你至少需要使用4GB的記憶體, 不過建議使用8GB, 因為在多資料雲平台中使用8GB記憶體會有明顯的網速以及更少的資源共享.
總結
再次聲明, 資料分片也是要有相應資源消耗,并且需要持續投入.
當索引擁有較多分片時, 為了組裝查詢結果, ES必須單獨查詢每個分片(當然并行的方式)并對結果進行合并. 是以高性能IO裝置(SSDs)和多核處理器無疑對分片性能會有巨大幫助. 盡管如此, 你還是要多關心資料本身的大小,更新頻率以及未來的狀态. 在分片配置設定上并沒有絕對的答案, 隻希望你能從本文的讨論中受益.
附加分片處理執行個體
添加分片:
//新增索引的同時添加分片,不使用預設分片,分片的數量
//一般以(節點數*1.5或3倍)來計算,比如有4個節點,分片數量一般是6個到12個,每個分片一般配置設定一個副本
//PUT /testindex
{
"settings" : {
"number_of_shards" : 12,
"number_of_replicas" : 1
}
}
修改副本:
//修改分片的副本數量
//PUT /testindex/_settings
{
"number_of_replicas" : 2
}
要是還有不太明白的地方請留言,評論必回
要是對我的文章感興趣的話,關注一下吧,謝謝!