1. 程式人生 > 實用技巧 >kafka-03-kafka常見線上問題

kafka-03-kafka常見線上問題

一、kafka叢集管理工具 kafka-manager部署安裝 https://www.cnblogs.com/dadonggg/p/8205302.html 二、JVM引數設定 kafka是scala語言開發,執行在JVM上,需要對JVM引數合理設定,參看JVM調優專題 修改bin/kafka-start-server.sh中的jvm設定 1 export KAFKA_HEAP_OPTS="‐Xmx16G ‐Xms16G ‐Xmn12G ‐XX:MetaspaceSize=256M ‐XX:+UseG1GC ‐XX:MaxGCPauseMillis=50" 這種大記憶體的情況一般都要用G1垃圾收集器,因為年輕代記憶體比較大,用G1可以設定GC最大停頓時間,不至於一次minor gc就花費太長 時間 三、線上問題及優化
1、訊息丟失情況訊息傳送端: (1)acks=0:表示producer不需要等待任何broker確認收到訊息的回覆,就可以繼續傳送下一條訊息。效能最高,但是最容易丟消 息。大資料統計報表場景,對效能要求很高,對資料丟失不敏感的情況可以用這種。 (2)acks=1:至少要等待leader已經成功將資料寫入本地log,但是不需要等待所有follower是否成功寫入。就可以繼續傳送下一條消 息。這種情況下,如果follower沒有成功備份資料,而此時leader又掛掉,則訊息會丟失。 (3)acks=-1或all:這意味著leader需要等待所有備份(min.insync.replicas配置的備份個數)都成功寫入日誌,這種策略會保證只要有一 個備份存活就不會丟失資料。這是最強的資料保證。一般除非是金融級別,或跟錢打交道的場景才會使用這種配置。當然如果 min.insync.replicas配置的是1則也可能丟訊息,跟acks=1情況類似。 訊息消費端:
如果消費這邊配置的是自動提交,萬一消費到資料還沒處理完,就自動提交offset了,但是此時你consumer直接宕機了,未處理完的資料 丟失了,下次也消費不到了。 2、訊息重複消費 訊息傳送端: 傳送訊息如果配置了重試機制,比如網路抖動時間過長導致傳送端傳送超時,實際broker可能已經接收到訊息,但傳送方會重新發送訊息 訊息消費端: 如果消費這邊配置的是自動提交,剛拉取了一批資料處理了一部分,但還沒來得及提交,服務掛了,下次重啟又會拉取相同的一批資料重 復處理 一般消費端都是要做消費冪等處理的。 3、訊息亂序 如果傳送端配置了重試機制,kafka不會等之前那條訊息完全傳送成功才去傳送下一條訊息,這樣可能會出現,傳送了1,2,3條訊息,第 一條超時了,後面兩條傳送成功,再重試傳送第1條訊息,這時訊息在broker端的順序就是2,3,1了 。可以通過設定引數max.in.flight.requests.per.connection = 1來限制客戶端在單個連線上能夠傳送的未響應請求的個數,設定此值是1 表示kafka broker在響應請求之前client不能再向同一個broker傳送請求,這樣便可以避免訊息亂序。 4、訊息積壓
1)線上有時因為傳送方傳送訊息速度過快,或者消費方處理訊息過慢,可能會導致broker積壓大量未消費訊息。 此種情況如果積壓了上百萬未消費訊息需要緊急處理,可以修改消費端程式,讓其將收到的訊息快速轉發到其他topic(可以設定很多分 區),然後再啟動多個消費者同時消費新主題的不同分割槽。 2)由於訊息資料格式變動或消費者程式有bug,導致消費者一直消費不成功,也可能導致broker積壓大量未消費訊息。 此種情況可以將這些消費不成功的訊息轉發到其它佇列裡去(類似死信佇列),後面再慢慢分析死信佇列裡的訊息處理問題。 5、延時佇列 延時佇列儲存的物件是延時訊息。所謂的“延時訊息”是指訊息被髮送以後,並不想讓消費者立刻獲取,而是等待特定的時間後,消費者 才能獲取這個訊息進行消費,延時佇列的使用場景有很多,比如: 1)在訂單系統中,一個使用者下單之後通常有30分鐘的時間進行支付,如果30分鐘之內沒有支付成功,那麼這個訂單將進行異常處理, 這時就可以使用延時佇列來處理這些訂單了。 2)訂單完成1小時後通知使用者進行評價。 實現思路:傳送延時訊息時先把訊息按照不同的延遲時間段傳送到指定的佇列中(topic_1s,topic_5s,topic_10s,...topic_2h,這個一 般不能支援任意時間段的延時),然後通過定時器進行輪訓消費這些topic,檢視訊息是否到期,如果到期就把這個訊息傳送到具體業務處理的topic中,佇列中訊息越靠前的到期時間越早,具體來說就是定時器在一次消費過程中,對訊息的傳送時間做判斷,看下是否延遲到對 應時間了,如果到了就轉發,如果還沒到這一次定時任務就可以提前結束了。 6、訊息回溯 如果某段時間對已消費訊息計算的結果覺得有問題,可能是由於程式bug導致的計算錯誤,當程式bug修復後,這時可能需要對之前已消 費的訊息重新消費,可以指定從多久之前的訊息回溯消費,這種可以用consumer的offsetsForTimes、seek等方法指定從某個offset偏移 的訊息開始消費 7、分割槽數越多吞吐量越高嗎 可以用kafka壓測工具自己測試分割槽數不同,各種情況下的吞吐量 1 #往test裡傳送一百萬訊息,每條設定1KB 2 #throughput用來進行限流控制,當設定的值小於0時不限流,當設定的值大於0時,當傳送的吞吐量大於該值時就會被阻塞一段時間 3 bin/kafka‐producer‐perf‐test.sh‐‐topictest‐‐num‐records1000000‐‐record‐size1024‐‐throughput‐1 4 ‐‐producer‐propsbootstrap.servers=192.168.0.60:9092acks=1 網路上很多資料都說分割槽數越多吞吐量越高,但從壓測結果來看,分割槽數到達某個值吞吐量反而開始下降,實際上很多事情都會有一個 臨界值,當超過 這個臨界值之後,很多原本符合既定邏輯的走向又會變得不同。一般情況分割槽數跟叢集機器數量相當就差不多了。 當然吞吐量的數值和走勢還會和磁碟、檔案系統、I/O排程策略等因素相關。 注意:如果分割槽數設定過大,比如設定10000,可能會設定不成功,後臺會報錯"java.io.IOException:Toomanyopenfiles"。 異常中最關鍵的資訊是“Toomanyopenflies”,這是一種常見的Linux系統錯誤,通常意味著檔案描述符不足,它一般發生在建立線 程、建立Socket、開啟檔案這些場景下。在Linux系統的預設設定下,這個檔案描述符的個數不是很多,通過ulimit-n命令可以查 看:一般預設是1024,可以將該值增大,比如:ulimit-n65535 test分割槽數 1 my-replicated-topic分割槽數 3