分布式基礎 誰來當老大(1)

2022-02-04 04:06:11 字數 3808 閱讀 8645

分布式系統中有的各個節點的地位是均等的,有的是有 leader 和 flower。這種區分 leader 的集群更好管理些。這樣在寫操作的時候都交給 leader 去處理,然後由 leader 再將資料同步給各個 flower 上的副本。如果同時對多個分布式節點寫資料,勢必不好進行資料同步。讀的時候可以從 flower 上讀取,也可以從 leader 上讀取,分散下系統壓力。有些分布式系統,leader 還負責一些元資料的管理。所以對於這種分布式系統來說 leader 選舉很重要。

這就涉及到如何在集群初始化或者主掛掉之後,或有新節點加入到集群中,會重新選主的問題。有的演算法根據 id 的大小來選舉 leader,有的演算法採用多數派投票演算法,誰的票數多誰當老大。本篇主要聊下簡單的 bully 演算法,即根據 id 來選舉 leader 的演算法。

bully 演算法基本思想就是誰的 id 最大或最小誰來當老大(一般選擇 id 大的)。節點的角色分為兩種主節點和普通節點。在集群開始啟動的時候,或者主掛了之後會發起選舉,節點間通過發訊息來進行選舉,訊息分為三種:

拿現實生活舉例,比如你們部門的領導不在了,調走了,然後大家都彼此相互了解(節點儲存集群中所有節點的資訊),每個人都對其他資歷比自己老的(id 比自己 id 大的)發起選舉訊息,意思是我選你當 leader;如果自己資歷最老對其他人說,我當老大(發起 victory 訊息);如果不是,當它傳送選舉訊息有返回後,就知道有比自己資歷還老的存在,那麼自己選舉就失敗了;如果過一段時間,沒有收到選舉訊息的回覆,那說明我最大,我就可以對其他節點傳送 victory 訊息,宣告我當 leader 了。

以集群中 leader 節點掛掉來說明具體過程:

圖1 集群中leader 節點5掛掉

1) leader 掛掉後,1 節點通過心跳探測訊息發現,將發起新的選舉,節點 1 向比它大的所有節點發起選舉訊息,也需要向節點 5 傳送選舉訊息,因為節點 5 這時候可能已經活了,所以再發一次。

節點 2,3,4 回覆 alive 給 1 節點,5 節點由於網路故障回覆 alive 訊息丟失。

1 有收到 alive 的回覆後,說明有比它資格老的還活著,老老實實等待選舉完成的 victory 訊息吧。

圖2節點2傳送選舉訊息

2)節點 2 也通過心跳探測發現 leader 5 掛了,這時候,通過向所有節點 id 比它大的 3,4,5 傳送選舉訊息,這時候,3 和 4 都回覆 alive 訊息給 2,2 就知道自己不能當 leader,老老實實等待吧;同樣道理節點 3 也會向節點 4 和節點 5 傳送選舉訊息,同樣收到節點 4 回覆的 alive 訊息後就進入等待狀態。

節點4發起選舉訊息

3)節點 4 也探測到超時後,發起選舉訊息給節點 5,接收選舉回覆訊息超時,這時候由於節點 4 沒有收到任何選舉訊息的恢復訊息,那就認為自己是 leader,向其他所有節點傳送 victory 訊息,宣布主權,從而完成這輪選舉。

早期的 mangodb 採用 bully 演算法,bully 演算法又叫欺負演算法,是因為直接粗暴的選擇最大 id(這個 id 也可以用時間戳,誰的大說明誰新)作為 leader。

bully 演算法優點:演算法實現比較簡單,直接通過比較 id 就可以抉擇出誰是 leader,由於簡單,所以效能比較好,實現起來也比較容易;

bully 演算法缺點: 每個節點都要儲存全部其他節點的資訊,儲存的元資料量大了點,我覺得這個不是缺點,就算成千台機器,儲存的資料也不會很多;還有個缺點就是如果集群的最大 id 機器不穩定,那麼頻繁掉線上線,可能會造成頻繁選舉,選舉的時候沒有 leader 就沒有辦法進行一些寫操作,從而造成集群不穩定。

演算法雖然簡單,實踐中還需要考慮不少問題。

比如說我們如何決定一輪選舉,像上文那種,如果選舉結束了,那麼節點 5 回覆給節點 3 的訊息現在才過來,那麼節點 3 如何處理這個訊息,我的理解是可以設定邏輯時鐘,標識每一輪的選舉,選舉成功後,邏輯時鐘加 1,這種延遲到來的訊息,由於是上一輪選舉的所以可以扔掉。

這裡還有問題要考慮,這個邏輯時鐘要保障每個節點都同步的,發起選舉的節點要判斷是自己判斷出來 leader 有問題選舉的嗎,如果是那麼就它在老時鐘上加一,如果其他節點同時也發現 leader 掛掉了,也會加 1 那豈不是就亂了,可能性比較小存在這種可能,我還沒考慮好這種問題怎麼解決?

我們知道 leader 節點 5 本身需要處理的事情比較多,自然壓力比較大,那麼如果乙個節點 4 判斷它死掉了發起了選舉,結果節點 5 又活過來了,這又要發起一次選舉,來回折騰,也許是節點 4 本身的網路有問題那?

對於這個問題 es 中是這樣解決的,當節點 4 判斷節點 5 死掉後,不立刻發起選舉,而是詢問節點 1,2,3,如果他們判斷也死掉了,才發起選舉;如果它們判斷沒節點 5 沒死掉,則不能發起選舉。

突然想到可以在這個判斷的時候廣播新一輪的可能序列號,如果 1,2,3 判斷節點 5 死掉了,就用節點 4 的序列號作為選舉的時鐘,選舉的時鐘只有乙個。 如果 4 和 3 同時判斷 5 死掉了,同時先 2 發起詢問,則 2 回覆,無論用誰的序列號都是一樣的,似乎可行。

還有個問題,就是如何防止腦裂,比如還是剛才的例子,對於節點 5 來說,它收到別人的選舉訊息後,也會發起選舉,由於它的 id 最大,那麼它自己會傳送選舉成功訊息給 1,2,3,4 節點,由於網路問題,其他節點並沒有收到這個訊息,4 節點法給它的選舉成功訊息也可能沒有收到,那麼它也自認為自己是老大,這樣整個集群中就有二個 leader 了,如果有客戶端連線 5 節點,發起寫操作,它當自己為 leader 話就自己先處理了,不會**。

對於這個問題,我的解決思路是集合集群中的存活節點數要包含集群中節點量一半,如果集群中的存活的節點數量沒有達到一半,則把自己變成 dead 狀態。比如上面描述的節點 5,當客戶端傳送請求給節點 5 的時候,直接回覆節點死掉,客戶端可以重試其他節點,從而把寫請求發到真正的 leader 節點 4 上,從而防止了腦裂。

網上分布式bully演算法選舉實現:[

我大概看了下,它的**,發現大概實現了這個演算法,使用起來可能還有些問題,比如:

private void electleader() throws exception else 

}}else }}

}}

大概說明了選舉的流程,當時,沒有說如果傳送給比它大的選舉訊息超時後如何處理,我上述描述的情況就無法選舉出四節點作為 leader 了,或者再傳送比它大的節點的時候判斷節點是否存活,如果不存活,則不算入集群,不過這又會造成誤判的情況,他**裡面並沒有這麼做:

public listlargernodes(final metadata metadata) 

}return largernodes;

}

總體來說,還是很有參考價值的,有空自己實現乙個應該挺有意思的。

臨江仙 寒柳

[清] [納蘭性德]

飛絮飛花何處是

層冰積雪摧殘

疏疏一樹五更寒

愛他明月好

憔悴也相關

最是繁絲搖落後

轉教人憶春山

湔裙夢斷續應難

西風多少恨

吹不散眉彎

分布式基礎

小小吐槽一番 因為一直在學習分布式架構,所以分布式架構部落格一直到現在才開始寫,在寫的過程也等於是在複習了!廢話不多說,進入正題 什麼是分布式?1,任務分解 2,節點通訊 分布式和集群的關係?分布式 乙個業務拆分成多個子系統,部署在不同的伺服器上 集群 同乙個業務,部署在多個伺服器上 1.訪問量 t...

分布式基礎概念

1.分布式是指將不同的業務分布在不同的地方 2.集群是指將幾台伺服器集中在一起,實現同一業務 3.節點是集群中的乙個伺服器 在分布式系統中,各個服務處於不同的主機,但是服務之間不可避免的需要相互呼叫,我們成為遠端呼叫 springcloud中使用http json的方式完成遠端呼叫 為了使每一台伺服...

分布式隨筆1 分布式概述

分布式,好寬泛的話題,來來咱扯兩句。你乙個人再強壯,也扛不了100袋大公尺,單機的資源也很有限,大 的大資料量 高併發以及各種業務需求 童鞋們的web應用,伺服器 rdb mq 服務 快取以及各類基礎設施,更別說還有安全 大資料方面的需求 於是,我們常見的面向服務的dubbo springcloud...