消息隊列kafka知識總結

Kafka簡介

Kafka是什麼

Kafka是由Apache軟件基金會開發的一個開源流處理平臺,由Scala和Java編寫。Kafka是一個分佈式的基於發佈/訂閱模式的消息隊列,相比於其他常見的消息隊列,Kafka的特點是高吞吐量極高,主要應用於大數據實時處理領域。

消息隊列

Kafka是一個常用的消息隊列,消息隊列就是在消息的傳輸過程中保存消息的容器。消息隊列有很多種用途,可以用來給程序解耦合,可以讓同步的程序變成異步,在運維和後臺中,消息隊列還會被用來削峯和限流。

下面舉了一個消息隊列的使用場景,讓同步的程序變成異步運行。一個原本以同步方式進行運行的程序,用戶填寫註冊表並提交,寫入數據庫成功後,系統調用發送短信接口發送短信,短信發送後用戶會得到響應成功的返回信息。這種同步運行的方式有一個問題,就是調用短信接口的過程可能會耗費很多時間,所以會讓用戶等很久才能得到回覆,然而其實用戶註冊信息寫入數據庫之後的步驟都已經不需要用戶的介入了。面對這種場景,通過消息隊列將同步處理變爲異步處理可以很好的解決問題。用戶註冊信息寫入數據庫之後,將發送短信的請求寫入消息隊列暫存,然後發送短信的接口從消息隊列中拿消息發短信,用戶可以直接得到響應而不用一直等待短信發送完成後才能得到註冊成功的信息。

這種異步的思想在前端框架ajax中也有體現。
在這裏插入圖片描述

消息隊列的兩種工作模式

點對點模式

消息生產者生產消息發送到Queue中,然後消息消費者從Queue中取出並且消費消息。消息被消費以後,Queue中不再有存儲,所以消息消費者不可能消費到已經被消費的消息。Queue支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費。
在這裏插入圖片描述

發佈/訂閱模式

消息生產者(發佈)將消息發佈到topic中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不同,發佈到topic的消息會被所有訂閱者消費,而且消費者消費數據之後不會清除消息。Kafka使用的就是這種模式

在這裏插入圖片描述

Kafka架構

下面是一個Kafka集羣的架構圖:
在這裏插入圖片描述broker :
一臺kafka服務器就是一個broker。一個集羣由多個broker組成。一個broker可以容納多個topic。

topic :
可以理解爲一個隊列,生產者和消費者面向的都是一個topic。

producer :
消息生產者,就是向kafka broker發消息的客戶端。

consumer :
消息消費者,向kafka broker取消息的客戶端。

consumer group (CG):
消費者組,由多個consumer組成。消費者組內每個消費者負責消費不同分區的數據,一個分區只能由一個消費者消費;消費者組之間互不影響。所有的消費者都屬於某個消費者組,即消費者組是邏輯上的一個訂閱者。

partition:
爲了實現擴展性,一個非常大的topic可以分佈到多個broker(即服務器)上,一個topic可以分爲多個partition,每個partition是一個有序的隊列。

replica:
副本,爲保證集羣中的某個節點發生故障時,該節點上的partition數據不丟失,且kafka仍然能夠繼續工作,kafka提供了副本機制,一個topic的每個分區都有若干個副本,一個leader和若干個follower。

leader:
每個分區多個副本的“主”,生產者發送數據的對象,以及消費者消費數據的對象都是leader。

follower:
每個分區多個副本中的“從”,實時從leader中同步數據,保持和leader數據的同步。leader發生故障時,某個follower會成爲新的follower。

Kafka消息存儲機制

Kafka中消息是以topic進行分類的,生產者生產消息,消費者消費消息,都是面向topic的。
topic是邏輯上的概念。爲了方便擴展,並提高吞吐量,Kafka將一個topic分爲多個partition,partition是物理上的概念,每個partition對應於一個log文件,該log文件中存儲的就是producer生產的數據。爲提高可用性,Kafka還爲每個partition增加若干副本,防止因爲節點宕機而產生的消息丟失。

producer生產的數據會被不斷追加到partition也就是log文件的末端,且每條數據都有自己的offset。消費者組中的每個消費者,都會實時記錄自己消費到了哪個offset,以便出錯恢復時,從上次的位置繼續消費。
在這裏插入圖片描述
由於生產者生產的消息會不斷追加到log文件末尾,爲防止log文件過大導致數據定位效率低下,Kafka採取了分片和索引機制,將每個partition分爲多個segment。每個segment對應兩個文件,以.index爲後綴名的文件和以.log爲後綴名的文件。這些文件位於一個文件夾下,該文件夾的命名規則爲:topic名稱+分區序號。例如,first這個topic有三個分區,則其對應的文件夾爲first-0、first-1、first-2。

index和log文件以當前segment的第一條消息的offset命名。index文件存儲大量的索引信息,log文件存儲大量的數據,索引文件中的元數據指向對應數據文件中message的物理偏移地址。下圖爲index文件和log文件的示意圖:

在這裏插入圖片描述

Kafka分區策略

Kafka的分區就是將一個topic分成多個Partition進行存儲,這種方式讓Kafka集羣的擴展性得到提高,每個Partition可以通過調整以適應它所在的機器,因此整個集羣就可以適應任意大小的數據了。除了可以提高擴展性,通過分區還可以提高Kafka集羣的併發性能,因爲分區前consumer只能以topic爲單位進行讀寫,分區後consumer可以以Partition爲單位進行讀寫,Partition只是topic的一部分,所以這樣設計讓Kafka的併發性能非常好。

Kafka會將producer發送的數據封裝成一個ProducerRecord對象。封裝過程中需要設置分區策略。Kafka的分區策略一共有三種:

  1. 指明partition的情況下,直接將指明的值直接作爲partiton值;
  2. 沒有指明partition值但有key的情況下,將key的hash值與topic的partition數進行取餘得到 partition 值;
  3. 使用round-robin算法,在既沒有 partition 值又沒有 key 值的情況下,第一次調用時隨機生成一個整數(後面每次調用在這個整數上自增),將這個值與topic 可用的 partition 總數取餘得到 partition 值。

Kafka數據可靠性保證

Kafka中的數據可靠性,指的是producer發送給Kafka的數據,不會丟失,也不會重複。

爲保證producer正常發送數據,不受Kafka集羣中節點變動的影響,可靠的將數據發送到指定的topic,topic的每個partition收到producer發送的數據後,都需要向producer發送ack(acknowledgement的縮寫,確認收到),如果producer收到ack,就會進行下一輪的發送,否則重新發送數據。

Kafka向producer發送ack確認的時機

Kafka集羣有很多的follower和一個leader節點,producer向Kafka集羣發送數據後,各個節點會同步自己接收到的數據。Kafka在確保有follower與leader同步完成後,leader纔會發送ack,這樣才能保證如果發生leader宕機掛掉的情況,能迅速在follower中選舉出新的leader。至於在leader發送ack時有多少follower完成同步,是有兩種方案的,這兩種方案和選舉機制有關。方案一:有半數以上的follower同步完成,即可發送ack。方案二:全部的follower同步完成,纔可以發送ack。

方案一的優點是,延遲低,因爲不用等所有follower同步完成,但是缺點也非常明顯,選舉新的leader時,容忍n臺節點的故障需要2n+1個副本。也就是說,這種方式雖然發送ack的延遲很低,但是Kafka集羣中的各個節點需要存儲更多的數據副本。

方案二的優點是,選舉新的leader時,容忍n臺節點的故障需要n+1個副本,但是缺點是延遲高。

面對以上兩種方案,Kafka選擇了第二種方案,原因是,同樣爲了容忍n臺節點的故障,第一種方案需要2n+1個副本,而第二種方案只需要n+1個副本,而Kafka的每個分區都有大量的數據,第一種方案會造成大量數據的冗餘。雖然第二種方案的網絡延遲會比較高,但網絡延遲對Kafka的影響較小。

ISR(in-sync replica set )

由於Kafka要等到全部的follower同步完成,纔可以發送ack,那麼很有可能會出現以下情景:leader收到數據,所有follower都開始同步數據,但有一個follower,因爲某種故障,遲遲不能與leader進行同步,那leader就要一直等下去,直到它完成同步,才能發送ack。這種情況會讓Kafka的效率大大降低,爲了應對這種場景,Kafka設計了ISR。

Kafka的Leader維護了一個動態的ISR,全稱是in-sync replica set ,意爲和leader保持同步的follower集合。當ISR中的follower完成數據的同步之後,leader就會給follower發送ack。如果follower長時間未向leader同步數據,則該follower將被踢出ISR。如果是Leader發生故障,Kafka就會通過Zookeeper從ISR中選舉新的leader。

ack應答機制

對於某些不太重要的數據,對數據的可靠性要求不是很高,能夠容忍數據的少量丟失,沒必要等ISR中的follower全部接收成功。所以Kafka爲用戶提供了三種可靠性級別,用戶根據對可靠性和延遲的要求進行權衡,選擇不同的配置。acks有三種可用的參數配置,分別是0、1、-1:

acks=0:
producer不等待broker的ack,這一操作提供了一個最低的延遲,broker一接收到還沒有寫入磁盤就已經返回,當broker故障時有可能丟失數據。

acks=1:
producer等待broker的ack,partition的leader落盤成功後返回ack,如果在follower同步成功之前leader故障,那麼將會丟失數據。

acks= -1:
producer等待broker的ack,partition的leader和follower全部落盤成功後才返回ack。但是如果在follower同步完成後,broker發送ack之前,leader發生故障,那麼會造成數據重複。

默認情況下,acks會被設置爲-1,避免數據丟失的情況。

Kafka中的故障處理

Kafka集羣中,如果producer在發送數據時,如果follower和leader發生故障,那麼集羣就需要最一些故障處理,避免發生數據讀取的混亂。

Kafka故障處理過程有兩個概念:LEO和HW,他們是兩個位置標識符。
LEO:每個副本的最後一個offset。
HW:所有副本中最小的LEO,HW之前的數據對Consumer可見,HW之後的數據對Consumer不可見。

在這裏插入圖片描述

follower發生故障:

follower發生故障後會被臨時踢出ISR,待該follower恢復後,follower會讀取本地磁盤記錄的上次的HW,並將log文件高於HW的部分截取掉,從HW開始向leader進行同步。等該follower的LEO大於等於該Partition的HW,即follower追上leader之後,就可以重新加入ISR了。

leader發生故障:

leader發生故障之後,會從ISR中選出一個新的leader,之後,爲保證多個副本之間的數據一致性,其餘的follower會先將各自的log文件高於HW的部分截掉,然後從新的leader同步數據。

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