天天看點

Elasticsearch高可用之叢集腦裂問題詳解

作者:方木H

大家好,我是方木

前言

什麼是腦裂問題

ES在主節點上産生分歧,産生多個主節點,進而使叢集分裂,使得叢集處于異常狀态。這個現象叫做腦裂。腦裂問題其實就是同一個叢集的不同節點對于整個叢集的狀态有不同的了解,導緻操作錯亂,類似于精神分裂

舉個栗子:

下圖是一個有兩個節點的elasticsearch叢集。叢集維護一個單個索引并有一個分片和一個複制節點。節點1在啟動時被選舉為主節點并儲存主分片(在下面的schema裡标記為0P),而節點2儲存複制分片(0R)

Elasticsearch高可用之叢集腦裂問題詳解

這時如果在兩個節點之間的通訊中斷了(網絡問題或隻是因為其中一個節點無響應(例如stop-the-world垃圾回收,es程序被占用,記憶體溢出等))

此時,兩個節點都會覺得對方挂了。

對于節點1來說,他自己就是master,是以不需要做什麼

對于節點2,因為此時叢集就隻有他一個節點,當他選舉一個節點當master,那就隻會是他自己。在elasticsearch叢集,是由主節點來決定将分片平均地分布到節點上的。節點2儲存的是複制分片,但它相信主節點不可用了。是以它會自動提升複制節點為主節點。

Elasticsearch高可用之叢集腦裂問題詳解

那麼此時,整個es叢集就會出現兩個master,打在節點1上的索引請求會将索引資料配置設定在主節點,同時打在節點2的請求會将索引資料放在分片上。

也就是說,如果資料添加到es叢集,就會出現分散到兩個分片中,分片的兩份資料分開了,不做一個全量的重索引很難對它們進行重排序。查詢叢集資料的請求都會成功完成,但是請求傳回的結果是不同的。通路不同的節點,會發現叢集狀态不一樣,可用節點數不一樣,而且結果資料也會不一樣

解決思路

腦裂主要是在master節點挂掉或子節點聯系不上master時出現,那麼我們就要盡可能保證不會出現節點挂掉的情況

1、網絡問題

保證網絡穩定,及時預警,重新開機叢集

2、master節點負載過大

避免master節點因為工作負載過大出現響應中斷進而引發腦裂

可以在jvm.options中增加堆記憶體大小或者修改合适的GC處理器

-Xms4g

-Xmx4g

## G1GC Configuration

# to use G1GC, uncomment the next two lines and update the version on the

# following three lines to your version of the JDK

# 8-13:-XX:-UseConcMarkSweepGC

# 8-13:-XX:-UseCMSInitiatingOccupancyOnly

14-:-XX:+UseG1GC           

也可以對叢集的節點做讀寫分離,master節點專門做叢集master管理,master節點配置

node.master: true

node.data: false           

同時設定一批data節點負責存儲資料和處理請求

node.master: false 

node.data: true           

如果确實還是頂不住,那麼就可以再設定一批client節點隻負責處理使用者請求,實作請求轉發,負載均衡等功能,讓data節點隻負責存儲資料

node.master: false  

node.data: false           

3、優化方法方面

由于elasticsearch6.X和elasticsearch7.X配置出入較大,是以這部分的優化分為兩種

elasticsearch6.X:

discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"]
discovery.zen.ping_timeout:5
discovery.zen.minimum_master_nodes:2           

discoveryzen.ping.multicast.enabled

将data節點的預設的master發現方式由multicast(多點傳播)修改為unicast(單點傳播),使新加入的節點快速确定master位置

discovery.zen.ping.unicast.hosts

提供其他 Elasticsearch 服務節點的單點廣播發現功能。配置叢集中基于主機 TCP 端口的其他 Elasticsearch 服務清單

discovery.zen.ping_timeout

節點等待響應的時間,預設值是3秒,增加這個值,會增加節點等待響應的時間,從一定程度上會減少誤判

discovery.zen.minimum_master_nodes

一個節點需要看到的具有master節點資格的最小數量,然後才能在叢集中做操作。官方的推薦值是(N/2)+1,其中N是具有master資格的節點的數量,設定這個參數後,隻有足夠的master候選節點時,才可以選舉出一個master

elasticsearch7.X:

官網文檔中有這麼一段話

If the cluster is running with a completely default configuration then it will automatically bootstrap a cluster based on the nodes that could be discovered to be running on the same host within a short time after startup. This means that by default it is possible to start up several nodes on a single machine and have them automatically form a cluster which is very useful for development environments and experimentation. However, since nodes may not always successfully discover each other quickly enough this automatic bootstrapping cannot be relied up

譯:如果叢集以完全預設的配置運作,那麼它将在啟動後的短時間内根據可以發現在同一主機上運作的節點自動引導叢集。這意味着預設情況下,可以在一台機器上啟動多個節點并讓它們自動形成一個叢集,這對于開發環境和實驗非常有用。但是,由于節點可能并不總是足夠快地成功發現彼此,是以不能依賴這種自動引導,也不能在生産部署中使用。

是以需要配置如下參數,讓叢集内的節點更快地被發現

cluster.initial_master_nodes: ["node-1", "node-2"]
discovery.seed_hosts: ["host1", "host2"]           

discovery.seed_hosts

在沒有任何網絡配置的情況下,Elasticsearch将直接綁定到可用的環回位址,并掃描本地端口9300到9305,以連接配接到同一伺服器上運作的其他節點,叢集中的節點能夠發現彼此并選擇一個主節點

cluster.initial_master_nodes

使用一組初始的符合主要條件的節點引導叢集

腦裂修複

當elasticsearch叢集重新選舉出一個master節點時,由于之前索引的兩份拷貝已經不一樣了,elasticsearch會認為選出來的master保留的分片是“主拷貝”并将這份拷貝推送給叢集中的其他節點。

這種情況就很容易導緻正确的節點上的資料被選舉出來的master節點的錯誤資料覆寫掉,造成資料丢失。

是以需要

1、給所有資料重新索引

POST _reindex{  
"source": {    "index": "twitter"  }, 
 "dest": {    "index": "new_twitter",   
 "op_type": "create"  }
}           

2、逐個關閉節點并備份資料,分析比對資料是否是最新的。如果是儲存的資料是最新的,啟動它并且讓它被選為主節點。然後就可以啟動叢集的其他節點了

最後

腦裂的問題很難被徹底解決。在elasticsearch的問題清單裡仍然有關于這個的問題, 描述了在一個極端情況下正确設定了minimum_master_nodes的參數時仍然産生了腦裂問題。elasticsearch項目組正在緻力于開發一個選主算法的更好地實作,但如果你已經在運作elasticsearch叢集了那麼你需要知道這個潛在的問題。​

我的微信公衆号:Java架構師進階程式設計

專注分享Java技術幹貨,包括JVM、SpringBoot、SpringCloud、資料庫、架構設計,還有我整理的上百份面試題庫,持續更新中!期待你的關注!

繼續閱讀