Kafka學習筆記

初入公司,接到一個卡夫卡的問題,將學習筆記輸出在這裏。

Kafka相關資料

Kafka 就是一款基於發佈與訂閱的消息系統。它一般被稱爲“分佈式提交日誌”或者“分佈式流平臺”。

Kafka 的數據單元被稱爲消息,消息可以有一個可選的元數據 ,也就是鍵批次就是一組消息,這些消息屬於同一個主題和分區。

Kafka的基本術語

Topic

Kafka將消息種子(Feed)分門別類,每一類的消息稱之爲一個主題(Topic).

Producer

發佈消息的對象稱之爲主題生產者(Kafka topic producer)

Consumer

訂閱消息並處理髮布的消息的種子的對象稱之爲主題消費者(consumers)

Broker

已發佈的消息保存在一組服務器中,稱之爲Kafka集羣。集羣中的每一個服務器都是一個代理(Broker). 消費者可以訂閱一個或多個主題(topic),並從Broker拉數據,從而消費這些已發佈的消息。

集羣成員關係

通過zookeeper維護,每個broker的id唯一,可在配置文件指定,或自動生成。具體配置見Zookeeper配置。在 broker 停機、出現網絡分區或長時間垃圾回收停頓時,broker 會從 Zookeeper 上斷開連接,此時 broker 在啓動時創建的臨時節點會自動從 Zookeeper 上移除。監聽broker列表的Kafka組件會被告知該 broker已移除。在關閉 broker 時,它對應的節點也會消失,不過它的 ID 會繼續存在於其他數據結構中 。例如,主題的副本列表裏就可能包含這些id。在完全關閉一個 broker 之後,如果使用相同的id啓動另一個全新的 broker,它會立即加入集羣,並擁有與舊 broker相同的分區和主題。

控制器

         就是一個broker,額外負責首領選舉,其他 broker 在控制器節點上創建Zookeeper watch 對象。如果控制器關閉或與zookeeper斷開,其他broker就嘗試成爲控制器。如果一個broker斷開,控制器負責爲失去首領的分區選擇新的首領(一般就是分區副本的下一個),控制器使用epoch 來避免兩個節點同時認爲自己是當前的控制器。

Kafka數據可靠保證

  1. Kafka可以保證分區消息的順序;
  2. 只有消息寫入所有同步副本才認爲消息是“已提交”的;
  3. 只要有一個活躍副本,已提交消息就不會丟失;
  4. 消費者只能讀取已提交消息;

複製(ISR)

         所有生產者請求和消費者請求都會經過首領副本。跟隨者唯一的任務就是從首領那裏複製消息,保持與首領一致的狀態。首領確保跟隨者數據與其保持一致,跟隨者數據不一致則無法成爲新首領。replica.lag.time.max.ms用來設定跟隨者的正常不活躍時間。

         跟隨者活躍的判斷條件:1. 它在過去的6s內(可配置)向Zookeeper 發送過心跳。2. 過去的10s內(可配置)從首領那裏獲取過消息。3. 在過去的10s內從首領那裏獲取過最新的消息,還必須是幾乎零延遲的。如果不活躍,跟隨者會與zookeeper重新建立連接,重新獲取最新數據。如果ack設置爲all,而跟隨者不活躍,則消費者可以忽略此跟隨者響應。

         主題級別的配置副本數量參數是replicatlon.factor,而在broker級別則可以通過 default.replication.factor 來配置自動創建的主題。

         unclean.leader.selection.enable設置爲true則允許不完全的首領選舉,即如果首領副本崩潰,而其他跟隨者副本都沒有同步,那麼允許不同步的副本成爲首領。

         min.insync.replic設定最小同步副本數量。如果不夠,則broker拒絕接收消息,返回錯誤,副本相當於變成只讀。

發送確認

ack =0,可以保證驚人的吞吐量,但是生產者完全不知道出現了數據丟失;

ack=1,也有可能出現丟失,因爲可能成功寫入後首領副本出現了崩潰;

ack=all,配合min.insync.replicas可以實現最保險的辦法,生產者會一直重試直到數據發送成功,但是會降低吞吐量。

生產者重試設置

首先要區分發送消息錯誤可否重試,如果要保證數據不丟失,那麼就需要在遇到可重試錯誤時進行重試,要注意重試次數。另外,還要注意重試可能會導致都寫入成功而重複,可以在消息里加入唯一的標識符加以辨別。

可靠系統裏使用消費者

如果消費者提交了偏移量卻未能處理完消息,那麼就有可能造成消息丟失,這也是消費者丟失消息的主要原因。在這種情況下,如果其他消費者接手了工作,那些沒有被處理完的消息就會被忽略,永遠得不到處理。具體分析詳見輪詢

有幾個設置需要注意:

  1. group.id 如果希望一個消費者獲取到一個topic的所有消息,則需要設置其唯一的group.id
  2. auto.offset.reset 可配置爲earliest與latest,none,需要注意的是,雖然是如果已有提交offset,從offset開始消費,但是長時間保持生產者速度大於消費者消費速度,消費者記錄的offset被刪除,那麼還是會觸發從最早還是從最新offset開始消費
  3. enable.auto.commit 此項容易造成重複消費,如在提交前停止處理消息,這時消息已經被處理一部分但是offset沒有提交上去。而且如果將消息交給線程處理,那麼可能消息還沒有處理完offset就已經提交了。
  4. auto.commit.interval.ms 默認5s自動提交一次offset,頻率越低重複消費的可能性越低,但是會提高額外開銷。

顯式提交偏移量

  1. 總是在處理完事件後再提交偏移量;
  2. 提交頻度是性能和重複消息數量之間的權衡;
  3. 確保對提交的偏移量心裏有數:在輪詢(poll)中提交的偏移量是讀取到的最新偏移量,而不是處理到的最新偏移量;
  4. 再均衡:需要注意對再均衡的處理;
  5. 消費者可能需要重試:有兩種處理方式,一種是在遇到可重試錯誤時,提交最後一個處理成功的偏移量,然後把還沒有處理好的消息保存到緩衝區裏(這樣下一個輪詢就不會把它們覆蓋掉),調用消費者的 pause()方怯來確保其他的輪詢不會返回數據(不需要擔心在重試時緩衝區隘出),在保持輪詢的同時嘗試重新處理。如果重試成功,或者重試次數達到上限井決定放棄,那麼把錯誤記錄下來井丟棄消息,然後調用resume()方能讓消費者繼續從輪詢裏獲取新數據。另一種則是在遇到可重試錯誤時,把錯誤寫入一個獨立的主題,然後繼續。一個獨立的消費者羣組負責從該主題上讀取錯誤消息,井進行重試,或者使用其中的一個消費者同時從該主題上讀取錯誤消息並進行重試,不過在重試時需要暫停該主題。這種模式有點像其他消息系統裏的 dead-letter-queue。
  6. 消費者可能需要維護狀態;
  7. 長時間處理:將數據交給線程池來處理,加快速度。並在保持輪詢的狀態下調用pause(),以防止再均衡。

模式

消息模式 (schema) Json XML

主題和分區

消息通過主題進行分類,主題可以被分爲若干個分區

通過分區來實現數據冗餘和伸縮性。一個主題可以橫跨多個服務器,以此來提供比單個服務器更強大的性能。

 

Topic的刪除

         實際測試的時候,發現刪除topic時,kafka只是將其marked as deleted,並未真正刪除,此時繼續向topic發送消息仍然成功,需要在server.properties設置一個屬性:delete.topic.enable=true,這樣纔是真正的刪除了topic。一般清空topic內的數據可以刪除topic,不用重新創建,直接再向topic發送消息即可。具體的操作可以查看某一topic數據清空

生產者

創建消息。一般情況下,一個消息會被髮布到一個特定的主題上。生產者在默認情況下把消息均衡地分佈到主題的所有分區上,而並不關心特定消息會被寫到哪個分區。不過,在某些情況下,生產者會把消息直接寫到指定的分區。這通常是通過消息鍵分區器來實現的,分區器爲鍵生成一個散列值,並將其映射到指定的分區上。這樣可以保證包含同一個鍵的消息會被寫到同一個分區上。生產者也可以使用自定義的分區器,根據不同的業務規則將消息映射到分區。

序列化器將消息序列化成字節數組,以網絡傳輸。

如果消息成功寫入 Kafka,就返回 一 個RecordMetaData 對象,它包含了主題和分區信息,以及記錄在分區裏的偏移量。如果寫入失敗, 則會返回 一個錯誤。

消息發送方式

  1. 發送並忘記
  2. 同步發送
  3. 異步發送

 

KafkaProducer一般會發生兩類錯誤。其中一類是可重試錯誤 ,這類錯誤可以通過重發消息來解決。比如對於連接錯誤,可以通過再次建立連接來解決,“無主( no leader )” 錯誤則可以通過重新爲分區選舉首領來解決。 KafkaProducer可以被配置成自動重試,如果在多次重試後仍無能解決問題,應用程序會收到一個重試異常。另一類錯誤無出通過重試解決,比如“消息太大”異常。對於這類錯誤, KafkaProducer不會進行任何重試,直接拋出異常。

注意:

librdkafka不像java客戶端那樣,可以通過future.get()實現同步發送。所以,如果broker不能連通的話,send方法還是可以正常將消息放入隊列。這會導致兩個問題

1、我們的客戶端是不會知道broker已經掛掉了,因而不能對這種情況作出及時處理,導致消息全部堆積在內存中,如果此時不幸,我們的客戶端也掛掉了,那這部分消息就全部丟失了。

2、如果broker一直沒有恢復,而我們一直向隊列中寫數據的話,producer中有一個選項message.timeout.ms,如果超過了設定的消息超時時間,那麼會有線程清理隊列中的數據,導致消息丟失,而如果將時間設置爲0(永不超時)的話,將導致客戶端內存撐滿。

此問題可以通過設置發送回調的處理方式來應對。

生產者重要配置

  1. acks指定了必須要有多少個分區副本收到消息,生產者纔會認爲消息寫入是成功的。

acks=0 , 生產者不等待服務器接收響應,吞吐量高。

acks=1 ,需要等待首領確認,可能產生數據丟失(首領切換時),吞吐量取決於同步還是異步發送。

acks=all ,只有當所有參與複製的節點全部收到消息時,生產者纔會收到一個來自

服務器的成功響應。這種模式是最安全的,它可以保證不止一個服務器收到消息,就算

有服務器發生崩潰,整個集羣仍然可以運行。不過,它的延遲比 acks=1時更高,因爲要等待不只一個服務器節點接收消息。

  1. buffer.memory

內存緩衝區的大小,生產者發送數據速度超過服務器接收時,這裏會被佔滿,send要麼阻塞要麼拋出異常,取決於max.block.ms的設定。

  1. compression.type

發送消息壓縮類型,有snappy 、 gzi.p 或 lz4四種。

  1. retries

錯誤重試次數,默認100ms一次,可以通過retry.backoff.ms改變,需判斷是臨時錯誤還是重要錯誤(如發送消息過大,重試無意義)來進行處理。

序列化器

Kafka有自己的散列算法(更新java版本算法不會改變),在分區不變的時候,鍵值相同一定會被分到相同分區。所以在創建主題時規劃好分區,不要輕易改變。

可以自定義實現分區策略,java語言需自己實現接口

 

消費者

讀取消息。消費者訂閱一個或多個主題,並按照消息生成的順序讀取它們。消費者通過檢查消息的偏移量來區分已經讀取過的消息。 偏移量是另一種元數據,它是一個不斷遞增的整數值,在創建消息時, Kafka 會把它添加到消息裏。在給定的分區裏,每個消息的偏移量都是唯一的。消費者把每個分區最後讀取的消息偏移量保存在 Zookeeper 或 Kafka 上,如果消費者關閉或重啓,它的讀取狀態不會丟失。

消費者是消費者羣組的一部分,也就是說,會有一個或多個消費者共同讀取一個主題 。 羣組保證每個分區只能被一個消費者使用 。下圖所示的羣組中,有 3 個消費者同時讀取一個主題。其中的兩個消費者各自讀取一個分區,另外一個消費者讀取其他兩個分區。消費者與分區之間的映射通常被稱爲消費者對分區的所有權關係 。

 

一個羣組裏的消費者訂閱的是同一個主題,每個消費者接收主題一部分分區的消息。如果消費者組數量超過partition數量,則會有消費者一直收不到消息,直到有正在消費的消費者停止消費。

 

消費者分區分配策略

而確定消費者消費那幾個分區的策略有如下幾種

  1. RangeStrategy
  1. 對分區編號進行排序(如0,1,2,3,4,5,6,7,8,9)
  2. 消費者線程排序(C1-0, C2-0, C2-1)
  3. 將partitions的個數除於消費者線程的總數來決定每個消費者線程消費幾個分區。如果除不盡,那麼前面幾個消費者線程將會多消費一個分區。

如下:

C1-0 將消費 0, 1, 2, 3 分區

C2-0 將消費 4, 5, 6 分區

C2-1 將消費 7, 8, 9 分區

假如我們有11個分區,那麼最後分區分配的結果看起來是這樣的:

C1-0 將消費 0, 1, 2, 3 分區

C2-0 將消費 4, 5, 6, 7 分區

C2-1 將消費 8, 9, 10 分區

假如我們有2個主題(T1和T2),分別有10個分區,那麼最後分區分配的結果看起來是這樣的:

C1-0 將消費 T1主題的 0, 1, 2, 3 分區以及 T2主題的 0, 1, 2, 3分區

C2-0 將消費 T1主題的 4, 5, 6 分區以及 T2主題的 4, 5, 6分區

C2-1 將消費 T1主題的 7, 8, 9 分區以及 T2主題的 7, 8, 9分區

 

可以看出,C1-0 消費者線程比其他消費者線程多消費了2個分區,這就是Range strategy的一個很明顯的弊端。

  1. RoundRobin strategy

使用此策略的前提條件:

同一個Consumer Group裏面的所有消費者的num.streams必須相等;

每個消費者訂閱的主題必須相同

         將所有主題的分區組成 TopicAndPartition 列表,然後對 TopicAndPartition 列表按照 hashCode 進行排序

 

分區分配策略,librdkafka如何自定義暫未發現方法,java應該是可以的。

消費者羣組和分區再均衡

一個新的消費者加入羣組時,它讀取的是原本由其他消費者讀取的消息。當一個消費者被關閉或發生崩潰時,它就離開羣組,原本由它讀取的分區將由羣組裏的其他消費者來讀取。在主題發生變化時,比如管理員添加了新的分區,會發生分區重分配。這種所有權轉移,叫做再均衡(rebalance),再均衡可以提供高可用性和伸縮性,但是消費者可能暫時無法讀取消息,造成整個羣組一小段時間的不可用。

消費者通過向被指派爲羣組協調器(group coordinater)的 broker (不同的羣組可以有不同的協調器)發送心跳來維持它們和羣組的從屬關係以及它們對分區的所有權關係。只要消費者以正常的時間間隔發送心跳,就被認爲是活躍的,說明它還在讀取分區裏的消息。消費者會在輪詢消息(爲了獲取消息)或提交偏移量時發送心跳。如果消費者停止發送心跳的時間足夠長,會話就會過期,羣組協調器認爲它已經死亡,就會觸發一次再均衡。另外,消費者退出,羣組協調器不會等待心跳而立即執行再均衡。如果發生了再均衡,整個過程也是在輪詢期間進行的。當然,心跳也是從輪詢裏發送出去的。所以,我們要確保在輪詢期間所做的任何處理工作都應該儘快完成

心跳行爲

Kafka 社區引入了一個獨立的心跳線程,可以在輪均消息的空檔發送心跳 。 這樣一來,發送心跳的頻率(也就是消費者羣組用於檢測發生崩潰的消費者或不再發送心跳消費者的時間)與消息輪詢的頻率(由處理消息所花費的時間未確定)之間就是相互獨立的。

訂閱主題

我們也可以在訂閱主題時傳入一個正則表達式。正則表達式可以匹配多個主題, 如果有人創建了新的主題,並且主題的名字與正則表達式匹配,那麼會立即觸發一次再均衡,消費者就可以讀取新添加的主題。如果應用程序需要讀取多個主題,井且可以處理不同類型的數據,那麼這種訂閱方式就很管用。在 Kafka 和其他系統之間複製數據時,使用正則表達式的方式訂閱多個主題是很常見的做法。

輪詢

一旦消費者訂閱了主題,輪詢就會處理所有的細節,包括羣組協調、分區再均衡、發送心跳和獲取數據。

poll () 方能返回一個記錄列表。每條記錄都包含了記錄所屬主題的信息、記錄所在分區的信息、記錄在分區裏的偏移量,以及記錄的鍵值對。我們一般會遍歷這個列表,逐條處理這些記錄。poll()方法有一個超時參數,它指定了在多久之後可以返回,不管有沒有可用的數據都要返回。 超時時間的設置取決於應用程序對響應速度的要求,比如要在多長時間內把控制權歸還給執行輪詢的線程。

注意:

Consumer讀取partition中的數據是通過調用發起一個fetch請求來執行的。而從KafkaConsumer來看,它有一個poll方法。但是這個poll方法只是可能會發起fetch請求。原因是:Consumer每次發起fetch請求時,讀取到的數據是有限制的,通過配置項max.partition.fetch.bytes來限制的。而在執行poll方法時,會根據配置項個max.poll.records來限制一次最多pool多少個record。

那麼就可能出現這樣的情況: 在滿足max.partition.fetch.bytes限制的情況下,假如fetch到了100個record,放到本地緩存後,由於max.poll.records限制每次只能poll出15個record。那麼KafkaConsumer就需要執行7次才能將這一次通過網絡發起的fetch請求所fetch到的這100個record消費完畢。其中前6次是每次pool中15個record,最後一次是poll出10個record。

在consumer中,還有另外一個配置項:max.poll.interval.ms ,它表示最大的poll數據間隔,如果超過這個間隔沒有發起poll請求,但heartbeat仍舊在發,就認爲該consumer處於 livelock狀態。就會將該consumer退出consumer group。所以爲了不使Consumer 自己被退出,Consumer 應該不停的發起poll(timeout)操作。而這個動作 KafkaConsumer Client是不會幫我們做的,這就需要自己在程序中不停的調用poll方法了。

因此fetch到消息後,offset提交的是fetch到消息的最大offset而不是poll得到的消息位置,此時如果消費者掛掉了,offset又自動提交了,那麼fetch到但是沒有消費的消息就是丟失,解決辦法是每poll成功一次消息就手動提交一次offset

消費者的配置

  • fetch.min.bytes

指定了消費者從服務器獲取記錄的最小字節數。broker 在收到消費者的數據請求時,如果可用的數據量小於fetch.min.bytes 指定的大小,那麼它會等到有足夠的可用數據時才把它返回給消費者。

  • fetch.max.wait.ms

默認500ms,即如果一直沒有到最小字節數,到500ms就發送數據。大部分客戶端只能讀取已經被寫入所有同步副本的消息(跟隨者副本也不行,儘管它們也是消費者 否則複製功能就無法工作)。分區首領知道每個消息會被複制到哪個副本上,在消息還沒有被寫入所有同步副本之前,是不會發送給消費者的一一嘗試獲取這些消息的請求會得到空的響應而不是錯誤 。

  • max . partition.fetch. bytes

消費者從分區獲取最大字節數,默認1M。注意,值必須比broker能夠接收的最大消息的字節數(通過max.message.size屬性配置)大,否則消費者一直掛起重試。

  • session.timeout.ms

會話超時時間,默認3s,如果在時間內沒有發送心跳,則認爲死亡而觸發rebalance。所以要注意協調heartbeat.interval.ms的設置。

  • auto.offset.reset

指定消費者在讀取一個沒有偏移量的分區或者偏移量無效的情況下(因消費者長時間失效,包含偏移量的記錄已經過時並被刪除)該作何處理。

earlist:當各分區下有已提交的offset時,從提交的offset開始消費;無提交的offset時,從頭開始消費

latest:當各分區下有已提交的offset時,從提交的offset開始消費;無提交的offset時,消費新產生的該分區下的數據

none:topic各分區都存在已提交的offset時,從offset後開始消費;只要有一個分區不存在已提交的offset,則拋出異常

  • enable.auto.commit

自動提交偏移量,避免重複消費應設爲false,如果爲true,需要設定auto.commit.interval.ms指定自動提交的間隔。另外發現,topic設置有一個auto.commit.enable,優先度比全局設置低,所以不要設置錯了。

  • partition.assignment.strategy

分區分配策略

提交和偏移量

如果消費者一直運行,提交到_consumer_offset並沒有什麼用,這個offset是爲了在消費者發生崩潰或有新的消費者加入羣組出發再均衡時使用的。

提交方式

  1. 自動提交

默認每隔5s自動提交一次。容易出現重複消費,通過減小提交時間降低,但是無法避免。每次輪詢會提交上次的offset,而不知道上一次的消息是否被處理,所以最好保證上一次的消息被處理之後再提交。

  1. 主動提交(同步提交,異步提交)

暫未發現librdkafka如何提交,需要閱讀源碼查找確認。一般採取同步異步組合提交結果比較準確。注意,提交的是最後一個offset,也不是當前處理的消息的offset

  1. 提交特定位置偏移量

Librdkafka應該有一個函數,可以手動傳入一個表,參數爲topic,partition,offset,用來指定下一個從哪裏讀取。

從特定位置開始處理消息記錄

Kafka支持消費者從特定位置處理消息記錄。消費端經調查有rd_kafka_offsets_store,應該可以手動提交,但是未驗證,但是可以通過kafkaserver的指令來指定。

broker和集羣

一個獨立的 Kafka 服務器被稱爲 broker。 broker接收來自生產者的消息,爲消息設置偏移量,並提交消息到磁盤保存

broker 是集羣的組成部分。每個集羣都有一個 broker 同時充當了集羣控制器的角色(自動從集羣的活躍成員中選舉出來)。控制器負責管理工作,包括將分區分配給 broker 和監控broker. 在集羣中, 一個分區從屬於一個 broker, 該 broker 被稱爲分區的首領 。一個分區可以分配給多個broker,這個時候會發生分區複製。這種複製機制爲分區提供了消息冗餘,如果有一個broker失效,其他broker可以接管領導權。不過,相關的消費者和生產者都要重新連接到新的首領。

Kafka配置

Zookeeper配置

Zookeeper 集羣被稱爲羣組。 Zookeeper 使用的是一致性協議,所以建議每個羣組裏應該包含奇數個節點(比如 3 個、 5 個等),這樣保證一小半不工作了還能處理外部請求。

羣組需要有一些公共配置,每個服務器還要在數據目錄中創建一個 myid 文件,用 於指明自己的 ID。如果羣組裏服務器的機器名是 zoo1.example.com 、 zoo2.example.com 、 zoo3 .example.com。initlimit 表示用於在從節點與主節點之間建立初始化連接的時間上限,synclimit 表示允許從節點與主節點處於不同步狀態的時間上限。這兩個值都是 tickTime 的倍數。服務器地址遵循 server.X=hostname:peerPort:leaderPort 格式,各個參數說明如下:

X

服務器的ID,它必須是一個整數,不過不一定要從 0 開始,也不要求是連續的

hostname

服務器的機器名或 IP 地址;

peerPort

用於節點間通信的 TCP 端口;

leaderPort

用於首領選舉的 TCP 端口。

客戶端只需要通過 clientPort 就能連接到羣組,而羣組節點間的通信則需要同時用到這 3 個端口( peerPort 、 leaderPort 、 clientPort )

 

KafkaServer參數配置

num.paritions指定了新創建的主題將包含多少個分區。一般根據生產者的吞吐量以及消費者的消費速度來決定分區數量,例如生產者1G/s對應消費者50M/s * 20partition,如果信息不足,可以將分區設置爲25G。

 

log.retention.hours指定消息保留時間,單位爲毫秒,如果同時設置了minutes和ms,這三個效果是一樣的,系統會優先選擇最小的時間,建議ms。

 

log.retention.bytes通過保留的消息字節數來判斷消息是否過期,作用在每一個分區上

 

如果上述兩項同時設置,則只要任意一個條件得到滿足,消息就會被刪除

 

log.segment.bytes決定日誌文件片段大小,達到指定大小之後,這塊文件片段會關閉,注意,正在寫入的片段是活躍片段,活躍片段永遠不會被刪除。只有片段關閉後纔開始等待過期,即一個日誌設置了7天過期,而這個片段花了10天才填滿,那麼從片段產生到過期其實過了17天。而且不管片段是否活躍,broker都會爲每個分區片段打開一個文件句柄,需要注意調優,避免打開太多文件句柄。

 

log.segment.ms 與日誌留存時間一樣,大小和時間任意條件達到設定大小,消息日誌就會過期,此設定默認情況下是沒有配置的。

 

磁盤容量:如果每天接收1T數據保留7天,則需要70T容量

Broker需要的數量:如果需要保留10T數據,則需要 (5 * 2T/Broker)個broker

 

常用配置Kafka指令

創建Topic

./kafka-topics.sh --zookeeper <zookeeper connect> --create --topic <string> --replication-factor <int> --partitions <int>

 

調整分區

./kafka-topics.sh --zookeeper <zookeeper connect> --alter --topic <string> --partitions <int>

 

刪除分區

./kafka-topics.sh --zookeeper <zookeeper connect> --delete --topic <string>

 

列出集羣裏所有主題

./kafka-topics.sh --zookeeper <zookeeper connect> --list

 

列出Topic詳細信息

./kafka-topics.sh --zookeeper <zookeeper connect> --describe --under-replicated-partitions

其中--under-replicated-partitions可以列出所有包含不同步副本的分區

使用--unavailable-partitions參數可以列出所有沒有首領的分區,它們處於離線狀態,對生產者和消費者是不可用的。

列出並描述消費者羣組

舊版本:./kafka-consumer-groups.sh --zookeeper <zookeeper connect> --list <string

新版本:./kafka-consumer-groups.sh --new-consumer --bootstrap-server <zookeeper connect> --list <string>

例子:./kafka-consumer-groups.sh --describe --verbose --group 0 --bootstrap-server 10.117.210.183:9092

 

將group內所有offset指向1000

./kafka-consumer-groups --bootstrap-server localhost:9092 --group 0 --topic TestWSL666 --reset-offsets --to-offset 1000 –execute

使用--describe代替--list就可以獲取該羣組的所有主題的信息和每個分區的偏移量。

刪除羣組

./kafka-consumer-groups.sh --zookeeper <zookeeper connect> --delete --group <string>

注意在執行前必須關閉所有的消費者。該命令也可以用來在不刪除整個羣組的情況下刪除單個主題的偏移量。

./kafka-consumer-groups.sh --zookeeper <zookeeper connect> --delete --group <string> --topic <string>

導出偏移量

./kafka-run-class.sh kafka.tools.ExportZkOffsets --zkconnect <zookeeper connect> --group <string> --output-file <string>

導入偏移量

./kafka-run-class.sh kafka.tools.ImportZkOffset -- zkconnect <zookeeper connect> --input-file offsets

注意在導入偏移量之前,必須先關閉所有的消費者。如果消費者羣組處於活躍狀

態,它們不會讀取新的偏移量 , 反而有可能將導人的偏移量覆蓋掉。

覆蓋主題的默認配置

./kafka-configs.sh --zookeeper <zookeeper connect> --alter --entity-type topics --entity-name <topic name> --add-config <key>=<value>[,<key>=<value>,…]

常用配置參數如下:

 

配置broker集羣

要把一個 broker 加入到集羣裏,只需要修改兩個配置參數。首先,所有 broker 都必須配

置相同的 zookeeper .connect , 該參數指定了用於保存元數據的 Zookeeper 羣組和路 徑。

其次,每個 broker 都必須爲 broker.id 參數設置唯一的值。 如果兩個 broker 使用相同的

Broker.id,那麼第二個broker就無陸啓動。

Kafka 對 Zookeeper 的延遲和超時比較敏感,與Zookeeper羣組之間的一個通信異常就可能導致Kafka服務器出現無法預測的行爲 。

其他

rdkafka常用接口說明

一、主要數據結構

1、typedef struct rd_kafka_conf_s rd_kafka_conf_t;

 

rd_kafka_conf_t是kafka的全局配置結構,通過rd_kafka_conf_new()創建,創建時即進行了默認配置,通過rd_kafka_conf_set()設置參數值,是rd_kafka_new()創建kafka處理句柄的第二個參數,是必須創建的結構。

 

2、typedef struct rd_kafka_topic_conf_s rd_kafka_topic_conf_t;

 

rd_kafka_topic_conf_t主題配置結構,通過rd_kafka_topic_conf_new()創建,創建時即進行了默認配置,通過rd_kafka_topic_conf_set()設置參數值,是必須創建的結構。

 

3、typedef struct rd_kafka_s rd_kafka_t;

 

rd_kafka_t 是kafka 處理句柄結構,分爲producer類型和consumer類型,由rd_kafka_new()第一個參數類型決定。rd_kafka_t是一個總體結構,conf和topic_conf都是爲此結構服務,其中包含rk_brokers鏈表,rk_topics鏈表,是必須創建的結構。

 

4、typedef struct rd_kafka_topic_partition_list_s rd_kafka_topic_partition_list_t;

 

rd_kafka_topic_partition_list_t 可擴展長度的 主題-分區 鏈表,通過rd_kafka_topic_partition_list_new()創建,創建時指定長度,通過rd_kafka_topic_partition_list_add()添加 主題-分區對,用於訂閱消息。

 

二、主要接口

1、rd_kafka_conf_t *rd_kafka_conf_new (void)

參數:無

返回值:rd_kafka_conf_t *

創建一個kafka全局配置結構,並進行默認初始化設置,返回其引用指針。

 

2、rd_kafka_conf_res_t rd_kafka_conf_set (rd_kafka_conf_t *conf,

                                       const char *name,

                                       const char *value,

                                       char *errstr, size_t errstr_size)

參數:

conf:配置結構

name:配置項名稱

value:配置項值

errstr:錯誤提示

errstr_size:錯誤提示長度

返回值:rd_kafka_conf_res_t 枚舉,錯誤寫入errstr中

name具體的名稱及作用見rd_kafka_properties 中_RK_GLOBAL類型的數據定義。調用這個函數後再調用rd_kafka_conf_set_default_topic_conf()會將之前設置的值全部用默認值覆蓋掉。因爲錯誤提示會寫入errstr中,所以提前給errstr分配512字節空間。

 

3、rd_kafka_topic_conf_t *rd_kafka_topic_conf_new (void)

參數:無

返回值:rd_kafka_topic_conf_t *

創建一個主題配置結構,並進行默認初始化設置,返回其引用指針。

 

4、rd_kafka_conf_res_t rd_kafka_topic_conf_set (rd_kafka_topic_conf_t *conf,

     const char *name,

     const char *value,

     char *errstr, size_t errstr_size)

參數:

Conf:主題配置結構

Name:主題配置項名稱

Value:主題配置項值

Errstr:錯誤提示

errstr_size:錯誤提示長度

返回值:rd_kafka_conf_res_t 枚舉,錯誤寫入errstr中

name具體的名稱及作用見rd_kafka_properties 中_RK_TOPIC類型的數據定義。因爲錯誤提示會寫入errstr中,所以提前給errstr分配512字節空間。

 

5、rd_kafka_t *rd_kafka_new (rd_kafka_type_t type, rd_kafka_conf_t *app_conf,

  char *errstr, size_t errstr_size)

參數:

Type:RD_KAFKA_PRODUCER是創建生產者類型,RD_KAFKA_CONSUMER是創建消費者類型

Conf:配置結構

Errstr:錯誤提示

errstr_size:錯誤提示長度

返回值:

成功:返回rd_kafka_t *kafka操作句柄

失敗:返回NULL,並記錄錯誤信息到errstr

程序中先配置conf和topic_conf,然後調用此接口生成操作句柄。對消費者來講,訂閱主題,輪詢接收消息。對生產者來講,根據主題生成主題操作句柄,並通過主題操作句柄發送消息。

 

6、void rd_kafka_destroy (rd_kafka_t *rk)

參數:

Rk:kafka操作句柄

返回值:無

釋放創建的kafka操作句柄。

 

6、rd_kafka_topic_t *rd_kafka_topic_new (rd_kafka_t *rk, const char *topic,

                                      rd_kafka_topic_conf_t *conf)

參數:

Rk:kafka操作句柄

Topic:主題內容

Conf:主題配置

返回值:

成功:返回rd_kafka_topic_t * 主題操作句柄

失敗:返回NULL,記錄錯誤信息到errstr

此接口一般是生產者使用,使用此接口生成的主題操作句柄進行發送消息。

 

7、void rd_kafka_topic_destroy (rd_kafka_topic_t *app_rkt)

參數:

app_rkt:主題操作句柄

返回值:無

釋放創建的主題操作句柄

 

8、int rd_kafka_produce (rd_kafka_topic_t *rkt, int32_t partition,

      int msgflags,

      void *payload, size_t len,

      const void *key, size_t keylen,

      void *msg_opaque)

參數:

Rkt:主題操作句柄

Partition:分區號

Msgflags:消息標誌,使用RD_KAFKA_MSG_F_COPY標誌

Payload:消息體指針

Len:消息體長度

Key:消息選項key值,用作平衡分區,計算分區號的,填NULL

Keylen:key長度,填0

msg_opaque:是作爲回調函數的參數,填NULL

 

10、int rd_kafka_poll(rd_kafka_t *rk, int timeout_ms)

參數:

Rk:kafka操作句柄

timeout_ms:毫秒級時間

返回值:處理的事件數

發送完消息後調用此接口,timeout_ms是毫秒級的時間,函數會阻塞timeout_ms 毫秒等待事件處理,調用設置的回調函數。timeout_ms爲0是非阻塞狀態。

 

11、rd_kafka_resp_err_t rd_kafka_flush (rd_kafka_t *rk, int timeout_ms)

參數:

Rk:kafka操作句柄

timeout_ms:毫秒級時間

返回值:

成功:RD_KAFKA_RESP_ERR_NO_ERROR

失敗:RD_KAFKA_RESP_ERR__TIMED_OUT

在摧毀生產者之前調用此接口,確保正在排隊和正在進行的消息被處理完成。此函數會調用rd_kafka_poll()並觸發回調。

 

12、int rd_kafka_brokers_add (rd_kafka_t *rk, const char *brokerlist)

參數:

Rk:kafka操作句柄

Brokerlist:broker字符串 如:”172.20.51.38:9092” 不寫端口,則採用默認端口9092

   多個broker  brokerlist = "broker1:10000,broker2"

返回值:成功添加的broker個數

添加一個broker也可以通過 設置rd_kafka_conf_t結構中的 "bootstrap.servers" 配置項

rd_kafka_conf_set(conf, "bootstrap.servers", brokers, errstr, sizeof(errstr))

 

13、rd_kafka_resp_err_t rd_kafka_poll_set_consumer (rd_kafka_t *rk)

參數:

Rk:kafka操作句柄

返回值:rd_kafka_resp_err_t 枚舉

將消息重定向到了消費者隊列,可以使用rd_kafka_consumer_poll()進行取消息。

 

14、rd_kafka_topic_partition_list_t *rd_kafka_topic_partition_list_new (int size)

參數:size是topic結構的個數

 

返回值:無

原文:https://blog.csdn.net/icando777/article/details/78904487

 

Kafka全部數據清空

kafka全部數據清空的步驟爲:

  1. 停止每臺機器上的kafka;
  2. 刪除kafka存儲目錄(server.properties文件log.dirs配置,默認爲“/tmp/kafka-logs”)全部topic的數據目錄;
  3. 刪除zookeeper上與kafka相關的znode節點;
  4. 重啓kafka、如果刪除topic還在則需要重啓zookeeper;

這裏以192.168.187.201 node1、192.168.187.202 node2、192.168.187.203 node3三臺機器作爲kafka的集羣。

注意:kafka版本爲kafka_2.11-1.1.1

1.1 停止每臺機器上的kafka

以root用戶分別登錄三臺機器,使用命令jps 找出kafka的PID,再使用命令 kill kafka進程。

 節點node1

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124230352303-2049111997.png

節點node2

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124230604840-853454566.png

節點node3

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124230801688-49494632.png

1.2 刪除kafka存儲目錄

在kafka安裝目錄的config文件夾下server.properties中查看存儲目錄爲:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124231905898-1028471428.png

刪除該目錄所有數據:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124232013087-1166111535.png

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124232116611-1659435898.png

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124232159767-1296313895.png

1.3 刪除zookeeper上與kafka相關的znode節點

zookeeper上面保存着kafka的所有topic及其消費信息,故需要刪除與kafka相關的znode節點:

進入zookeeper的shell界面:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124232558053-413681242.png

查看與kafka相關的znode節點:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124233936717-1791540859.png

在上面的znode節點中,除了zookeeper作爲zk的安全保障措施,其他znode節點都得刪除 

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124233616030-1658716067.png

1.4 重啓kafka

分別在node1、node2、node3上面執行如下命令啓動kafka:

/opt/app/kafka_2.11-1.1.1/bin/kafka-server-start.sh /opt/app/kafka_2.11-1.1.1/config/server.properties > /dev/null 2>&1 &

jps命令查看node1、node2、node3上面的啓動情況:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124234414705-1069369616.png

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124234443997-38484802.png

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124234458986-1326839643.png

最後在查看kafka上面是否還有topic存在:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124234641324-1532703507.png

可以看到topic及其相關數據已被清空刪除

某一topic數據清空

查看當前所有topic

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124234837316-1278266344.png

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181125000359591-1820181582.png

比如目前需要刪除test這一topic,目前kafka_2.11-1.1.1以上版本默認delete.topic.enable=true,即是說使用命令

./kafka-topics.sh --zookeeper node1:2181 --delete --topic test

該命令將會在zookeeper中刪除與test這一topic相關的znode節點(包括test詳細信息、生產數據、消費數據的節點),並在kafka的存儲目錄/opt/data/kafka/kafka-logs/下把與test這一topic相關的存儲數據目錄標記爲待刪除,稍後會真正刪除這些待刪除的目錄,如下:

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124235634498-1520342452.png

使用kafka-topics.sh查看test在zookeeper中相關znode節點信息是否已被刪除

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181125000145373-1805029236.png

在/opt/data/kafka/kafka-logs目錄下查看test相關存儲目錄是否被標記刪除

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124235751959-368041425.png

在/opt/data/kafka/kafka-logs目錄下查看test相關存儲目錄已被刪除

https://img2018.cnblogs.com/blog/1217276/201811/1217276-20181124235845962-1152346598.png

3. 思考

kafka全部數據清空步驟比較繁瑣,借鑑某一topic數據清空的方式,可以通過使用kafka-topics.sh --delete命令逐個刪除所有的topic,達到清空kafka全部topic數據的目的,不足的是topic“__consumer_offsets”無法刪除,不過不礙事。

 

librdkafka常用配置參數

kafka資料\librdkafka配置參數 - 代碼天地.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章