1. Zookeeper
1.1 初始化啟動Leader選舉
前提:集群中要大于等于2臺機器
- 發(fā)出投票
每個機器給自己投票黄虱,投票結(jié)構(gòu)為(myid,zxid)劣挫,然后將自己的投票發(fā)給其他的機器 - 接收投票
每臺機器接收其他機器的投票痢缎,只比較和自己相同的epoch鸵闪,并且是LOOKING狀態(tài)的機器的投票 - 投票PK
3.1 進行zxid比對梯皿,以zxid較大的投票為準
3.2 如果zxid相同主儡,以myid較大的投票為準
如果自己PK失敗了奖唯,將自己的投票更新為選定的投票,然后重發(fā)出去糜值;
如果自己PK勝利了丰捷,不用更新自己的投票,只需要重新香其他機器發(fā)出投票 - 統(tǒng)計投票
每次投票后寂汇,服務器都會統(tǒng)計所有的投票病往,判斷是否有過半的機器接收到相同投票信息骄瓣,當統(tǒng)計到有此情況時停巷,認為Leader已經(jīng)選出 - 改變服務器狀態(tài)
一旦確定Leader榕栏,每個服務器會更新自己的狀態(tài),如果是Follower扒磁,狀態(tài)變?yōu)镕ollowing;如果是Leader庆揪,狀態(tài)變?yōu)長eading
1.2 崩潰恢復Leader選舉
- 變更狀態(tài)
當Leader掛了后,剩余的非Observer服務器會將自己的服務器狀態(tài)變更為Looking妨托,然后進入Leader選舉流程 - 發(fā)出投票
- 接收投票
- 投票PK
- 統(tǒng)計投票
- 修改服務器狀態(tài)
2. Redis
2.1 哨兵模式哨兵leader選舉
目的:哨兵模式下當發(fā)現(xiàn)Master宕機后,哨兵要對主從進行自動切換内颗,所以哨兵要選舉出來一個leader來執(zhí)行故障轉(zhuǎn)移
原則:
- 每一個監(jiān)視主服務器的哨兵都有資格成為領(lǐng)頭哨兵
- 每一個設(shè)置紀元中領(lǐng)頭哨兵確定后不能改變
- 在一個配置紀元中不管有沒有選出領(lǐng)頭哨兵,配置紀元+1
步驟:
- 哨兵拉票
拉票遵循先到先得原則:最先向目標sentinel發(fā)出設(shè)置要求的源sentinel將成為目標sentinel的局部領(lǐng)頭sentinel医清,目標sentinel后續(xù)收到的設(shè)置要求會被拒絕起暮; - 處理拉票
根據(jù)先到先得的原則,目標sentinel對設(shè)置要求做出響應会烙,返回leader_runid和leader_epoch分別記錄目標sentinel的局部領(lǐng)頭sentinel的runId和配置紀元 - 檢查拉票結(jié)果
源sentinel檢查目標sentinel的響應結(jié)果,如果返回的配置紀元和自己的配置紀元相同纸厉,繼續(xù)取出響應中的leader_runid,如果leader_runid和自己的runid相同颗品,那么說明目標sentinel將自己設(shè)置為局部領(lǐng)頭sentinel - 統(tǒng)計結(jié)果
如果某個sentinel被半數(shù)以上的sentinel設(shè)置為局部sentinel,那么這個sentinel將會成為這次配置紀元的領(lǐng)頭sentinel - 重新選舉
如果在給定時間內(nèi)躯枢,沒有選出領(lǐng)頭的sentinel,那么各個sentinel將過一段時間再進行一次選舉锄蹂,知道選舉出領(lǐng)頭的sentinel
2.2 集群模式leader選舉
背景:
當集群中大多數(shù)主服務節(jié)點將某一個主服務節(jié)點標記為下線,會在集群中廣播主節(jié)點下線當消息敬扛,當一個從節(jié)點發(fā)現(xiàn)自己復制的主節(jié)點標記下線的時候要進行故障轉(zhuǎn)移朝抖,從節(jié)點需要競爭為主節(jié)點
原則:
- 集群中的配置紀元是自增,初始值為0
- 當集群中的某個節(jié)點開始一次故障轉(zhuǎn)移治宣,集群的配置紀元+1
- 對于某一次配置紀元急侥,主節(jié)點只有一次投票權(quán)炼七,第一個向主節(jié)點要求投票的從節(jié)點獲取選票
- 從節(jié)點的資格
4.1 過期的超時不執(zhí)行。data_age = 當前時間點-上次master失聯(lián)的時間點-超時時間陕悬,如果data_age > master到slave的ping間隔時間+超時時間乘以cluster_slave_validity_factor按傅, 則認為過期。cluster_slave_validity_factor是一個配置項唯绍,cluster_slave_validity_factor 設(shè)置的越小越不容易觸發(fā)failover。 - 從節(jié)點拉票的順序
計算出一個延遲執(zhí)行的時間failover_auth_time惜纸, failover_auth_time = 當前時間 + 500ms + random(0-500ms) + 當前slave的rank*1s, rank按已同步的offset計算绝骚,offset同步的越延遲,rank值越大压汪,該slave 就越推遲觸發(fā)failover的時間,以此來避免多個slave同時failover腺阳。只有當前時間到failover_auth_time的時間點才會執(zhí)行failover。
步驟:
- 從節(jié)點拉票
主節(jié)點向集群廣播一條CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST的消息亭引,要求收到這條消息并具備投票權(quán)的主節(jié)點向這個從節(jié)點投票 - 主節(jié)點投票
當一個主節(jié)點收到消息并且有投票權(quán)并且還沒有投給其他從節(jié)點,那么這個主節(jié)點將會給請求的從節(jié)點響應CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK的消息朝氓,表示主節(jié)點支持此從節(jié)點成為新的主節(jié)點 - 統(tǒng)計結(jié)果
每個從節(jié)點都會接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息主届,并根據(jù)消息數(shù)量的多少判斷獲取了多少主節(jié)點的支持待德;假設(shè)集群中有N個投票權(quán)的主節(jié)點,如果有一個從節(jié)點獲取大于等于N/2+1張選票的時候将宪,這個從節(jié)點當選為主節(jié)點 - 重新選舉
如果在一個配置紀元中沒有從節(jié)點獲取足夠多的選票,那么集群進入新的配置紀元印蔗,并再次選擇丑勤,直到選出主節(jié)點為止
Kafka
3.1 Kafka Controller選舉
目的:controller選舉是為了在leader partition掛掉的時候能從ISR中選出一個副本作為新的leader partition,而controller就是執(zhí)行這個故障轉(zhuǎn)移的broker法竞,它和其他的broker沒有什么不一樣
步驟:
- broker啟動的時候,所有的broker都回去zookeeper上注冊controller臨時節(jié)點薛躬,只有一個broker可以注冊成功呆细,這個broker就是controller,follower broker會監(jiān)聽這個臨時節(jié)點
- controller節(jié)點掛掉的時候絮爷,其他的broker會收到通知,重新競爭controller節(jié)點