1. 程式人生 > >控制Elasticsearch分片和副本的分配

控制Elasticsearch分片和副本的分配

    ES叢集中索引可能由多個分片構成,並且每個分片可以擁有多個副本。通過將一個單獨的索引分為多個分片,我們可以處理不能在一個單一的伺服器上面執行的大型索引,簡單的說就是索引的大小過大,導致效率問題。不能執行的原因可能是記憶體也可能是儲存。由於每個分片可以有多個副本,通過將副本分配到多個伺服器,可以提高查詢的負載能力。

    為了進行分片和副本的操作,ES需要確定將這些分片和副本放到叢集節點的哪個位置,就是需要確定把每個分片和副本分配到哪臺伺服器/節點上。

一、顯式控制分配


生產情景:
比如生產環境有三個索引分別為 man、woman、katoey
希望達到的效果:
       man索引放置在一些叢集節點上   
       woman索引又單獨放置到叢集的另外一些叢集節點上
       katoey索引希望放置在所有放置man索引和woman索引的叢集節點上
       
這麼做是因為katoey索引比其他兩個索引小很多,因此我們可以將它和其他兩個索引一起分配。
但是基於ES預設演算法的處理方法,我們不能確定分片和副本的存放位置,但是ES允許我們對其做相應的控制!

1、指定節點的引數 epei1.png
    如上圖所示,我們將ES叢集劃分為兩個"空間"。當然你也可以叫做區域,隨便命名。我們將左邊的三臺ES節點伺服器放置到zone_one的空間上面,將右邊的三臺ES節點伺服器放到zone_two的空間上。

配置
為了做到我們需要的效果,我們需要將如下屬性配置到左邊三臺ES叢集節點伺服器的elasticsearch.yml配置檔案中
node.zone: zone_one
    將如下屬性配置到右邊的三臺ES叢集節點伺服器elasticsearch.yml配置檔案中
node.zone: zone_two


索引建立
當所有節點配置檔案屬性配置完成後,我們就可以根據空間名稱,我們就可以建立索引放到指定的空間。

    首先我們執行如下命令,來建立man索引:
# curl -XPOST "http://ESnode:9200/man'
# curl -XPUT "http://ESnode:9200/man/_settings' -d '{
   "index.routing.allocation.include.zone" : "zone_one"
   }'
    第一條命令是建立man索引;第二條命令是傳送到_settings REST端點,用來指定這個索引的其他配置資訊。我們將index.routing.allocation.include.zone屬性設定為zone_one值,就是我們所希望的把man索引放置到node.zone屬性值為zone_one的ES叢集節點伺服器上。


    同樣對woman索引我們做類似操作:
# curl -XPOST "http://ESnode:9200/woman'
# curl -XPUT "http://ESnode:9200/woman/_settings' -d '{
   "index.routing.allocation.include.zone" : "zone_two"
   }'
    不同的是,這次指定woman索引放置在node.zone屬性值為zone_two的ES叢集節點伺服器上

    最後我們需要將katoey索引放置到上面所有的ES叢集節點上面,配置設定命令如下:
# curl -XPOST "http://ESnode:9200/katoey"
# curl -XPUT "http://ESnode:9200/katoey/_settings" -d '{
  "index.routing.allocation.include.zone" : "zone_one,zone_two"
  }'
2、分配時排除節點
跟我們上面操作為索引指定放置節點位置一樣,我們也可以在索引分配的時候排除某些節點。參照之前的例子,我們新建一個people索引,但是不希望people索引放置到zone_one的ES叢集節點伺服器上,我們可以執行如下命令操作:
# curl -XPOST "http://EScode:9200/people"
# curl -XPUT "http://EScode:9200/people/_settings" -d '{
  "index.routing.allocation.exclude.zone" : "zone_one"
  }'
    請注意,在這裡我們使用的是index.routing.allocation.exclude.zone屬性而不是index.routing.allocation.include.zone屬性。

使用IP地址進行分配配置
除了在節點的配置中新增一些特殊的屬性引數外,我們還可以使用IP地址來指定你將分片和副本分配或者不分配到哪些節點上面。為了做到這點,我們應該使用_ip屬性,把zone換成_ip就好了。例如我們希望lucky索引分配到IP地址為10.0.1.110和10.0.1.119的節點上,我們可以執行如下命令設定:
# curl -XPOST "http://ESnode:9200/lucky"
# curl -XPUT "http://ESnode:9200/lucky/_settings" -d '{
  "index.routing.allocation.include._ip" "10.0.1.110,10.0.1.119"
  }'

二、叢集範圍內分配


   除了索引層面指定分配活著排除分配之外(上面我們所做的都是這兩種情況),我們還可以指定叢集中所有索引的分配。例如,我們希望將所有的新索引分配到IP地址為10.0.1.112和10.0.1.114的節點上,我們可以執行如下命令設定:
# curl -XPUT "http://ESnode:9200/_cluster/settings" -d '{
  "transient" : {
   "cluster.routing.allocation.include._ip" "10.0.1.112,10.0.1.114"
   }
  }'
    叢集級別的控制後續還會分享transient和persistent屬性介紹

三、每個節點上分片和副本數量的控制


    除了指定分片和副本的分配,我們還可以對一個索引指定每個節點上的最大分片數量。例如我們希望ops索引在每個節點上只有一個分片,我們可以執行如下命令:
# curl -XPUT "http://ESnode:9200/ops/_settings" -d '{
  "index.routing.allocation.total_shards_per_node" : 1
  }'
    這個屬性也可以直接配置到elasticsearch.ym配置檔案中,或者使用上面命令在活動索引上更新。如果配置不當,導致主分片無法分配的話,叢集就會處於red狀態。

四、手動移動分片和副本


    接下來我們介紹一下節點間手動移動分片和副本。可以使用ElasticSearch提供的_cluster/reroute REST端點進行控制,能夠進行下面操作:
  • 將一個分片從一個節點移動到另外一個節點
  • 取消對分片的分配
  • 強制對分片進行分配

移動分片
假設我們有兩個節點:es_node_one和es_node_two,ElasticSearch在es_node_one節點上分配了ops索引的兩個分片,我們現在希望將第二個分片移動到es_node_two節點上。可以如下操作實現:
# curl -XPOST "http://ESnode:9200/_cluster/reroute' -d  '{
   "commands" : [ {
   "move" : {
   "index" : "ops",
   "shard" : 1,
   "from_node" : "es_node_one",
   "to_node" : "es_node_two"
   }
  }]
  }'
    我們通過move命令的index屬性指定移動哪個索引,通過shard屬性指定移動哪個分片,最終通過from_node屬性指定我們從哪個節點上移動分片,通過to_node屬性指定我們希望將分片移動到哪個節點。

取消分配
如果希望取消一個正在進行的分配過程,我們通過執行cancel命令來指定我們希望取消分配的索引、節點以及分片,如下所示:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{
  "commands" : [ {
  "cancel" : {
  "index" : "ops",
  "shard" : 0,
  "node" : "es_node_one"
  }
  } ]
  }'
    執行上面的命令將會取消es_node_one節上ops索引的第0個分片的分配

分配分片
除了取消和移動分片和副本之外,我們還可以將一個未分配的分片分配到一個指定的節點上。假設ops索引上有一個編號為0的分片尚未分配,並且我們希望ElasticSearch將其分配到es_node_two上,可以執行如下命令操作:
# curl -XPOST "http://ESnode:9200/_cluster/reroute' -d '{
  "commands" : [ {
   "allocate" : {
    "index" : "ops",
    "shard" : 0,
    "node" : "es_node_two"
    }
   } ]
   }'
一次HTTP請求包含多個命令
我們可以在一次HTTP請求中包含多個命令,例如:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{
   "commands" : [
     {"move" : {"index" : "ops", "shard" : 1, "from_node" : "es_node_one", "to_node" : "es_node_two"}},
     {"cancel" : {"index" : "ops", "shard" : 0, "node" : "es_node_one"}}
    ]
 }'