#作者:孫德新
文章目錄
- 一、底層模塊深入解析之shard allocation
- 1、shard allocation的介紹
- 2、cluster level shard allocation介紹
- 3、disk-based shard allocation介紹
- 4、shard allocation awareness
- 5、shard allocation filtering
- 6、node下線時的shard延遲分配
- 7、索引恢復的優先級
- 8、每個節點的shard數量
- 二、底層模塊深入解析之gateway
- 三、底層模塊深入解析之http、network和transport
- 1、http module
- 2、network module
- 3、transport module
一、底層模塊深入解析之shard allocation
本文檔主要涉及運維相關的elasticsearch底層知識,涉及到的很多參數,主要是給初學者、研發人員等提供一些運維、解決問題的思路。
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,例如es集群有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數量,默認是無限制的
二、底層模塊深入解析之gateway
gateway,elasticsearch底層的一個module,是es代碼中的一個模塊。比如搞java,j2ee,java web,可能有用戶管理模塊,訂單管理模塊。。。用戶管理模塊,就是類似一個module,是用來管理用戶信息的。
elasticsearch底層模塊,英文,module,類似用戶管理模塊,訂單管理模塊,gateway module,是用來進行es自身的一些元數據,比如說cluster state,里面包含了一些集群中有哪些node,每個node的信息,負載,資源,索引,每個索引的shard在各個node上分配的一些信息等等。
gateway module,是負責用來存儲每個es節點的cluster state的,node重啟的時候,gateway也會負責將本地磁盤上的cluster state給它讀取出來,放入內存中
local gateway module,用來存儲cluster state,并且在集群重啟的時候共享數據
以下的設置,必須在每個master候選節點上都進行設置:
gateway.expected_nodes:要求必須有多少個節點在集群中,當加入集群中的節點數量達到這個期望數值之后,每個node的local shard的恢復就會理解開始,默認的值是0,也就是不會做任何的等待
gateway.expected_master_nodes:要求必須有多少個master node在集群中,只要有這個數量的master node加入了集群,每個node的local shard recovery就會立即開始,默認的值是0
gateway.expected_data_nodes:要求必須有多少個data node在集群中,只要有這個數量的master node加入了集群,每個node的local shard recovery就會立即開始,默認的值是0
gateway.recover_after_time:如果期望的節點數量沒有達標,那么會等待一定的時間,然后就開始進行shard recovery,默認是等待5m
如果gateway.recover_after_time時間范圍內,指定數量的節點還沒有加入集群,但是只要滿足下面的條件之一就會立即開始恢復
gateway.recover_after_nodes:只要指定數量的節點加入集群,就開始進行恢復
gateway.recover_after_master_nodes:只要指定數量的master節點加入集群,就開始進行恢復
gateway.recover_after_data_nodes:只要指定數量的data node加入集群,就開始恢復
比如說,集群中一共有10個node
gateway.recover_after_nodes: 8
gateway.expected_nodess: 10
gateway.recover_after_time: 10m
要求集群中達到8個節點,接下來,如果等待超過10分鐘那么,就會開始shard recovery,或者是到了8個節點之后,在10分鐘之內,立即到了10個節點,那么也會立即開始shard recovery。
三、底層模塊深入解析之http、network和transport
elasticsearch的這些底層Module,可以以實際使用和運維等等角度去理解這個es。很多功能和特性,參數,實際上都是圍繞著es的一些module展開的。下面系統地梳理一下es的一些底層module。
shard allocation module
gateway module
http module
network module
transport module
其中http,network,transport三個module是最常用的知識和參數
1、http module
HTTP module就是es的http api模塊。http機制是完全異步的,線程不會因為等待響應而陷入阻塞,http異步通信機制的優點就是解決了C10k問題。如果可能的話,盡量使用http keep alive,可以提升性能,而且可以避免客戶端發生http chunking現象。
下面是一些常用的http設置:
http module,主要是用來對外提供請求接口服務的,向es發送一個rest請求,就是走es的http module的,用來處理外部的請求。
http.port,es對外暴露的http api接口的端口號,默認在9200~9300之間選擇一個,優先選擇9200,如果被綁定,則選擇9201,以此類推。
用curl工具發送http請求,那么其實就是走es的http module,還是http.port設置的http module監聽的端口號。默認是http.port就是9200,如果9200被占用,那么就會用9201,以此類推,一直到9300等等。
2、network module
es默認是綁定到localhost的,這只能讓es運行在開發模式下,如果要運行在生產模式下,下面的一些network設置是必須設置的。
network.host:節點綁定的hostname或者ip地址,設置之后,才能進入生產模式下。
主要是對一些網絡上的基礎性的東西進行一個配置
network.host,綁定的是本地的回環地址,127.0.0.1,進入的是development mode,開發模式。如果將network.host,設置為比如192.168.31.187之類的這種hostname或者ip地址之后,進入production mode,生產模式。
3、transport module
transport是用來進行節點間的互相通信的模塊。
transport.tcp.port:用于配置節點間互相通信的端口號,默認是9300,范圍在9300~9400之間,優先綁定9300,如果被占用,則用9301,以此類推。
transport module,es各個node之間,其實也會進行頻繁的通信,比如交換cluster state,reqeust transfer,比如插入一條document,路由之后,應該是到node3的shard2上去處理,但是請求可能發送到的是node1的shard0上,node1就要將這個document index的請求轉發給node3,讓node3上的shard2去處理這個請求
默認transport.tcp.port端口號是9300,如果被占用,那么就會用9301,一直到9400,以此類推。