## 改變分片的默認分配方式
<div style="text-indent:2em">
<p>在前面的章節中,我們學習了很多關于分片的知識以及與之相關的特性。我們也討論了shard allocation的工作方式(本章的<i>調整集群的分片分配</i>一節)。然而除了默認的分配方式,我們并沒有探討其它的內容。ElasticSearch提供了更多的分片分配策略來構建先進的系統。在本節,我們將更深入地了解在分片分配方面,我們還能做哪些事情。</p>
<h3>ShardAllocator介紹</h3>
<p>ShardAllocator是決定分片安置到哪個節點起主要作用的一個。 當ElasticSearch改變數據在節點上的分配時,比如集群拓撲結構的改變(當節點添加或者移出集群)或者用戶強制集群進行再平衡操作,ElasticSearch中分片就需要重新分配。在ElasticSearch內部,分配器繼承org.elasticsearch.cluster.routing.allocation.allocator.ShardsAllocator接口。ElasticSearch提供了兩種類型的分配器,它們分別是:
<ul>
<li>even\_shard</li>
<li>balanced(默認實現)</li>
</ul>
我們可以通過在elasticsearch.yml文件中或者settings API設置cluster.routing.allocation.type屬性來指定一種分配器的接口實現方式。
</p>
<h4>even_shard 分片分配器</h4>
<p>早在0.90.0版本之前,ElasticSearch就已經支持該分配器。它唯一的作用就是確保每個節點中分片數量都相同(當然,這一點并不總是能得到保證的)。它也不允許把主分片和它的副本存儲在同一個節點上。當需要重新調整分片分布時,如果使用even_shard,只要集群沒有達到完全平衡的狀態或者分片間已經無法再移動了,ElasticSearch就會把一些分片從分片密集節點移動到分片稀疏節點。需要注意的是,這種分配器的應用層面并非索引層面,這意味著只要分片和它的副本分布在不同的節點上即可,它并不關心來自同一個索引的不同分片分配到哪個節點。</p>
<h4>balanced 分片分配器</h4>
<p>該分配器是ElasticSearch 0.90.0版本新引入的,它是基于服務器的重要程度來分配分片,這個重要程度是用戶可以掌控的。與前面提到的even_shard分配器相比,它通過暴露一些參數接口給用戶來實現分片分配過程的調整,這些參數可以用集群的update API實時更新,它們是:
<ul>
<li>cluster.routing.allocation.balance.shard:默認值 0.45</li>
<li>cluster.routing.allocation.balance.index:默認值 0.5</li>
<li>cluster.routing.allocation.balance.primary:默認值 0.05</li>
<li>cluster.routing.allocation.balance.threshold:默認值 1.0</li>
</ul>
上述的參數決定了balanced分配器的行為。從第一個開始一一介紹,首先是基于分片數量的權重因子;其次是基于某個索引所有分片的權重因子;最后是基于主分片的權重因子。我們暫時將threshold參數放在一邊,不作解說。對于某個特定的因子,其權重值越大,表明它越重要,對ElasticSearch在分片重新分配的決策上產生和影響也越大。
</p>
<p>第一個因子用來告訴ElasticSearch每個節點上分配數量相近的分片在用戶心中的重要程度。第二個因子的作用差不多,只是不針對整個集群所有的分片,針對的是整個索引的所有分片。第三個因用來告訴ElasticSearch每個節點上分配數量相同的主分片在用戶心中的重要程度。所以,如果你的集群中,保證每個節點擁有相同數量的主分片這一原則非常重要,那么就應該提升cluster.routing.allocation.balance.primary的權重因子值,同時降低除threshold外其它因子的權重值。</p>
<p>最后,如果所有因子乘以權重后的和如果比設置的threhold值要大,那么該索引的分片就需要進行重新分配了。如果由于某個原因,你希望一些因子不影響分片的分配,那么設置其值為0即可。</p>
<h4>自定義ShardAllocator</h4>
<p>有些情況下,系統內置的分配器可能不適用于用戶的系統部署方案。比如,在在分配分片的過程中要考慮到索引的大小;又比如,一個由不同硬件組件,處理能力不同的CPU,數量不同的內存,容量不同的硬盤組成的超大集群。所有的這些因素都可能導致分布式系統分發數據到各個節點時效率不高。
令人高興的是,在ElasticSearch中能夠實現自己的解決方案,只需要編寫自己的Java類,實現org.elaticsearch.cluster.routing.allocation.allocator.ShardsAllocator接口,然后把全限定類名作為cluster.routing.allocation.type屬性的參數值,配置到集群中即可。
</p>
<h4>決策者(Deciders)</h4>
<p>為了了解分片分配器是如何決定什么時候分片會被移動,又該移向哪個節點,我們需要探究ElaticSearch的內部實現方式,這個內部實現方式稱為決策者(deciders)。它們就像是人的大腦一樣制定分配決策。ElasticSearch允許用戶同時使用多個決策者,所有的決策者在決策時進行投票。它們遵循一致性原則,比如,如果一個決策者反對重新分配一個分片,那么這個分片就不會被移動。如下的決策者是ElasticSearch內置的,它們的決策方式一成不變,除非修改源代碼。讓我們來看看哪些決策者是默認的</p>
<h4>SameShardAllocationDecider</h4>
<p>正如它的名字一樣,這個決策者不允許數據及副本(主分片和分片副本)出現在同一個節點上的狀況出現。原因很明顯:我們不希望備份數據和源數據放在同一個地方。說到這個決策者,我們就不得不提cluster.routing.allocation.same\_shard.host屬性。它控制著ElasticSearch是否關注分片所在的物理機。其默認值為false,因為多個節點可以運行在完全一樣的服務器上,通過運行多虛擬機的方式。當設置它的值為true時,這個決策者就不允許把分片和它的分片副本分配到同一個物理機上。可能看起來有點奇怪,但是想想現在各種虛擬化技術大行其道,在現代社會甚至操作系統都無法決定其運行在哪臺物理機。正因為如此,最好多依靠index.routing.allocation屬性家族的其它設置方式來實現這一功能,相關的內容可以從本章<i>調整集群的分片分配</i>一節中了解。</p>
<h4>ShardsLimitAllocationDecider</h4>
<p>ShardsLimitAllocationDecider確保對于給定的索引,每個節點上分片的數量不會多于設定的數量,該值設定在index.routing.allocation.total\_shards\_per\_node屬性中,可以將該屬性添加在elasticsearh.yml文件中或者用update API實時更改。默認的值是-1,代表節點上分片的數量沒有任何限制。需要注意,如降低該值會導致集群強制進行分片的重新分配,在集群平衡這個過程中引發額外的負載。</p>
<h4>FilterAllocationDecider</h4>
<p>FilterAllocationDecider用于添加分控制片分配的相關屬性,即這些屬性的名字都能匹配\*.routing.allocation.\*正則表達式。關于該決策者的工作方式,可以在本章的adjusting shard allocation一節中找到更多的信息。</p>
<h4>ReplicaAfterPrimaryActiveAllocationDecider</h4>
<p>該決策者使得ElasticSearch只會在主分片分配完畢后才開始分配分片副本。</p>
<h4>ClusterRebalanceAllocationDecider</h4>
<p>ClusterRebalanceAllocationDecider允許集群根據當前的狀態改變集群再平衡的結束時間點。該決策者可以用cluster.routing.allocation.allow_rebalance屬性控制,該屬性有如下三種值可用:
<ul><li>indices\_all\_active:它是默認值,表示只有集群中所有的節點分配完畢,才能認定集群再平衡完成。</li>
<li>indices\_primaries\_active:這個值表示只要所有主分片分配完畢了,就可以認定集群再平衡完成。</li>
<li>always:它表示即使當主分片和分片副本都沒有分配,集群再平衡操作也是允許的。</li></ul>
注意這些值無法在系統運行時更改。
</p>
<h4>ConcurrentRebalanceAllocationDecider</h4>
<p>ConcurrentRebalanceAllocationDecider能夠對分片重定位操作進行限制,通過 cluster.routing.allocation.cluster\_concurrent\_rebalance屬性實現。利用該屬性,我們可以設置給定集群中同時進行分片重定位的分片個數。系統默認值是2,表示集群中最多有兩個分片可以同時移動。如果設置值為-1,就關閉了限制功能,這意味著rebalance的并發數不受限制。</p>
<h4>DisableAllocationDecider</h4>
<p>DisableAllocationDecider是另一種通過調整分片分配方式來滿足業務需求的決策者,我們可以通過更改如下的設置(可以在elasticsearch.yml中靜態修改或者用集群的settings API動態修改):
<ul>
<li>cluster.routing.allocation.disable\_allocation:這個設置項用來停止所有分片的分配。</li>
<li>cluster.routing.allocation.disable\_new\_allocation:這個設置項用來停止所有的新的主分片的分配。</li>
<li>cluster.routing.allocation.disable\_replica\_allocation:這個設置項用來停止所有的分片副本的分配。</li>
</ul>
這些設置項都默認設置為false。當希望完全控制分片什么時候可以進行分配操作時,這些設置項用起來很方便。比如,你希望重新配置一些節點,然后重新啟動使配置生效,那么就可以事先停止分片的reallocations。此外需要記住,盡管上述設置項可以在elasticsearch.yml文件中設置,但是通常用update API會更有意義。
</p>
<h4>AwarenessAllocationDecider</h4>
<p>AwarenessAllocationDecider負責分配感知(awareness)的功能。只要使用了cluster.routing.allocation.awareness.attributes設置項,這個決策者就會生效。更多相關的功能可以參看本章<i>調整集群的分片分配</i>一節的內容。</p>
<h4>ThrottlingAllocationDecider</h4>
<p>ThrottlingAllocationDecider跟前面提到的ConcurrentRebalanceAllocationDecider有些類似。這個決策者可以用來限制allocation過程中產生的系統負載。我們可以通過如下的屬性來操控這個決策者:
<ul><li>cluster.routing.allocation.node\_initial\_primaries\_recoveries:這個屬性的默認值為4,它用來描述單個節點上允許recovery操作的初始主分片數量。</li>
<li>cluster.routing.allocation.node\_concurrent\_recoveries:它的默認值是2,它用來限制單個節點上進行recovery操作的并發數。</li></ul>
</p>
<h4>RebalanceOnlyWhenActiveAllocationDecider</h4>
<p>RebalanceOnlyWhenActiveAllocationDecider用來限制rebalancing過程只了生在所有分片都活躍于同一個分片復制組(主分片和它的分片副本)這一狀態下。
</p>
<h4>DiskThresholdDecider</h4>
<p>DiskThresholdDecider是在ElasticSearch 0.90.4版本引入的功能。它允許用戶基于可用磁盤空間來分配分片。它默認是關閉的。如果想啟動它,則需要把cluster.routing.allocation.disk.threshold_enabled屬性設置為true。這個決策者可以通過配置閾值來控制何時可以將分片分配到該節點,何時ElasticSearch應該把分片分配到其它節點。
</p>
<p>cluster.routing.allocation.disk.watermark.low屬性允許用戶指定一個百分比閾值或者絕對數值來控制何時能夠進行分片分配。比如默認值是0.7,表示當可用磁盤空間低于70%時,新的分片才可以分配到該節點上。</p>
<p> cluster.routing.allocation.disk.watermark.high屬性允許用戶指定一個百分比閾值或者絕對數值來控制何時需要將分片分配到其它的節點。比如默認值是0.85,表示當可用磁盤空間高于85%時,ElasticSearch會重新把該節點的分片分配到其它節點。</p>
<p> cluster.routing.allocation.disk.watermark.low屬性和cluster.routing.allocation.disk.watermark.high屬性都可以指定一個百分比閾值(比如0.7或者0.85)或者絕對數值(比如1000mb)。來控制何時需要將分片分配到其它的節點。比如默認值是0.85,此外,上述屬性都可以通過elasticsearch.yml靜態設置或者用ElasticSearch API動態調整。</p>
</div>
- 前言
- 第1章 認識Elasticsearch
- 認識Apache Lucene
- 熟悉Lucene
- 總體架構
- 分析你的文本
- Lucene查詢語言
- 認識 ElasticSearch
- 基本概念
- ElasticSearch背后的核心理念
- ElasticSearch的工作原理
- 本章小結
- 第2章 強大的用戶查詢語言DSL
- Lucene默認打分算法
- 查詢重寫機制
- 重排序
- 批處理
- 查詢結果的排序
- Update API
- 使用filters優化查詢
- filters和scope在ElasticSearch Faceting模塊的應用
- 本章小結
- 第3章 索引底層控制
- 第4章 探究分布式索引架構
- 選擇恰當的分片數量和分片副本數量
- 路由功能淺談
- 調整集群的分片分配
- 改變分片的默認分配方式
- 查詢的execution preference
- 學以致用
- 本章小結
- 第5章 管理Elasticsearch
- 選擇正確的directory實現類——存儲模塊
- Discovery模塊的配置
- 索引段數據統計
- 理解ElasticSearch的緩存
- 本章小結
- 第6章 應對突發事件
- 第7章 優化用戶體驗
- 第8章 ElasticSearch Java API
- 第9章 開發ElasticSearch插件