選舉源碼
Ⅰ zookeeper另類
zookeeper是動物管理員的意思。
ZooKeeper是一個分布式的,開放源碼租前慎的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致性服務的軟體,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。
ZooKeeper的基本運轉流程:1、選舉Leader。2、同步數據。3、選舉Leader過程中演算法有很多,但要達到的選舉標準是一致的。4、Leader要具有最高的執行ID,類似root許可權。5、集群中大多數的機器得到響應並接受選出的Leader。
Ⅱ zk源碼閱讀37:ZooKeeperServer源碼分析
前面針對server啟動到選舉leader進行了一個小結,現在進入leader和follower的啟動交互過程,需要先講ZooKeeperServer,
在之前源碼閱讀的25節裡面帶過了一部分,這里詳細講解ZooKeeperServer的源碼
繼承關系如下
本節主要講解內容如下
在源碼閱讀第24節講解了,這里不贅述
是SessionTracker的內部介面
如下圖
除去log,jmx相關部分,源碼如下
ChangeRecord是ZooKeeperServer的內部類,衫畝下面會介紹
ServerStats,ZooKeeperServerListener都在25節的源碼介紹過
這個類或升森並沒有調用,不用管
定義異常
這個數據結構為了促進PrepRequestProcessor以及FinalRequestProcessor的信息共享,講到調用鏈的時候再講。
其中,StatPersisted在源碼閱讀7中講DataNode的時候講過了
描述當前server所處的狀態
這里列舉處兩個底層調用的構造函數
啟動涉及到db的數據載入,這里也有集群和單機兩種,調用順序為
主要是集群的時候,server選完了leader,由leader才能調用數據載入loadData
下面按照單機版startdata函數展開
初始化zkDb完成數據載入
恢復session和數據,單機版啟動或者集群版leader選舉之後調用lead方法時,會調用該方法。
主要完成設置zxid以及把無效的session給kill掉的工作
這里注意,為什麼需要干這件事情,在下面思考中會說
裡面調用了setZxid(不展開)以及killSession函數
清除db中臨時會話記錄,會話跟蹤器也清除記錄
入口是ZooKeeperServer#startup,zkServer都是在上述載入了db的數據之後,調用startup來完成啟動
啟動的入口函數
調用了createSessionTracker等函數,介紹如下
createSessionTracker 完成會話跟蹤器的創建
這里是默認的單機版實現,在集群版不同的角色有不同的實現,主要是參數sid不會傳1,而是配置中的sid
startSessionTracker 啟動會話跟蹤器
設置笑薯伺服器運行狀態,對於ERROR和SHUTDOWN的state,進行對應的操作
在 源碼閱讀25:伺服器異常報警,關閉機制 講過,這里不贅述
安裝請求處理鏈路,是PrepRequestProcessor -> SyncRequestProcessor -> FinalRequestProcessor順序
具體在後面請求處理鏈路再講
兩個函數getServerId和expire
processConnectRequest用於處理client的連接請求,不展開
值得注意的地方是重連的調用
展開如下
重連的核心函數
驗證sessionId和傳遞來的密碼的正確性
根據sessionId生成密碼
在會話跟蹤器SessionTracker中判斷會話是否還有小
完成會話初始化,根據參數valid代表認證通過與否,用來判斷server是接收連接請求,還是發出closeConn的請求,不展開,重要部分如下
除去的get,set,jmx,shutdown相關函數,剩下重要函數如下
部分函數列舉如下
獲取下一個server的zxid,調用方需要確保控制並發順序
上面ZooKeeperServer#expire調用了close函數,介紹如下
該函數用於提交一個 關閉某個sessionId 的請求
這里有兩個函數
之前在源碼21節 會話管理中講解了會話清除,在sessionTracker的記錄是馬上清除的,而DateTree中臨時會話的清除是通過調用鏈一步步來的,也就是說兩個步驟不是同步的,所以如果中間伺服器狀態改變了,會出現不一致的情況
requestsInProcess代表正在處理的請求個數
就是說發出請求時,requestsInProcess+1,最後完成請求時,requestsInProcess-1.涉及到請求處理鏈。
ZooKeeperServer#checkPasswd調用
ZooKeeperServer#generatePasswd
就是sessionId要和sessionId^superSecret生成的第一個隨機數相匹配即可
密碼不是client端設置的,是根據sessionId生成的
ZooKeeperServer#processConnectRequest 裡面調用reopenSession中
在上面已經講了,核心就是
這里還沒有深入看,先存疑
比如思考中提到的loadData為什麼會出現數據不一致,屬於某種異常情況的處理
為什麼不放到另外一個類裡面去
Ⅲ 教你3種Kafka的指定副本作為Leader的實現方式
在實際的運維過程中,我們有時需要指定某個分區副本為Leader,然而Kafka的Leader選舉策略並不支持此功能。本文將介紹三種實現方式,以便滿足這一需求。
在生產環境中,常見需求是修改某個Topic中某分區的Leader。例如,對於topic1-0這個分區,有三個副本[0,1,2]。按照優先副本規則,0號副本將是Leader。然而,如果0號副本性能資源不足、網路不佳或IO壓力大,我們需要切換到壓力較小的副本作為Leader,以提高整體讀寫性能。這就是優先副本概念,即分區中選擇第一位的副本作為Leader,而僅有一個Leader副本提供讀寫服務,其他副本作為備份。
實現這一需求有以下三種方案:
方案一:分區副本重分配(低成本方案)
通常,分區副本重分配涉及三個步驟,重點在於遷移文件內容。在遷移文件中,可以指定topic1-0號分區的副本分配規則為[0,1,2],最終的副本分布為{brokerId-0,brokerId-1,brokerId-2}。根據Leader選舉策略,不論規則如何,都會按照副本分配順序選擇Leader。因此,通過修改副本分配順序(如將「replicas」:[0,1,2]更改為「replicas」:[2,1,0]),執行重分配流程後,Leader將變為第一個位置的副本(即2號副本)。
方案二:手動修改AR順序(高成本方案)
此方案涉及直接修改副本分配順序。在操作前,首先獲取分區的原始數據,然後手動修改數據結構(如「partitions」:{「0」:[0,1,2]}),並刪除Controller的zk節點以觸發重新選舉。這將導致Controller重新載入所有元數據,並重新執行Leader選舉,以應用修改後的順序。
方案三:修改源碼(高級方案推薦)
此方案通過在源代碼中添加邏輯,以在不重新選舉Controller的情況下更新副本分配順序。通常,Controller在新增副本時會更新內存,因此在相關邏輯中添加檢測副本順序變更的代碼,使得一旦順序變更,即可立即更新內存。這樣操作不僅實現了目標需求,而且操作簡單、方便,不會對現有流程產生負面影響。
這三種方案各有優缺點。方案一操作簡便,無需額外開發工作,但需要具備一定技術能力以確保流程正確執行。方案二操作直接,但頻繁的Controller重選舉可能對生產環境產生一定影響。方案三通過修改源碼實現,對系統影響最小,且無額外開銷,推薦在具備一定技術基礎的場景中使用。