一文理解kafka?rebalance負載均衡
介紹
今天主要分享一下 kafka 的 rebalance,在 kafka 中,rebalance 是一個十分重要的概念,很多時候引發(fā)的一些問題可能都是由于 rebalance 引起的,rebalance 也就是再均衡,顧名思義,再均衡就是再次負載均衡,下面會對再均衡進行一個詳細的描述。
負載均衡
說再均衡之前,先說一說負載均衡,負載均衡就是將請求分發(fā)到不同的操作單元上,我們通俗一點來說,就是將請求分發(fā)到不同的服務(wù)器上,以減輕單臺服務(wù)器的壓力,提高吞吐量,負載均衡的方式有很多,下面是 nginx 的負載均衡,當客戶端請求到 nginx 時,nginx 根據(jù)一定的負載均衡算法將請求轉(zhuǎn)發(fā)到不同的服務(wù)器。

請求應(yīng)該落到那一臺機器上,這取決于我們使用的負載均衡策略,負載均衡策略有很多,比如隨機,輪詢,LFU,LRU 等等,這取決于我們的選擇。
rebalance圖示
上面說了負載均衡,其實再均衡也是一樣,再 kafka 中,一個消費者群組怎么去消費一個主題下面的分區(qū),該以什么方式去消費這些分區(qū),是我們值得去考慮的,kafka 提供了一個分區(qū)分配器,他能協(xié)調(diào)哪些消費者應(yīng)該去消費那些分區(qū)。
如下圖所示,一個消費者群組中有兩個消費者,他們各自消費兩個分區(qū)。

此時加入一個消費者,那么就觸發(fā)了再均衡操作,kafka 就會重新進行分配,分配后的樣子可能是下面的這樣,c2 從原來的消費兩個分區(qū) partition-3,partition-4 變?yōu)橹幌M partition-2,partition-4 讓 c3 去消費。

從上面我們看出,kafka 的再均衡其實就是協(xié)調(diào)消費者和分區(qū)的消費對應(yīng)關(guān)系,我們一般是希望消費者和分區(qū)之間的消費關(guān)系盡量做到平衡,別出現(xiàn)某個消費者的負載很高,某個消費者的負載很低,資源不能進行合理的利用。
再均衡產(chǎn)生的條件
再均衡產(chǎn)生的條件就是有消費者加入或者退出,加入和退出的方式有很多,有一些是主動因素,有一些是被動因素,比如我們主動增加一個消費者,這時候就會發(fā)生再均衡,我們停掉一個消費者,那么這時候也發(fā)生再均衡,還有當消費者和 broker 之間由于長時間沒有心跳,那么消費者就被提出,這時候也會發(fā)生再均衡,某個主題下的分區(qū)數(shù)量發(fā)生變化,也會發(fā)生再均衡,還有其他的一些因素,就不展開了,不過我們應(yīng)該盡量避免再均衡。
再均衡期間消費者是讀取不了任何消息,因為這段時間會對分區(qū)進行重新分配,所以 之前消費者與分區(qū)之間的對應(yīng)關(guān)系已經(jīng)不存在,需要進行重新分配,所以會出現(xiàn)短暫不可用現(xiàn)象。
主動因素導(dǎo)致消費者的加入和離開是無法避免的,當數(shù)據(jù)量比較大時,可能需要增加消費者來分擔(dān)壓力,提高吞吐量,所以這時候就需要人為去添加消費者了,這時候發(fā)生再均衡是可預(yù)見的,但是被動導(dǎo)致再均衡就不可預(yù)見了,下面我們從一些參數(shù)和原理來說明一下,盡量避免再均衡。
相關(guān)參數(shù)
在 kafka 中,分區(qū)的分配和分區(qū)分配器PartitionAssignor有關(guān),在底層實現(xiàn)中,是通過協(xié)調(diào)器Coordinator來協(xié)調(diào)消費者和分區(qū)的,分為消費者端的消費者協(xié)調(diào)器ConsumerCoordinator和 Broker 端的組協(xié)調(diào)器GroupCoordinator。
Broker 端參數(shù)
- group.max.session.timeout.ms:消費者會話的最大超時時間。如果消費者在這個時間內(nèi)沒有發(fā)送心跳 GroupCoordinator,那么它會被認為已經(jīng)失效,會被踢出消費組。
- group.min.session.timeout.ms:消費者會話的最小超時時間。如果消費者在這個時間內(nèi)沒有發(fā)送心跳 GroupCoordinator,那么它會被認為已經(jīng)失效,會被踢出消費組。
- group.initial.rebalance.delay.ms:消費者組啟動時,等待多長時間再進行 rebalance。這個參數(shù)可以讓消費者有時間加入消費者組。
consumer 端參數(shù)
- session.timeout.ms:消費者會話的超時時間。如果一個消費者在這個時間內(nèi)沒有發(fā)送心跳到組協(xié)調(diào)器 GroupCoordinator,那么被認為它已經(jīng)失效了,就會將其踢出消費者組。如果這個值設(shè)置過小,那么就會比較消耗資源,但是能夠快速的發(fā)現(xiàn) ConsumerCoordinator 是否還“存活”,然后進行 rebalance,如果設(shè)置過大,那么就會導(dǎo)致長時間沒有收到心跳,可能 ConsumerCoordinator 已經(jīng)“掛了”一段時間,沒有及時進行 rebalance。
- heartbeat.interval.ms:消費者發(fā)送心跳的時間間隔。心跳是消費者與 GroupCoordinator 之間維持會話的機制,如果一個消費者在這個時間間隔內(nèi)沒有發(fā)送心跳,那么 GroupCoordinator 認為它已經(jīng)失效,然后將其踢出,如果這個值設(shè)置過大,那么一個消費者失效時,可能需要等待很長時間才能觸發(fā) rebalance,如果過小那么就會比較消耗資源。
- max.poll.interval.ms:消費者處理消息的最大時間間隔。如果消費者在這個時間內(nèi)沒有消費完消息導(dǎo)致不能 poll 消息,那么它將被認為已經(jīng)失效,將被踢出消費者組,這個值默認為 5 分鐘。
heartbeat.interval.ms 的值一定要比 session.timeout.ms 小,官網(wǎng)建議是 1/3,比如 heartbeat.interval.ms 為 5s,那么 session.timeout.ms 為 15s,這樣的話在這個時間會話內(nèi)能收到三次心跳,不過這兩個的值也要在 Broker 端 group.max.session.timeout.ms(5min)和 group.min.session.timeout.ms(6s)的區(qū)間之間。
分配器
消費者和分區(qū)之間進行分配是由分配器來完成的,當消費者加入和離開時觸發(fā) reabalance,然后會使用分配器從新對分區(qū)和消費者進行分配,kafka 有一個分配器接口ConsumerPartitionAssignor,它的下面有一個抽象類AbstractPartitionAssignor,如果我們需要自定義分配器,那么集成抽象類AbstractPartitionAssignor即可,kafka 默認提供了好幾種分配器,如 RoundRobinAssignor,RangeAssignor,StickyAssignor,CooperativeStickyAssignor,kafka 默認使用 RangeAssignor。
如下,我創(chuàng)建了一個名稱為 musk 的主題,分區(qū)數(shù)為 4,然后創(chuàng)建一個消費者,那么這時因為只有一個消費者,所以四個分區(qū)都劃給了它。

此時我又加入一個消費者,因為加入消費者后會觸發(fā) rebalance,所以這時候就會對分區(qū)重新進行分配,分配后如下,每個消費者劃分了兩個分區(qū)。

對于分配器,kafka 自帶的已經(jīng)能夠滿足我們大多時候的需求,因為我們在使用多個消費者的時候,其實就是為了讓分區(qū)被均分給消費組內(nèi)的消費者,以達到壓力的分擔(dān)。
總結(jié)
從上面我們對 rebalance 進行一些介紹,對 rebalance 產(chǎn)生的原因進行說明,對消費者協(xié)調(diào)器和組協(xié)調(diào)器進行了解,對一些參數(shù)進行詳解,還有通過測試 rebalance 來更加直觀說明 rebalance,rebalance 的觸發(fā)有很多方式,不過我們應(yīng)該盡量去避免它的發(fā)生,對于分區(qū)的修改,應(yīng)該盡量在一開始規(guī)劃好,不要后續(xù)去修改分區(qū),對于其他引起 rebalance 的因素,也應(yīng)該將其概率降到最低。
今天的分享就到這里,感謝你的觀看,我們下期見,如果文中有說得不合理或者不正確的地方,希望你能進行指點,更多關(guān)于kafka rebalance負載均衡的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot 中 thymeleaf 常用的語法完整實例
在 Spring Boot 項目中,Thymeleaf 是一個常用的模板引擎,它提供了豐富的語法來動態(tài)渲染 HTML 頁面,下面給大家介紹springboot 中 thymeleaf 常用的語法完整實例,感興趣的朋友一起看看吧2024-03-03
SpringCloud @RefreshScope注解源碼層面深入分析
@RefreshScope注解能幫助我們做局部的參數(shù)刷新,但侵入性較強,需要開發(fā)階段提前預(yù)知可能的刷新點,并且該注解底層是依賴于cglib進行代理的,所以不要掉入cglib的坑,出現(xiàn)刷了也不更新情況2023-04-04

