ElasticSearch集羣出現腦裂

Elasticsearch部分節點不能發現集羣(腦裂)問題處理


現象描述

es版本 1.4.5+centos 6.5

es1,es2,es3三臺es組成一個集羣,集羣狀態正常,

當es1 服務器重啓後,es1不能加到集羣中,自己選舉自己爲master,這就產生了es集羣中所謂的“腦裂”, 把es1的es服務重啓後,es1則能正常發現集羣並加入。
當重啓es2服務器後,es2不能加到集羣中,自己選舉自己爲master,也產生了es集羣中所謂的“腦裂”,當重啓es服務後,還是不能發現集羣。
當重啓es3服務器後,es3能加到集羣中。正常。

分析

三臺es服務器es服務,插件的版本均一樣,配置除了節點名不同也一樣。

查看es服務的啓動日誌發現:
[2015-07-22 16:48:24,628][INFO ][cluster.service          ] [Es_node_10_0_31_2] new_master [Es_node_10_0_31_2][fDJA3kUtTHC7eJuS4h78FA][localhost][inet[/10.0.31.2:9300]]{rack=rack2, master=true}, reason: zen-disco-join (elected_as_master)
服務啓動過程中,由於未能發現集羣,自己選舉自己爲master
導致該問題有可能網絡原因。因爲discovery.zen(es 中一個集羣的服務)超時了還沒有找到集羣則選舉自己爲master。
修改設置 discovery.zen.ping_timeout: 30s,原來10s 重啓es1發現正常了。用同樣的方法修改es2,發現不湊效
修改es2的設置如下:
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping_timeout: 120s
discovery.zen.minimum_master_nodes: 2 #至少要發現集羣可做master的節點數,
client.transport.ping_timeout: 60s
discovery.zen.ping.unicast.hosts: ["10.0.31.2", "10.0.33.2"] 指明集羣中其它可能爲master的節點ip,以防找不到
用該方法後,重啓es2服務器能正常發現集羣,服務正常。


實驗後三臺es服務的配置均加了
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping_timeout: 120s
discovery.zen.minimum_master_nodes: 2
client.transport.ping_timeout: 60s
discovery.zen.ping.unicast.hosts: ["10.0.31.2", "10.0.33.2"] 


只是ip,及超時時間略有不同,es2的超時時間設得最長。
es2的服務雖然正常了,但啓動日誌中會有個異常,如下:
[2015-07-22 21:43:29,012][WARN ][transport.netty          ] [Es_node_10_0_32_2] exception caught on transport layer [[id: 0x5c87285c]], closing connection
java.net.NoRouteToHostException: No route to host
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
at org.elasticsearch.common.netty.channel.socket.nio.NioClientBoss.connect(NioClientBoss.java:152)
at org.elasticsearch.common.netty.channel.socket.nio.NioClientBoss.processSelectedKeys(NioClientBoss.java:105)
at org.elasticsearch.common.netty.channel.socket.nio.NioClientBoss.process(NioClientBoss.java:79)
at org.elasticsearch.common.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318)
at org.elasticsearch.common.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42)
at org.elasticsearch.common.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.elasticsearch.common.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
[2015-07-22 21:43:55,839][WARN ][discovery    
懷疑跟網絡有關係,雖然不影響服務。

總結:

es服務啓動後到發現集羣的時間有點長,如果超時時間設得短則發現不了。這個原因還未知。只是通過修改設置讓他儘可能能找到了集羣了。







什麼是“腦裂”現象?

由於某些節點的失效,部分節點的網絡連接會斷開,並形成一個與原集羣一樣名字的集羣,這種情況稱爲集羣腦裂(split-brain)現象。這個問題非常危險,因爲兩個新形成的集羣會同時索引和修改集羣的數據。


如何避免腦裂問題?

避免腦裂現象,用到的一個參數是:discovery.zen.minimum_master_nodes。這個參數決定了要選舉一個Master需要多少個節點(最少候選節點數)。默認值是1。根據一般經驗這個一般設置成 N/2 + 1,N是集羣中節點的數量,例如一個有3個節點的集羣,minimum_master_nodes 應該被設置成 3/2 + 1 = 2(向下取整)。

用到的另外一個參數是:discovery.zen.ping.timeout,等待ping響應的超時時間,默認值是3秒。如果網絡緩慢或擁塞,建議略微調大這個值。這個參數不僅僅適應更高的網絡延遲,也適用於在一個由於超負荷而響應緩慢的節點的情況。

如果您剛開始使用elasticsearch,建議搭建擁有3個節點的集羣,這種方式可以把discovery.zen.minimum_master_nodes設置成2,這樣就限制了發生腦裂現象的可能,且保持着高度的可用性:如果你設置了副本,在丟失一個節點的情況下,集羣仍可運行。

真的高枕無憂了?

其實問題依然存在,ES的issue空間也在討論一個特例情況《#2488》:即使 minimum_master_nodes 設置了一個正確的值,腦裂也有可能發生。

如何識別這個問題?

在您的集羣裏面儘快識別這個問題非常重要。一個比較容易的方法是定時獲取每一個節點/_nodes響應,它返回了集羣中所有節點的狀態報告,如果兩個節點返回的集羣狀態不一樣,就是一個腦裂情況發生的警示信號。

新增解決方案

對於一個具有全功能的ES節點,必須要有一個活動的Master節點。ES1.4.0.Beta1後,新增了一項沒有Master時阻塞集羣操作設置:discovery.zen.no_master_block

當集羣中沒有活動的Master節點後,該設置指定了哪些操作(read、write)需要被拒絕(即阻塞執行)。有兩個設置值:all和write,默認爲wirte。

這項配置不會對基本api(例如集羣狀態、節點信息和狀態API)產生影響,這些節點在任何節點上執行都不會被阻塞。

總結

腦裂問題依然是一個比較難以解決的問題,最終解決方案也是妥協的結果。這個問題也是分佈式系統都會面臨的問題。一下子想到了前幾天看到的CAP理論,難道只有CP或者AP?
總體感覺ES還很年輕,但因爲它的開箱即用、天生集羣、自動容錯、擴展性強等優點,還是選擇它來做全文檢索。


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