1. 程式人生 > >記一次 Kafka 叢集線上擴容

記一次 Kafka 叢集線上擴容

前段時間收到某個 Kafka 叢集的生產客戶端反饋傳送訊息耗時很高,於是花了一段時間去排查這個問題,最後該叢集進行擴容,由於某些主題的當前資料量實在太大,在對這些主題遷移過程中話費了很長一段時間,不過這個過程還算順利,因為在遷移過程中也做足了各方面的調研,包括分割槽重平衡過程中對客戶端的影響,以及對整個叢集的效能影響等,特此將這個過程總結一下,也為雙十一打了一劑強心劑。

排查問題與分析

接到使用者的反饋後,我用指令碼測試了一遍,並對比了另外一個正常的 Kafka 叢集,發現耗時確實很高,接下來

經過排查,發現有客戶端在頻繁斷開與叢集節點的連線,發現日誌頻繁列印如下內容:

Attempting to send response via channel for which there is no open connection, connection id xxx(kafka.network.Processor)

定位到原始碼位置:

kafka.network.Processor#sendResponse:

看原始碼註釋,是遠端連線關閉了或者空閒時間太長了的意思,找到具體客戶端負責人,經詢問後,這是大資料 Spark 叢集的節點。

從以上日誌看出,Spark 叢集的某個消費組 OrderDeliveryTypeCnt,竟然發生了近 4 萬次重平衡操作,這顯然就是一個不正常的事件,Kafka 消費組發生重平衡的條件有以下幾個:

  1. 消費組成員發生變更,有新消費者加入或者離開,或者有消費者崩潰;
  2. 消費組訂閱的主題數量發生變更;
  3. 消費組訂閱的分割槽數發生變更。

很顯然第 2、3 點都沒有發生,那麼可以斷定,這是 Spark叢集節點頻繁斷開與kafka的連線導致消費組成員發生變更,導致消費組發生重平滑。

那為什麼 Spark 叢集會產生頻繁斷開重連呢?

檢視 Spark 叢集用的 Kafka 版本還是 0.10.1.1 版本,而 Kafka 叢集的版本為 2.2.1,一開始以為是版本相容問題,接著資料智慧部的小夥伴將 Spark 叢集連線到某個版本為 0.11.1.1 的 Kafka 叢集,使用 8 個 Spark 任務消費進行消費,同樣發現了連線斷開的問題。說明此問題是由於 Spark 內部消費 Kafka 機制導致的,和 kafka 版本關係不大。

經過幾番跟大資料的人員討論,這個頻繁重平衡貌似是 Spark 2.3 版本內部機制導致的,Spark 2.4 版本沒有這個問題存在。

由於這個頻繁斷開重連,並不是開發人員開發過程中導致的,考慮到雙十一臨近,不能貿然升級改動專案,那麼現在最好的方案就是對叢集進行水平擴充套件,增加叢集的負載能力,並對專門的主題進行分割槽重分配。

分割槽重分配方案的分析

目前叢集一共有 6 個節點,擴容以 50% 為基準,那麼需要在準備 3 個節點,在運維準備好機器並且將其加入到叢集中後,接下來就要準備對主題進行分割槽重分配的策略檔案了。

在執行分割槽重分配的過程中,對叢集的影響主要有兩點:

  1. 分割槽重分配主要是對主題資料進行 Broker 間的遷移,因此會佔用叢集的頻寬資源;
  2. 分割槽重分配會改變分割槽 Leader 所在的 Broker,因此會影響客戶端。

針對以上兩點,第 1 點可以在晚間進行(太苦逼了,記得有個主題資料遷移進行了將近5小時),針對第二點,我想到了兩個方案:

  1. 整個分配方案分成兩個步驟:1)手動生成分配方案,對原有的分割槽 Leader 位置不改變,只對副本進行分割槽重分配;2)等待資料遷移完成後,再手動更改分割槽分配方案,目的是均衡 Leader。
  2. 直接用 Kafka 提供的 API 生成 分割槽重分配方案,直接執行分割槽重分配。

第一個方案理論上是對客戶端影響最小的,把整個分配方案分成了兩個步驟,也就是將對叢集的頻寬資源與客戶端的影響分開了,對過程可控性更高了,但問題來了,叢集中的某些主題,有 64 個分割槽,副本因子為 3,副本一共有 192 個,你需要保持原有分割槽 Leader 位置不變的情況下,去手動均衡其餘副本,這個考驗難度真的太大了,稍微有一點偏差,就會造成副本不均衡。

因此我特意去看了分割槽重分配的原始碼,並對其過程進行了進一步分析,發現分配重分配的步驟是將分割槽原有的副本與新分配的副本的集合,組成一個分割槽副本集合,新分配的副本努力追上 Leader 的位移,最終加入 ISR,待全部副本都加入 ISR 之後,就會進行分割槽 Leader 選舉,選舉完後就會將原有的副本刪除,具體細節我會單獨寫一篇文章。

根據以上重分配的步驟,意味著在資料進行過程中不會發生客戶端阻塞,因為期間 Leader 並沒有發生變更,在資料遷移完成進行 Leader 選舉時才會,但影響不大,針對這點影響我特意用指令碼測試了一下:

可以發現,在傳送過程中,如果 Leader 發生了變更,生產者會及時拉取最新的元資料,並重新進行訊息傳送。

針對以上的分析與測試,我們決定採取第二種方案,具體步驟如下:

  1. 對每個主題生成分配分割槽分配策略:執行時間段(10:00-17:00),並對分配策略進行檢查,並儲存執行的 topic1_partition_reassignment.json 檔案,並把原來的方案儲存到topic1_partition_reassignment_rollback.json 檔案中,以備後續的 rollback 操作;
  2. 執行分配策略:執行時間段(00:30-02:30),準備好的 topic1_partition_reassignment.json 檔案,執行完再驗證並檢視副本分配情況,每執行一個分配策略都要檢視 ISR 收縮擴張狀況、訊息流轉狀況,確定沒問題後再執行下一個分配策略;
  3. 由於叢集 broker 端的引數 auto.leader.rebalance.enable=true,因此會自動執行 Preferred Leader 選舉,預設時間間隔為 300 秒,期間需要觀察 Preferred Leader 選舉狀況。

分割槽重分配

對於新增的 Broker,Kafka 是不會自動地分配已有主題的負載,即不會將主題的分割槽分配到新增的 Broker,但我們可以通過 Kafka 提供的 API 對主題分割槽進行重分配操作,具體操作如下:

  1. 生成需要執行分割槽重分配的主題列表 json 檔案:
echo '{"version":1,"topics":[{"topic":"sjzn_spark_binlog_order_topic"}]}' > sjzn_spark_binlog_order_topic.json
  1. 生成主題的分配方案:
bin/kafka-reassign-partitions.sh  --zookeeper  --zookeeper xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181 --topics-to-move-json-file sjzn_spark_binlog_order_topic.json --broker-list "0,1,2,3,4,5,6,7,8" --generate

由於主題的有64個分割槽,每個分割槽3個副本,生成的分配資料還是挺大的,這裡就不一一貼出來了

  1. 將分配方案儲存到一個 json 檔案中:
echo '{"version":1,"partitions":[{"topic":"sjzn_spark_binlog_order_topic","partition":59,"replicas":[4,8,0],"log_dirs":["any","any","any"]} ......' > sjzn_spark_binlog_order_topic_reassignment.json
  1. 執行分割槽重分配:
 bin/kafka-reassign-partitions.sh   --zookeeper xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181 --reassignment-json-file sjzn_spark_binlog_order_topic_reassignment.json --execute
  1. 驗證分割槽重分配是否執行成功:
bin/kafka-reassign-partitions.sh  --zookeeper xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181,xxx.xxx.xx.xxx:2181 --reassignment-json-file sjzn_spark_order_unique_topic_resign.json --verify

由於該主題存在的資料量特別大,整個重分配過程需要維持了好幾個小時:

在它進行資料遷移過程中,我特意去 kafka-manage 控制檯觀察了各分割槽資料的變動情況:

從控制檯可看出,各分割槽的副本數目基本都增加了,這也印證了分割槽當前的副本數等於原有的副本加上新分配的副本的集合,新分配的副本集合目前還沒追上 Leader 的位移,因此沒有加入 ISR 列表。

有沒有注意到一點,此時各分割槽的 Leader 都不在 Preferred Leader 中,因此後續等待新分配的副本追上 ISR 後,會進行新一輪的 Preferred Leader 選舉,選舉的細節實現我會單獨寫一篇文章去分析,敬請期待。

過一段時間後,發現位移已經改變了:

從這點也印證了在分割槽重分配過程中,只要 Leader 沒有發生變更,客戶端是可以持續傳送訊息給分割槽 Leader 的。

從上圖可看出,新分配的副本追上 Leader 的位移後,就會加入 ISR 列表中。

現在去看看叢集頻寬負載情況:

從上圖中可看出,在遷移過程中,新分配的副本不斷地從 Leader 拉取資料,佔用了叢集頻寬。

主題各分割槽重分配完成後的副本情況:

從以上圖中可看出,各分割槽的新分配的副本都已經全部在 ISR 列表中了,並且將舊分配的副本刪除,經過 Preferred Leader 選舉之後,各分割槽新分配副本的 Preferred Leader 大多數成為了該分割槽 leader。

更多精彩文章請關注作者維護的公眾號「後端進階」,這是一個專注後端相關技術的公眾號。
關注公眾號並回復「後端」免費領取後端相關電子書籍。
歡迎分享,轉載請保留出處。

相關推薦

Kafka 叢集線上擴容

前段時間收到某個 Kafka 叢集的生產客戶端反饋傳送訊息耗時很高,於是花了一段時間去排查這個問題,最後該叢集進行擴容,由於某些主題的當前資料量實在太大,在對這些主題遷移過程中話費了很長一段時間,不過這個過程還算順利,因為在遷移過程中也做足了各方面的調研,包括分割槽重平衡過程中對客戶端的影響,以及對整個叢集的

Kafka叢集的故障恢復

Kafka 叢集部署環境 kafka 叢集所用版本 0.9.0.1 叢集部署了實時監控: 通過實時寫入資料來監控叢集的可用性, 延遲等; 叢集故障發生 叢集的實時監控發出一條寫入資料失敗的報警, 然後馬上又收到了恢復的報警, 這個報警當時沒有重要,沒有去到對應

kafka故障

con type 檢查 狀態 shadow ef6 sed tex consumer 故障現象:kafka有3個Partition分別為0,1,2,在實際運行中發現consumer只能收到Partition:0和Partition:1的數據,檢查topic狀態均正常。查找P

【troubleshooting】Kafka集群重啟導致消息重復消費問題處理記錄

進程 pid 導致 set pic 方法 sum tails log 因需要重啟了Kafka集群,重啟後發現部分topic出現大量消息積壓,檢查consumer日誌,發現消費的數據竟然是幾天前的。由於平時topic消息基本上無積壓,consumer消費的數據都是最新的,明顯

阿里雲盤擴容遇到的坑

背景 生產環境使用了阿里雲並且以mongo作為圖片伺服器,由於業務發展需要資料盤的400G的容量已經用到81%,所以需要對磁碟做無損擴容操作。 操作步驟 在控制檯上擴容資料盤的磁碟空間 官方文件:https://help.aliyun.com/document_detail/25452.html?s

Kafka消費能力低,重新分配節點問題優化

         目前在做一個車聯網APP專案。 專案中歷史軌跡的處理模式為kafka推送給我車輛報文,然後我自行判斷車輛熄火點火來進行歷史軌跡行程的儲存。        專案開始車輛較少,每次kafka推送

Kafka不能消費故障

背景: kafka叢集機器升級,使得部分spark Streaming不能消費讀取資料 問題原因: kafka會自動建立一個預設的topic __consumer_offsets,用於儲存offset到Kafka系統 由於我們叢集kafka節點有7個,當逐漸的下架上架機器後,使得

redis叢集搭建的問題處理

1.複製3份conf檔案,用來起不同埠的3個redis應用 修改conf: port 6399 bind 10.61.70.136 183.61.70.136 dir /data/redis/data/ 2.分別將3個redis啟動起來 ./redis-server ../con

koacms的線上部署心得

今天學完了大地老師的koa教程,自個正好有閒置的伺服器,備案域名,正好也就練手,來一次小小的全棧專案部署之旅。我能說早就籌劃了嗎,哈哈!特此記錄下此過程,以備將來再查閱! 首先用到的技術棧是koa2+mongodb+node+nginx,先說mongodb,因為伺服器上裝的是視覺化的寶塔面板,所

ZOOKEEPER叢集超時問題分析

CDH安裝的ZK,三個節點,基本都是預設配置,一直用得正常,今天出現問題,客戶端連線超時6倍時長,預設最大會話超時時間是一分鐘。原因分析:1.首先要確認網路正確。確認時鐘同步。2.檢視現有的配置,基本都是預設配置 JVM配置是1G 有 2g的,不一樣3.檢視dataDir目錄,du -sh .發現已經有五百多

kafka消費能力優化

之前的程式碼: 有多個source:多個kafka,一個ES 1.消費者資料介面 interface Source { List<String> poll(); } 2.im

Spark叢集查詢速度變慢的問題調查

現象:針對某張表(下文中用A表代替)的查詢速度慢了6s 簡單介紹一下系統的架構:Spark + Tachyon + glusterfs+mesos,其中glusterfs負責tachyon資料的

【面試】A公司線上程式設計面試

面試之前準備了很多諸如生產者消費者,ABC問題,手擼LRU啊,負載均衡演算法啊。。 結果題目一來感覺自己被辜負了,2333 措手不及,有點小緊張… 兩道leetCode easy(我感覺)難度的題目。。 後記,得知掛了。但我一頭霧水不知道掛在哪?

k8s 叢集單點故障引發的血案

寫在前面 公司使用了 k8s 叢集來管理一些比較基礎的有狀態叢集,基於 k8s 進行了簡單的二次開發,使之可以支援有狀態的叢集(並沒有使用自帶的petset,現在改名為statefulset了好像)。運行了了挺長時間,一直比較正常。但由於一些歷史原因及僥倖心理

kubernetes叢集異常: kubelet連線apiserver超時

Background kubernetes是master-slave結構,master node是叢集的大腦, 當master node發生故障時整個叢集都"out of controll"。master node中最重要的當屬apiserver元件, 它負責處理所有請求, 並持久化狀態到

阿里雲LVM擴容與 LVM 相關知識學習

一、lvm 擴容 問題: 我們阿里雲伺服器有一個磁碟容量為 1T ,但是最近由於業務的擴增,磁碟容量已經不夠了,需要增大磁碟的容量。磁碟掛載在 /home,使用的是 LVM。我們現在需要對磁碟進行擴容。 通過增加新的磁碟,然後將磁碟新增到卷組(VG),然後再將邏輯卷(LV)擴容。 擴容原有的磁碟。然後再

坑逼的線上事故

out 表示 imp true clas 線上事故 col 線上 java SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd"); SimpleDateFormat

線上gc調優的過程

aspect hash 接下來 JD lac abs rac 數據庫 %x 近期公司運營同學經常表示線上我們一個後臺管理系統運行特別慢,而且經常出現504超時的情況。對於這種情況我們本能的認為可能是代碼有性能問題,可能有死循環或者是數據庫調用次數過多導致接口運

線上MySQL數據庫死鎖問題

重復 成功 中一 主鍵 adl 一次 his TE BE 最近線上項目報了一個MySQL死鎖(DealLock)錯誤,雖說對業務上是沒有什麽影響的,由於自己對數據庫鎖這塊了解不是很多,之前也沒怎麽的在線上碰到過。這次剛好遇到了,便在此記錄一下。 出現

線上Java程序導致服務器CPU占用率過高的問題排除過程

tasks all lob jstat rip 進行 runable tails 分享圖片 https://blog.csdn.net/u013991521/article/details/52781423 1、故障現象 客服同事反饋平臺系統運行緩慢,網頁卡頓嚴重,多次重啟