1. 程式人生 > 其它 >[譯]如何防止elasticsearch的腦裂問題

[譯]如何防止elasticsearch的腦裂問題

本文翻譯自blog.trifork.com的博文
地址是http://blog.trifork.com/2013/10/24/how-to-avoid-the-split-brain-problem-in-elasticsearch/ ,可以複製後在瀏覽器觀看。

我們都遇到過這個 - 在我們開始準備一個elasticsearch叢集的時候,第一個問題就是“叢集需要有多少節點?”。我想大家都知道,這個問題的答案取決於很多因素,例如期望的負載,資料大小,硬體等。這篇博文不會深入解釋如何調整叢集大小的細節,而是去關注另一個同樣重要的事情 - 如何避免腦裂問題。

什麼是腦裂?

讓我們看一個有兩個節點的elasticsearch叢集的簡單情況。叢集維護一個單個索引並有一個分片和一個複製節點。節點1在啟動時被選舉為主節點並儲存主分片(在下面的schema裡標記為0P

),而節點2儲存複製分片(0R

現在,如果在兩個節點之間的通訊中斷了,會發生什麼?由於網路問題或只是因為其中一個節點無響應(例如stop-the-world垃圾回收),這是有可能發生的。

兩個節點都相信對方已經掛了。節點1不需要做什麼,因為它本來就被選舉為主節點。但是節點2會自動選舉它自己為主節點,因為它相信叢集的一部分沒有主節點了。在elasticsearch叢集,是有主節點來決定將分片平均的分佈到節點上的。節點2儲存的是複製分片,但它相信主節點不可用了。所以它會自動提升複製節點為主節點。

現在我們的叢集在一個不一致的狀態了。打在節點1上的索引請求會將索引資料分配在主節點,同時打在節點2的請求會將索引資料放在分片上。在這種情況下,分片的兩份資料分開了,如果不做一個全量的重索引很難對它們進行重排序。在更壞的情況下,一個對叢集無感知的索引客戶端(例如,使用REST介面的),這個問題非常透明難以發現,無論哪個節點被命中索引請求仍然在每次都會成功完成。問題只有在搜尋資料時才會被隱約發現:取決於搜尋請求命中了哪個節點,結果都會不同。

如何避免腦裂問題

elasticsearch的預設配置很好。但是elasticsearch專案組不可能知道你的特定場景裡的所有細節。這就是為什麼某些配置引數需要改成適合你的需求的原因。這篇博文裡所有提到的引數都可以在你elasticsearch安裝地址的config目錄中的elasticsearch.yml中更改。

要預防腦裂問題,我們需要看的一個引數就是discovery.zen.minimum_master_nodes。這個引數決定了在選主過程中需要 有多少個節點通訊。預設配置是1.一個基本的原則是這裡需要設定成 N/2+1, N是急群中節點的數量。 例如在一個三節點的叢集中, minimum_master_nodes應該被設為 3/2 + 1 = 2(四捨五入)。

讓我們想象下之前的情況下如果我們把discovery.zen.minimum_master_nodes設定成 2(2/2 + 1)。當兩個節點的通訊失敗了,節點1會失去它的主狀態,同時節點2也不會被選舉為主。沒有一個節點會接受索引或搜尋的請求,讓所有的客戶端馬上發現這個問題。而且沒有一個分片會處於不一致的狀態。

我們可以調的另一個引數是discovery.zen.ping.timeout。它的預設值是3秒並且它用來決定一個節點在假設叢集中的另一個節點響應失敗的情況時等待多久。在一個慢速網路中將這個值調的大一點是個不錯的主意。這個引數不止適用於高網路延遲,還能在一個節點超載響應很慢時起作用。

兩節點叢集?

如果你覺得(或直覺上)在一個兩節點的叢集中把minimum_master_nodes引數設成2是錯的,那就對了。在這種情況下如果一個節點掛了,那整個叢集就都掛了。儘管這杜絕了腦裂的可能性,但這使elasticsearch另一個好特性 - 用複製分片來構建高可用性 失效了。

如果你剛開始使用elasticsearch,建議配置一個3節點叢集。這樣你可以設定minimum_master_nodes為2,減少了腦裂的可能性,但仍然保持了高可用的優點:你可以承受一個節點失效但叢集還是正常執行的。

但如果已經運行了一個兩節點elasticsearch叢集怎麼辦?可以選擇為了保持高可用而忍受腦裂的可能性,或者選擇為了防止腦裂而選擇高可用性。為了避免這種妥協,最好的選擇是給叢集新增一個節點。這聽起來很極端,但並不是。對於每一個elasticsearch節點你可以設定node.data引數來選擇這個節點是否需要儲存資料。預設值是“true”,意思是預設每個elasticsearch節點同時也會作為一個數據節點。

在一個兩節點叢集,你可以新增一個新節點並把node.data引數設定為“false”。這樣這個節點不會儲存任何分片,但它仍然可以被選為主(預設行為)。因為這個節點是一個無資料節點,所以它可以放在一臺便宜伺服器上。現在你就有了一個三節點的叢集,可以安全的把minimum_master_nodes設定為2,避免腦裂而且仍然可以丟失一個節點並且不會丟失資料。

結論

腦裂問題很難被徹底解決。在elasticsearch的問題列表裡仍然有關於這個的問題, 描述了在一個極端情況下正確設定了minimum_master_nodes的引數時仍然產生了腦裂問題。 elasticsearch專案組正在致力於開發一個選主演算法的更好的實現,但如果你已經在執行elasticsearch叢集了那麼你需要知道這個潛在的問題。

如何儘快發現這個很重要。一個比較簡單的檢測問題的方式是,做一個對/_nodes下每個節點終端響應的定期檢查。這個終端返回一個所有叢集節點狀態的短報告。如果有兩個節點報告了不同的叢集列表,那麼這是一個產生腦裂狀況的明顯標誌。