27.Elasticsearch的底層模塊深入解析之shard allocation

1、shard allocation的介紹

兩種node:master node,data node

master node的一個很重要的功能,比如說,你現在創建了一個索引,然後這個索引是不是有很多的shard,可能你自己指定了幾個primary shard,每個primary shard還有一些replica shard。master node,其實就是決定哪些shard分配給哪些node,以及什麼時候在node之間移動shard,來讓集羣達到rebalance。對於shard allocation而言,有很多設置,都可以控制這個過程:

(1)cluster level shard allocation,可以在集羣層面來控制shard allocation和rebalance的過程
(2)disk-based shard allocation,es會在shard分配的時候,考慮可用的磁盤空間
(3)shard allocation awareness,控制shard如何在不同的機架上進行分佈
(4)shard allocation filter,可以控制有些node不參與allocation的過程,這樣的話,這些node就可以被安全的下線

2、cluster level shard allocation

shard allocation,就是將shard分配給node的一個過程,這個過程可能會在集羣啓動初始化進行恢復的時候發生,也會發生在replica shard被分配的時候,集羣進行rebalance的時候,或者是有新的node加入,有舊的node被下線的時候。

(1)shard allocation settings

cluster.routing.allocation.enable

all,默認,對所有類型的shard都允許分配
primaries,僅僅允許primary shard被分配
new_primaries,僅僅對新建索引的primary shard允許分配
none,不允許任何shard被分配

但是這個配置對node重啓時本地primary shard的恢復沒有影響,重啓node的時候,如果本地有一個未被分配的primary shard,還是會立即恢復這個primary shard。

cluster.routing.allocation.node_concurrent_incoming_recoveries:在一個node上允許同時恢復多少個shard,這裏的shard recovery過程,指的就是要將某個shard分配給這個node。這個設置的默認值是2.

cluster.routing.allocation.node_concurrent_outgoing_recoveries:一個node上允許同時進行多少個shard recovery outgoing,比如這個node上,有一個primary shard,現在要將replica shard分配給其他的node,那麼就是outgoing shard recovery。默認值也是2.

cluster.routing.allocation.node_concurrent_recoveries:同時設置上面兩個值

cluster.routing.allocation.node_initial_primaries_recoveries:如果replica shard recovery通過網絡傳輸來分配,那麼一個未被分配的primary shard會在node重啓之後使用本地磁盤上的數據,這個過程因爲是使用本地的數據,因此會比較快,默認值是4.

cluster.routing.allocation.same_shard.host:默認值是false,如果設置爲true,那麼就不允許將一個primary shard和replica shard分配到同一個物理機上,也許這個物理機上啓動了多個es實例。

有可能你有一臺超級服務器,32核CPU+128G內存,這個時候的話呢,可能你在這臺機器上啓動兩個es進程,但是默認情況下,有可能一個shard的primary shard被分配到了這臺物理機上的node1,同時這個primary shard的replica shard被分配到了這臺物理機上的node2,此時,primary shard和replica shard就在同一臺物理機上了。

可用性是比較低的,因爲如果這臺物理機掛掉了,比較慘烈了,primary shard和replica shard全部丟失

(2)shard rebalance settings

rebalance,什麼意思,比如說你的集羣,有5臺機器,一共有100個shard,負載均衡的情況下,平均分配一下呢,每個機器上有20個shard。然後此時加入了一臺新機器,6臺機器了,此時就要觸發rebalance操作,重新讓整個集羣負載均衡,100 / 6 = 16~17個shard每臺機器

如果下線一臺機器的話。。。

cluster.routing.rebalance.enable

all,默認,允許對所有類型的shard進行rebalance過程
primaries,僅僅允許對primary shard進行rebalance過程
replicas,僅僅允許對replica shard進行rebalance
none,不允許對任何shard進行rebalance

cluster.routing.allocation.allow_rebalance

always,任何時候都允許rebalance
indices_primaries_active,僅僅只有在所有的primary shard都被分配之後才允許rebalance
indices_all_active,默認,僅僅允許所有的primary shard和replica shard都被分配之後,才能rebalance

cluster.routing.allocation.cluster_concurrent_rebalance

允許控制多少個shard rebalance的操作同時運行,默認是2

(3)shard balance heuristics

cluster.routing.allocation.balance.shard:設置每個node的shard分配的權重因子,默認是0.45f,提高權重因子,就會盡可能讓均勻的shard分配給集羣中的所有node

cluster.routing.allocation.balance.index:定義每個index在一個node上的shard數量因子,默認是0.55f,提高這個參數,就會盡可能讓每個index的shard均勻分配到所有的node上

cluster.routing.allocation.balance.threshold:默認是1.0f,提高這個權重因子會導致集羣對shard balance有更小的侵略性

3、disk-based shard allocation

es在進行shard allocation的時候,會充分考慮每一個node的可用磁盤空間

cluster.routing.allocation.disk.threshold_enabled:默認是true,如果是false會禁用基於disk的考慮

cluster.routing.allocation.disk.watermark.low:控制磁盤使用率的低水位,默認是85%,如果一個節點的磁盤空間使用率已經超過了85%,那麼就不會分配shard給這個node了

cluster.routing.allocation.disk.watermark.high:控制磁盤使用率的高水位,默認是90%,如果一個節點的磁盤空間使用率已經超過90%了,那麼就會將這個node上的部分shard移動走

cluster.info.update.interval:es檢查集羣中每個node的磁盤使用率的時間間隔,默認是30s

cluster.routing.allocation.disk.include_relocations:默認是true,意味着es在計算一個node的磁盤使用率的時候,會考慮正在分配給這個node的shard。

4、shard allocation awareness

(1)機架感知特性

如果在一個物理機上運行多個虛擬機,並且在多個虛擬機中運行了多個es節點,或者在多個機架上,多個機房,都有可能有多個es節點在相同的物理機上,或者在相同的機架上,或者在相同的機房裏,那麼這些節點就可能會因爲物理機,機架,機房的問題,一起崩潰

如果es可以感知到硬件的物理佈局,就可以確保說,priamry shard和replica shard一定是分配到不同的物理機,或者物理機架,或者不同的機房,這樣可以最小化物理機,機架,機房崩潰的風險

shard allocation awareness可以告訴es我們的硬件架構

舉哥例子,如果我們有多個機架,那麼我們啓動一個node的時候,就要告訴這個node它在哪個機架上,可以給它一個rack_id,比如下面的命令:./bin/elasticsearch -Enode.attr.rack_id=rack_one,也可以在elasticsearch.yml中設置這個機架id

cluster.routing.allocation.awareness.attributes: rack_id
node.attr.rack_id=rack_one

上面的兩行設置裏,第一行是設置機架id的屬性名稱,第二行是用那個機架id屬性名稱設置具體的機架id

如果啓動兩個node,都在一個機架上,此時創建一個有5個primary shard和5個replica shard的索引,此時shards會被分配到兩個節點上

如果再啓動兩個node,設置爲另外一個機架,此時es會將shard移動到新的node上,去確保說,不會讓primary shard和其replica shard在同一個機架上。但是如果機架2故障了,爲了恢復集羣,那麼還是會在恢復的時候,將shards全部在機架1上分配的

prefer local shard機制:在執行search或者get請求的時候,如果啓用了shard awareness特性,那麼es會盡量使用local shard來執行請求,也就是在同一個awareness group中的shard來執行請求,也就是說盡量用一個機架或者一個機房中的shard來執行請求,而不要跨機架或者跨機房來執行請求

可以指定多個awareness屬性,比如機架id和機房名稱,類似下面:cluster.routing.allocation.awareness.attributes: rack_id,zone

(2)強制性的感知

如果現在我們有兩個機房,並且有足夠的硬件資源來容納所有的shard,但是可能每個機房的硬件只能容納一半shard,不能容納所有的shard。如果僅僅使用原始的感知特性,如果一個機房故障了,那麼es會將需要恢復的shard全部分配給剩下的一個機房,但是剩下的那個機房的硬件資源並不足以容納所有的shard。

強制感知特性會解決這個問題,因爲這個特性會絕對不允許在一個機房內分配所有的shard

比如說,有一個感知屬性叫做zone,有兩個機房,zone1和zone2,看看下面的配置:

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

那麼此時如果將2個node分配給zone1機房,然後創建一個索引,5個primary shard和5個replica shard,但是此時只會在zone1機房分配5個primary shard,只有我們啓動一批node在zone2機房,纔會分配replica shard

5、shard allocation filtering

shard allocation filtering可以讓我們允許或者不允許某些index的shard分配給一些特殊的節點,典型的用途,就是如果我們要下線一些node,就可以用這個feature禁止shard分配給這些即將下線的node,而且我們還可以將這些即將下線的節點的shard移動到其他節點。

用下面的命令可以下線一個節點,因爲就不允許將shard分配給這個節點了

 

PUT _cluster/settings
{
  "transient" : {
    "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
  }
}

6、node下線時的shard延遲分配

如果從集羣中下線一個節點,master會做下面這些事情:

(1)如果那個節點上有primary shard,那麼master會將那些primary shard在其他節點上的replica shard提升爲primary shard
(2)分配新的replica shard來保證replica數量充足
(3)在剩下的各個node上進行shard rebalance,確保負載均衡

這些操作可以保護集羣不會丟失數據,因爲會對每個shard都複製充足的replica shard

但是這個過程,可能會導致集羣中出現很重的負載,包括網絡負載和磁盤IO負載,如果那個下線的節點只是因爲故障被下線,馬上就會有新的節點來頂替它,那麼這種立即執行的shard recovery過程是不需要的,考慮下面的場景:

(1)某個node跟集羣丟失了網絡連接
(2)master node將那個node上的primary shard對應的其他節點上的replica shard提升爲primary shard
(3)master node分配新的replica shard到其他節點上
(4)每個新的replica shard都會通過網絡傳輸一份primary shard的完整的副本數據
(5)很多shard都被移動到其他的node來讓集羣rebalance
(6)但是幾分鐘以後,那個丟失了網絡連接的node又重新連接到了集羣中
(7)master節點又要再次進行rebalance操作,因爲需要將一些shard分配給那個node

其實如果master node也許只要等待幾分鐘,那麼丟失的那個node自己會回來,丟失的shard也會自動恢復過來,因爲數據都在節點的本地,不需要重新拷貝數據以及網絡傳輸,這個過程是非常快速的

index.unassigned.node_left.delayed_timeout,這個參數可以設置某個節點下線之後,對應的replica shard被重新複製和分配的時間等待期,默認是1m,可以通過下面的命令來修改:

 

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "5m"
  }
}

如果啓用了delayed allocation之後,那麼就會看到下面的場景:

(1)某個node丟失了網絡連接
(2)master將那個node上的一些primary shard對應的其他node上的replica shard提升爲primary shard
(3)master記錄下來一條消息日誌,這個primary shard的replica shard還沒有重新分配和開始,被delayed了,會等待1m
(4)cluster會保持yellow狀態,因爲沒有足夠的replica shard
(5)那個丟失了的node在幾分鐘之後,如果回到了集羣中
(6)缺失的那些replica shard會直接分配給那個node,使用其本地的數據即可

如果某個node確定了肯定不會再回到集羣中,那麼可以通過下面的命令,手動設置一下,直接不等待那個節點回來了

 

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "0"
  }
}

7、索引恢復的優先級

沒有被分配的shard都是按照優先級來分配的,有下面幾個優先級,index.priority,索引的創建日期,索引名稱

 

PUT index_3
{
  "settings": {
    "index.priority": 10
  }
}

8、每個節點的shard數量

cluster.routing.allocation.total_shards_per_node,設置每個節點最多承載的shard數量,默認是無限制的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章