「譯」如何防止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

「译」如何防止elasticsearch的脑裂问题

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

「译」如何防止elasticsearch的脑裂问题

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

「译」如何防止elasticsearch的脑裂问题

現在我們的集群在一個不一致的狀態了。打在節點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下每個節點終端響應的定期檢查。這個終端返回一個所有集群節點狀態的短報告。如果有兩個節點報告了不同的集群列表,那麼這是一個產生腦裂狀況的明顯標誌。

「译」如何防止elasticsearch的脑裂问题

歡迎大家留言討論


分享到:


相關文章: