3-kafka服務端之控制器

文章目錄

  • 概述
  • 控制器的選舉與故障恢復
    • 控制器的選舉
    • 故障恢復
  • 優雅關閉
  • 分區leader的選舉

概述

在Kafka集群中會有一個或多個broker,其中有一個broker會被選舉為控制器(Kafka Controler),它負責管理整個集群中所有分區和副本的狀態。當某個分區的leader副本出現故障時,由控制器負責為該分區選舉新的leader副本。當檢測到某個分區的ISR集合發生變化時,由控制器負責通知所有broker更新其元數據信息。當使用kafka-topics.sh腳本為某個topic增加分區數量時,同樣還是由控制器負責分區的重新分配

這里主要講控制器的功能與實現,優雅關閉部分會簡單概括。

控制器的選舉與故障恢復

控制器的選舉

Kafka中的控制器選舉工作依賴于ZooKeeper,成功競選為控制器的broker會在ZooKeeper中創建/controller這個臨時(EPHEMERAL)節點,此臨時節點的內容參考如下:
(version":1,brokerid":0,“timestamp":”1529210278988”)
其中version在目前版本中固定為1,brokeria表示成為控制器的broker的ia編號,timestamp 表示競選成為控制器時的時間戳。

在任意時刻,集群中有且僅有一個控制器。每個broker啟動的時候會去嘗試讀取/controller節點的brokeria的值,如果讀取到brokerid的值不為-1,則表示已經有其他broker節點成功競選為控制器,所以當前broker就會放棄競選:如果ZooKeeper中不存在/controller,或者這個節點中的數據異常,那么就會嘗試去創建/controller節點。當前broker去創建節點的時候,也有可能其他broker同時去嘗試創建這個節點,只有創建成功的那個broker才會成為控制器,而創建失敗的broker競選失敗。每個broker都會在內存中保存當前控制器的brokerid值,這個值可以標識為activeControllerid。

ZooKeeper中還有一個與控制器有關的/controller_epoch節點,這個節點是持久(PERSISTENT)節點,節點中存放的是一個整型的controller_epoch值。controller_epoch用于記錄控制器發生變更的次數,即記錄當前的控制器是第幾代控制器,我們也可以稱之為“控制器的紀元”

controller_epch的初始值為1,即集群中第一個控制器的紀元為1,當控制器發生變更時,每選出一個新的控制器就將該字段值加1。每個和控制器交互的請求都會攜帶controller_epoch這個字段,如果請求的controller_epoch值小于內存中的controller_epoch值,則認為這個請求是向已經過期的控制器所發送的請求,那么這個請求會被認定為無效的請求。如果請求的controller_epoch值大于內存中的controller_epoch值,那么說明已經有新的控制器當選了。由此可見,Kafka通過controller_epoch來保證控制器的唯性,進而保證相關操作的一致性。

具備控制器身份的broker需要比其他普通的broker多一份職責,具體細節如下:

  • 監聽分區相關的變化。為ZooKeeper中的/admin/reassign partitions節點注 冊
    PartitionReassignmentHandler,用來處理分區重分配的動作。為ZooKeeper中的/isr change notification節點注冊IsrChangeNotificetionHandler,用來處理ISR集合變更的動作。為ZooKeeper中中的/admin/preferred-replica-election節點添加
    PreferredReplicaElectionHandler,用來處理優先副本的選舉動作

  • 監聽主題相關的變化。為ZooKeeper中的/brokers/topics節點添加
    TopicChangeHandler,用來處理主題增減的變化;為ZooKeeper中的/admin/ delete
    topics節點添加TopicDeletionHandler,月用來處理刪除主題的動作。

  • 監聽broker相關的變化。為ZooKeeper中的/brokers/ids節點添加BrokerChangeHandler,用來處理broker增減的變化。

  • 從ZooKeeper中讀取獲取當前所有與主題、分區及broker有關的信息并進行相應的管理。對所有主題對應的ZooKeeper中的/brokers/topics/節點添加PartitionModificationsHandler,用來監聽主題中的分區分配變化

  • 啟動并管理分區狀態機和副本狀態機

  • 更新集群的元數據信息

  • 如果參數auto.leader.rebalance.enable設置為true,貝則還會開啟一個名為
    “auto-leader-rebalance-task”的定時任務來負責維護分區的優先副本的均衡

控制器在選舉成功之后會讀取ZooKeeper中各個節點的數據來初始化上下文信息(ControllerContext),并且需要管理這些上下文信息。比如為某個主題增加了若干分區,控制器在負責創建這些分區的同時要更新上下文信息,并且需要將這些變更信息同步到其他普通的broker節點中。不管是監聽器觸發的事件,還是定時任務觸發的事件,或者是其他事件都會讀取或更新控制器中的上下文信息,那么這樣就會涉及多線程間的同步。如果單純使用鎖機制來實現,那么整體的性能會大打折扣。針對這一現象,Kafka的控制器使用單線程基于事件隊列的模型,將每個事件都做一層封裝,然后按照事件發生的先后順序暫存到LinkedBlockingQueue中,最后使用一個專用的線程(ControllerEventThread)按照FIFO(FirstInputFirstOutput,先入先出)的原則順序處理各個事件,這樣不需要鎖機制就可以在多線程間維護線程安全,具體可以參考下圖。
在這里插入圖片描述

在Kafka的早期版本中,并沒有采用KafkaController這樣一個概念來對分區和副本的狀態進行管理,而是依賴于ZooKeeper,每個broker都會在ZooKeeper上為分區和副本注冊大量的監聽器(Watcher)。當分區或副本狀態變化時,會喚醒很多不必要的監聽器,這種嚴重依賴

ZooKeeper的設計會有腦裂羊群效應,以及造成ZooKeeper過載的隱患(舊版的消費者客戶端存在同樣的問題)。在目前的新版本的設計中,只有KafkaController在ZooKeeper上注冊相應的監聽器,其他的broker極少需要再監聽ZooKeeper中的數據變化,這樣省去了很多不必要的麻煩。不過每個broker還是會對/controller節點添加監聽器,以此來監聽此節點的數據變化(ControllerChangeHandler)

故障恢復

當/controller節點的數據發生變化時,每個broker都會更新自身內存中保存的activeControllerlds如果broker在數據變更前是控制器,在數據變更后自身的brokerid值與新的 activeControllerId值不一致,那么就需要“退位”,關閉相應的資源,比如關閉狀態機、注銷相應的監聽器等。有可能控制器由于異常而下線,造成/controller這個臨時節點被自動刪除;也有可能是其他原因將此節點刪除了。

當/controller節點被刪除時,每個broker都會進行選舉,如果broker在節點被刪除前是控制器,那么在選舉前還需要有一個“退位”的動作。如果有特殊需要,則可以手動刪除/controller節點來觸發新一輪的選舉。當然關閉控制器所對應的broker,以及手動向/controller節點寫入新的brokerid的所對應的數據,同樣可以觸發新一輪的選舉。

優雅關閉

Kafka自身提供了一個腳本工具,就是存放在其bin目錄下的kafka-server-stop.sh,這個腳本的內容非常簡單,具體內容如下:

PIDS=S (ps ax I grep -i kafkal.Kafka’ Igrep java l grep -v grep 1 awk print S1)') if[-Z”SPIDS”】;then echo rNokafkaserver to stop' exit 1 else kill -S TERM SPIDS fi

以上腳本直接執行會存在執行不成功,這是因為與Kafka進程有關的輸出信息太長,所以kafka-server-stop.sh腳本在很多情況下并不會奏效。

可以通過修改計算機PAGE_SIZE的大小或者修改腳本內容,這里我們可以直接修改kafka-server-storsh腳本的內容,將其中的第一行命令修改如下:
PIDS=S(ps axIgrep -i 'kafka’i grep javalgrep-v greplawkitprint Si}'
即把“.Kafka”去掉,這樣在絕大多數情況下是可以奏效的。如果有極端情況,即使這樣也不能關閉,那么只需要按照以下兩個步驟就可以優雅地關閉Kafka的服務進程:
(1)獲取Kafka的服務進程號PIDS。可以使用Java中的jps命令或使用Linux系統中的ps命令來查看。
(2)使用kill-STERMSPIDS或kill-15 $PIDS的方式來關閉進程,注意千萬不要使用kill-9的方式。

為什么這樣關閉的方式會是優雅的?Kafka服務入口程序中有一個名為“kafka-shutdown-hock”的關閉鉤子,待Kafka進程捕獲終止信號的時候會執行這個關閉鉤子中的內容,其中除了正常關閉一些必要的資源,還會執行一個控制關閉C ControlledShutdown )的動作。使用ControlledShutdown的方式關閉Kafka有兩個優點:一是可以讓消息完全同步到磁盤上,在服務下次重新上線時不需要進行日志的恢復操作;二是ControllerShutdown在關閉服務之前,會對其上的leader副本進行證移,這樣就可以減少分區的不可用時間。這里更加詳細的分析可以查下其他人的博客。

當然這里是通過腳本進行優雅關閉,你也可以自己通過KafkaAdminClient自己寫一個優雅關閉的接口去執行。這里詳細的設計與實現可以查下其他博客。

分區leader的選舉

分區leader副本的選舉由控制器負責具體實施。當創建分區(創建主題或增加分區都有創建分區的動作)或分區上線(比如分區中原先的leader副本下線,此時分區需要選舉一個新的leader上線來對外提供服務)的時候都需要執行leader的選舉動作,對應的選舉策略為OfflinePartitionLeaderElectionStrategy。這種策略的基本思路是按照AR集合中副本的順序查找第一個存活的副本,并且這個副本在ISR集合中。一個分區的AR集合在分配的時候就被指定并且只要不發生重分配的情況,集合內部副本的順序是保持不變的,而分區的ISR集合中副本的順序可能會改變。注意這里是根據AR的順序而不是ISR的順序進行選舉的

如果ISR集合中沒有可用的副本,那么此時還要再檢查一下所配置的unclean.leader.election.enable參數(默認值為false)。如果這個參數配置為true那么表示允許從非ISR列表中的選舉leader,從AR列表中找到第一個存活的副本即為leader。

那么哪些情況下會出現leader選舉呢?

  • 當分區進行重分配的時候也需要執行leader的選舉動作,對應的選舉策略為ReassignPartitionLeaderElectionStrategy。這個選舉策略的思路比較簡單:從重分配的AR列表中找到第一個存活的副本,且這個副本在日前的ISR列表中。

  • 當發生優先副本的選舉時,直接將優先副本設置為leader即可,AR集合中的第一個副本即為優先副本(PreferredReplicaPartitionLeaderElectionStrategy)

  • 還有一種情況會發生leader的選舉,當某節點被優雅地關閉(也就是執行 ControlledShutdown)時,位于這個節點上的leader副本都會下線,所以與此對應的分區需要執行leader的選舉。與此對應的選舉策略(ControlledShutdownPartitionLeaderElectionStrategy)為:從AR列表中找到第一個存活的副本,且這個副本在日前的ISR列表中,與此同時還要確保這個副本不處于正在被關閉的節點上。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/68149.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/68149.shtml
英文地址,請注明出處:http://en.pswp.cn/web/68149.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

物聯網的三層架構:感知層、網絡層與應用層

物聯網(Internet of Things, IoT)作為現代科技的重要組成部分,正在深刻改變我們的生活和工作方式。它將物理世界與數字世界無縫連接,通過智能設備、傳感器和網絡技術,實現數據的采集、傳輸和應用。物聯網的架構通常分為…

react的antd表單校驗,禁止輸入空格并觸發校驗提示

首先需要用到form組件&#xff0c;在form.item內添加rules屬性&#xff0c;寫正則表達式 <Form.Itemlabel"員工姓名"name"name"rules{[{ required: true, message: 員工姓名 },{ pattern: /^(?!\s*$).$/, message: 不能全是空格 },]}> <Input p…

JavaScript addEventListener事件列表

addEventListener 方法用于向指定元素添加事件監聽器&#xff0c;當該對象觸發指定的事件時&#xff0c;指定的回調函數就會被執行。以下是一些常見的事件類型 鼠標事件 click: 當用戶點擊某個對象時觸發。 dblclick: 當用戶雙擊某個對象時觸發。 contextmenu&#xff1a;當…

IDEA 中集成 Maven,配置環境、創建以及導入項目

目錄 在 IntelliJ IDEA 中集成 Maven 并配置環境 1. 打開 IDEA 設置 2. 定位 Maven 配置選項 3. 配置 Maven 路徑 4. 應用配置 創建 Maven 項目 1. 新建項目 2. 選擇項目類型 3. 配置項目信息 4. 確認 Maven 設置 5. 完成項目創建 導入 Maven 項目 1. 打開導入窗口…

神經網絡常見激活函數 1-sigmoid函數

sigmoid 1 函數求導 sigmoid函數 σ ( x ) 1 1 e ( ? x ) \sigma(x) \frac{1}{1e^{(-x)}} σ(x)1e(?x)1? sigmoid函數求導 d d x σ ( x ) d d x ( 1 1 e ? x ) e ? x ( 1 e ? x ) 2 ( 1 e ? x ) ? 1 ( 1 e ? x ) 2 1 1 e ? x ? 1 ( 1 e ? x ) 2 …

窮舉vs暴搜vs深搜vs回溯vs剪枝系列一>黃金礦工

目錄 決策樹&#xff1a;代碼設計代碼&#xff1a; 決策樹&#xff1a; 代碼設計 代碼&#xff1a; class Solution {boolean[][] vis;int ret,m,n;public int getMaximumGold(int[][] grid) {m grid.length;n grid[0].length;vis new boolean[m][n]; for(int i 0; i <…

rabbitMQ消息轉換器

消息轉換器 Spring的消息發送代碼接收的消息體是一個Object&#xff1a; 而在數據傳輸時&#xff0c;它會把你發送的消息序列化為字節發送給MQ&#xff0c;接收消息的時候&#xff0c;還會把字節反序列化為Java對象。 只不過&#xff0c;默認情況下Spring采用的序列化方式是J…

Java 如何覆蓋第三方 jar 包中的類

目錄 一、需求描述二、示例描述三、操作步驟四、驗證結果五、實現原理 背景&#xff1a; 在我們日常的開發中&#xff0c;經常需要使用第三方的 jar 包&#xff0c;有時候我們會發現第三方的 jar 包中的某一個類有問題&#xff0c;或者我們需要定制化修改其中的邏輯&#xff0c…

CS 與 BS 架構的差異

在數字化的今天&#xff0c;選擇軟件架構模式對系統的性能、維護、安全和成本都有很大影響。BS架構和CS架構是最常見的兩種模式&#xff0c;了解它們的區別和特點對開發人員和企業決策者都很重要。 CS架構最早出現&#xff0c;當時用戶直接從主機獲取數據。隨著客戶端和服務端…

HTML之table表格學習

HTML table使用 thead、tbody、tfoot均可省略&#xff1b; 瀏覽器解析的時候會自動套上tbody tr 行 td 列 th 標題列屬性 colspan 列占用數 rowspan 行占用數 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…

常用抓包工具tcpdump、Fiddler、Charles、Wireshark 和 Sniffmaster 下載地址

抓包大師官網下載地址 Sniff Master Download - Free TCP and HTTPS Proxy Sniffing Tool, Supports IOS Sniffing Fiddler classic官網下載地址 Download Fiddler Web Debugging Tool for Free by Telerik Fiddler Everywhere官網下載地址 The Ultimate Web Debugging Tool …

【PostgreSQL內核學習 —— (WindowAgg(二))】

WindowAgg WindowAggState 結構體窗口聚合行為ExecInitWindowAgg 函數ExecWindowAgg 函數代碼邏輯解釋&#xff1a;計算窗口偏移量代碼邏輯詳細解釋&#xff1a; 代碼邏輯解釋&#xff1a;窗口聚合分區初始化與行推進邏輯代碼邏輯詳細解釋&#xff1a; 代碼邏輯解釋&#xff1a…

區塊鏈項目孵化與包裝設計:從概念到市場的全流程指南

區塊鏈技術的快速發展催生了大量創新項目&#xff0c;但如何將一個區塊鏈項目從概念孵化成市場認可的產品&#xff0c;是許多團隊面臨的挑戰。本文將從孵化策略、包裝設計和市場落地三個維度&#xff0c;為你解析區塊鏈項目成功的關鍵步驟。 一、區塊鏈項目孵化的核心要素 明確…

【React】受控組件和非受控組件

目錄 受控組件非受控組件基于ref獲取DOM元素1、在標簽中使用2、在組件中使用 受控組件 表單元素的狀態&#xff08;值&#xff09;由 React 組件的 state 完全控制。組件的 state 保存了表單元素的值&#xff0c;并且每次用戶輸入時&#xff0c;React 通過事件處理程序來更新 …

C#開發的進銷存管理系統軟件

#### 介紹 進銷存管理系統實現的功能及用途 含模塊銷售管理、采購管理、存貨管理、庫存管理、賬款管理、用戶管理、職員管理七個部分 進銷存管理系統實現以下功能&#xff1a; 1. 庫存管理 2. 應付賬款和應收賬款的統計 3. 對訂單未結數量和采購單未結數量的統計 4. 權限的管理…

高性能 AI 處理器親和性調度算法實現

目錄 題目描述解題思路分析C 語言實現 生成組合的函數主程序實現C 語言代碼使用示例Python 實現 生成組合的函數主程序實現Python 代碼使用示例總結與展望題目描述 某公司研發的高性能 AI 處理器,每臺物理設備 a 包含 8 顆 AI 處理器,編號為 0 - 7。其中,編號 0 - 3 的處理…

快手ip屬地是定位嗎?怎么改

在當今數字化時代&#xff0c;隨著網絡平臺的不斷發展&#xff0c;用戶隱私和數據安全成為了公眾關注的焦點。各大社交媒體平臺紛紛推出的“IP屬地”功能&#xff0c;無疑為網絡環境增添了一抹新的色彩。其中&#xff0c;快手的IP屬地顯示功能尤為引人注目。那么&#xff0c;快…

Git 常用基礎命令詳解:init、add、commit

一、引言 在軟件開發的世界里&#xff0c;版本控制是一項至關重要的技術&#xff0c;它就像是一個時光機器&#xff0c;讓開發者能夠追蹤代碼的每一次變化&#xff0c;輕松回溯到任意歷史版本&#xff0c;同時也為多人協作開發提供了強大的支持。而 Git&#xff0c;作為目前最…

1-kafka服務端之延時操作前傳--時間輪

文章目錄 背景時間輪層級時間輪時間輪降級kafka中的時間輪kafka如何進行時間輪運行 背景 Kafka中存在大量的延時操作&#xff0c;比如延時生產、延時拉取和延時刪除等。Kafka并沒有使用JDK自帶的Timer或DelayQueue來實現延時的功能&#xff0c;而是基于時間輪的概念自定義實現…

從零開始:OpenCV 圖像處理快速入門教程

文章大綱 第1章 OpenCV 概述 1.1 OpenCV的模塊與功能  1.2 OpenCV的發展 1.3 OpenCV的應用 第2章 基本數據類型 2.1 cv::Vec類 2.2 cv&#xff1a;&#xff1a;Point類 2.3 cv&#xff1a;&#xff1a;Rng類 2.4 cv&#xff1a;&#xff1a;Size類 2.5 cv&#xff1a;&…