大數據雲計算——kafka組件

Kafka 是一個分佈式的基於發佈/訂閱模式的消息隊列(Message Queue),主要應用於大數據實時處理領域。

使用消息隊列的好處

1) 解耦

允許你獨立的擴展或修改兩邊的處理過程,只要確保它們遵守同樣的接口約束。

2) 可恢復性

系統的一部分組件失效時,不會影響到整個系統。消息隊列降低了進程間的耦合度,所以即使一個處理消息的進程掛掉,加入隊列中的消息仍然可以在系統恢復後被處理。

3) 緩衝

有助於控制和優化數據流經過系統的速度,解決生產消息和消費消息的處理速度不一致的情況。

4) 靈活性 & 峯值處理能力在訪問量劇增的情況下,應用仍然需要繼續發揮作用,但是這樣的突發流量並不常見。如果爲以能處理這類峯值訪問爲標準來投入資源隨時待命無疑是巨大的浪費。使用消息隊列能夠使關鍵組件頂住突發的訪問壓力,而不會因爲突發的超負荷的請求而完全崩潰。

5) 異步通信

很多時候,用戶不想也不需要立即處理消息。消息隊列提供了異步處理機制,允許用戶把一個消息放入隊列,但並不立即處理它。想向隊列中放入多少消息就放多少,然後在需要的時候再去處理它們。

消息隊列的兩種模式:

(1)點對點模式(一對一,消費者主動拉取數據,消息收到後消息清除)

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

(2)發佈/訂閱模式(一對多,消費者消費數據之後不會清除消息)

消息生產者(發佈)將消息發佈到 topic 中,同時有多個消息消費者(訂閱)消費該消

息。和點對點方式不同,發佈到 topic 的消息會被所有訂閱者消費。

 Kafka的基礎架構圖

Kafka中message to A-0 /meesage to A-1的消息分區的作用是:提高某一個topic的負載均衡的能力和提高併發度。

在0.9版本中Kafka集羣中也會在信息中的存儲在zookeeper中,消費者也會將一部分消息放置在Zookeeper 消費者保存的消費的位置的信息中。但是在0.9以後就採用的是本地的中。

1)Producer :消息生產者,就是向 kafka broker 發消息的客戶端;

2)Consumer :消息消費者,向 kafka broker 取消息的客戶端;

3)Consumer Group(CG):消費者組,由多個 consumer 組成。 消費者組內每個消費者負

責消費不同分區的數據,一個分區只能由一個組內消費者消費;消費者組之間互不影響。 所

有的消費者都屬於某個消費者組,即消費者組是邏輯上的一個訂閱者。

4)Broker:一臺kafka服務器就是一個broker。一個集羣由多個broker組成。一個 broker可以容納多個topic。

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

6)Partition:爲了實現擴展性,一個非常大的topic可以分佈到多個broker即服務器上,

一個 topic 可以分爲多個 partition,每個 partition 是一個有序的隊列;

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

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

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

Kafka中的消息在磁盤中的保存的是7天。

Kafka 工作流程及文件存儲機制

Kafka 中消息是以 topic 進行分類的, 生產者生產消息,消費者消費消息,都是面向 topic

的。topic 是邏輯上的概念,而 partition 是物理上的概念,每個 partition 對應於一個 log 文件,該 log 文件中存儲的就是 producer 生產的數據。 Producer 生產的數據會被不斷追加到該log 文件末端,且每條數據都有自己的 offset。 消費者組中的每個消費者, 都會實時記錄自己消費到了哪個 offset,以便出錯恢復時,從上次的位置繼續消費。

Kafka的文件存儲機制

“.index”文件存儲大量的索引信息,“.log”文件存儲大量的數據,索引文件中的元數據指向對應數據文件中 message 的物理偏移地址.

Kafka的生產者

分區策略

1)分區的原因

(1) 方便在集羣中擴展,每個 Partition 可以通過調整以適應它所在的機器,而一個 topic

又可以有多個 Partition 組成,因此整個集羣就可以適應任意大小的數據了;

(2) 可以提高併發,因爲可以以 Partition 爲單位讀寫了。

2) 分區的原則

我們需要將 producer 發送的數據封裝成一個 ProducerRecord 對象。

(1)指明 partition 的情況下,直接將指明的值直接作爲 partiton 值;

(2)沒有指明 partition 值但有 key 的情況下,將 key 的 hash 值與 topic 的 partition

數進行取餘得到 partition 值;

(3)既沒有 partition 值又沒有 key 值的情況下,第一次調用時隨機生成一個整數(後

面每次調用在這個整數上自增),將這個值與 topic 可用的 partition 總數取餘得到 partition值,也就是常說的 round-robin 算法

3.2生產數據的可靠性:

爲保證 producer 發送的數據,能可靠的發送到指定的 topic topic 的每個 partition 收到producer 發送的數據後, 都需要向 producer 發送 ackacknowledgement 確認收到) ,如果producer 收到 ack 就會進行下一輪的發送,否則重新發送數據。

Kafka 選擇了第二種方案,原因如下:

1.同樣爲了容忍 n 臺節點的故障,第一種方案需要 2n+1 個副本,而第二種方案只需要 n+1個副本,而 Kafka 的每個分區都有大量的數據, 第一種方案會造成大量數據的冗餘。

  1. 雖然第二種方案的網絡延遲會比較高,但網絡延遲對 Kafka 的影響較小。

ISR

採用第二種方案之後,設想以下情景: leader 收到數據,所有 follower 都開始同步數據,但有一個 follower,因爲某種故障,遲遲不能與 leader 進行同步,那 leader 就要一直等下去,直到它完成同步,才能發送 ack。這個問題怎麼解決呢?

Leader 維護了一個動態的 in-sync replica set (ISR),意爲和 leader 保持同步的 follower 集合。當 ISR 中的 follower 完成數據的同步之後, leader 就會給 follower 發送 ack。如果 follower長 時 間 未 向 leader 同 步 數 據 , 則 該 follower 將 被 踢 出 ISR , 該 時 間 閾 值 由replica.lag.time.max.ms 參數設定。 Leader 發生故障之後,就會從 ISR 中選舉新的 leader。

ack 應答機制

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

數據的重複的問題:

acks:

0:producer 不等待 broker 的 ack,這一操作提供了一個最低的延遲, broker 一接收到還

沒有寫入磁盤就已經返回,當 broker 故障時有可能丟失數據;

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

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

3.4數據的一致性問題:

LEO:指的是每個副本最大的 offset;

HW:指的是消費者能見到的最大的 offset, ISR 隊列中最小的 LEO。

1、follower 故障

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

2、leader 故障

leader 發生故障之後,會從 ISR 中選出一個新的 leader,之後,爲保證多個副本之間的數據一致性, 其餘的 follower 會先將各自的 log 文件高於 HW 的部分截掉,然後從新的 leader同步數據。注意: 這隻能保證副本之間的數據一致性,並不能保證數據不丟失或者不重複。

3.5Exactly Once 語義:

將服務器的 ACK 級別設置爲-1,可以保證 Producer 到 Server 之間不會丟失數據,即 AtLeast Once 語義。相對的,將服務器 ACK 級別設置爲 0,可以保證生產者每條消息只會被

發送一次,即 At Most Once 語義。At Least Once 可以保證數據不丟失,但是不能保證數據不重複;相對的, At Least Once

可以保證數據不重複,但是不能保證數據不丟失。 但是,對於一些非常重要的信息,比如說

交易數據,下游數據消費者要求數據既不重複也不丟失,即 Exactly Once 語義。 在 0.11 版本以前的 Kafka,對此是無能爲力的,只能保證數據不丟失,再在下游消費者對數據做全局

去重。對於多個下游應用的情況,每個都需要單獨做全局去重,這就對性能造成了很大影響。

0.11 版本的 Kafka,引入了一項重大特性:冪等性。所謂的冪等性就是指 Producer 不論

向 Server 發送多少次重複數據, Server 端都只會持久化一條。冪等性結合 At Least Once 語義,就構成了 Kafka 的 Exactly Once 語義。即:

At Least Once + 冪等性 = Exactly Once

要啓用冪等性,只需要將 Producer 的參數中 enable.idompotence 設置爲 true 即可。 Kafka的冪等性實現其實就是將原來下游需要做的去重放在了數據上游。開啓冪等性的 Producer 在初始化的時候會被分配一個 PID,發往同一 Partition 的消息會附帶 Sequence Number。而Broker 端會對<PID, Partition, SeqNumber>做緩存,當具有相同主鍵的消息提交時, Broker 只會持久化一條。但是 PID 重啓就會變化,同時不同的 Partition 也具有不同主鍵,所以冪等性無法保證跨分區跨會話的 Exactly Once。

Kafka的消費者

consumer 採用 pull(拉)模式從 broker 中讀取數據。push(推)模式很難適應消費速率不同的消費者,因爲消息發送速率是由 broker 決定的。它的目標是儘可能以最快速度傳遞消息,但是這樣很容易造成 consumer 來不及處理消息,典型的表現就是拒絕服務以及網絡擁塞。而pull 模式則可以根據 consumer 的消費能力以適當的速率消費消息。pull 模式不足之處是,如果 kafka 沒有數據,消費者可能會陷入循環中,一直返回空數據。針對這一點,Kafka 的消費者在消費數據時會傳入一個時長參數 timeout,如果當前沒有數據可供消費,consumer 會等待一段時間之後再返回,這段時長即爲 timeout。

4.1分區分配策略:

一個 consumer group 中有多個 consumer,一個 topic 有多個 partition,所以必然會涉及到 partition 的分配問題,即確定那個 partition 由哪個 consumer 來消費。Kafka 有兩種分配策略,一是 RoundRobin,一是 Range。

RoundRobin:

Range:(默認採用的方式,就是的一個消費者訂閱了兩個或者多個分配的策略)

offset 的維護

由於consumer在消費過程中可能會出現斷電宕機等故障,consumer恢復後,需要從故障前的位置的繼續消費,所consumer需要實時記錄自己消費到了哪個offset,以便故障恢復後繼續消費

Kafka 0.9 版本之前,consumer 默認將 offset 保存在 Zookeeper 中,從 0.9 版本開始,

consumer 默認將offset 保存在Kafka一個內置的topic中,該topic爲__consumer_offsets。

Kafka 高效讀寫數據原理

0)分佈式的 有分區的操作。

1)順序寫磁盤

Kafka 的producer 生產數據,要寫入到 log 文件中,寫的過程是一直追加到文件末端,爲順序寫。 官網有數據表明,同樣的磁盤,順序寫能到 600M/s,而隨機寫只有 100K/s。這與磁盤的機械機構有關,順序寫之所以快,是因爲其省去了大量磁頭尋址的時間。

2)零複製技術

Zookeeper 在 Kafka 中的作用

Kafka 集羣中有一個 broker 會被選舉爲 Controller,負責管理集羣 broker 的上下線,所有 topic 的分區副本分配和 leader 選舉等工作。Controller 的管理工作都是依賴於 Zookeeper 的。以下爲 partition 的 leader 選舉過程:

Kafka的事務

6.1Producer 事務 使用的是PID

爲了實現跨分區跨會話的事務,需要引入一個全局唯一的 Transaction ID,並將 Producer獲得的PID 和Transaction ID 綁定。這樣當Producer 重啓後就可以通過正在進行的 TransactionID 獲得原來的 PID。

爲了管理Transaction,Kafka 引入了一個新的組件 Transaction Coordinator。 Producer 就是通過和 Transaction Coordinator 交互獲得 Transaction ID 對應的任務狀態。 TransactionCoordinator 還負責將事務所有寫入 Kafka 的一個內部 Topic,這樣即使整個服務重啓,由於事務狀態得到保存,進行中的事務狀態可以得到恢復,從而繼續進行。

6.2Consumer 事務 就是維護一個offerset

上述事務機制主要是從 Producer 方面考慮,對於 Consumer 而言,事務的保證就會相對較弱,尤其時無法保證 Commit 的信息被精確消費。這是由於 Consumer 可以通過 offset 訪問任意信息,而且不同的 Segment File 生命週期不同,同一事務的消息可能會出現重啓後被刪除的情況

Kafka的API 策略

7.1生產者API

Kafka 的 Producer 發送消息採用的是異步發送的方式。在消息發送的過程中,涉及到了兩個線程——main 線程和 Sender 線程,以及一個線程共享變量——RecordAccumulator。main 線程將消息發送給 RecordAccumulator, Sender 線程不斷從 RecordAccumulator 中拉取消息發送到 Kafka broker。

消費者API

Consumer 消費數據時的可靠性是很容易保證的,因爲數據在 Kafka 中是持久化的,故不用擔心數據丟失問題。由於 consumer 在消費過程中可能會出現斷電宕機等故障, consumer 恢復後,需要從故障前的位置的繼續消費,所以 consumer 需要實時記錄自己消費到了哪個 offset,以便故障恢復後繼續消費。所以 offset 的維護是 Consumer 消費數據是必須考慮的問題。

手動提交 offset

雖然自動提交 offset 十分簡介便利,但由於其是基於時間提交的, 開發人員難以把握offset 提交的時機。因此 Kafka 還提供了手動提交 offset 的 API。手動提交 offset 的方法有兩種:分別是 commitSync(同步提交) 和 commitAsync(異步提交) 。兩者的相同點是,都會將本次 poll 的一批數據最高的偏移量提交;不同點是,commitSync 阻塞當前線程,一直到提交成功,並且會自動失敗重試(由不可控因素導致,也會出現提交失敗);而 commitAsync 則沒有失敗重試機制,故有可能提交失敗

數據漏消費和重複消費分析

無論是同步提交還是異步提交offset,都有可能會造成數據的漏消費或者重複消費。先提交 offset 後消費,有可能造成數據的漏消費;而先消費後提交 offset,有可能會造成數據的重複消費。

自定義的offset來解決是的數據的漏消費和重複消費的問題

Kafka 0.9 版本之前, offset 存儲在 zookeeper, 0.9 版本及之後,默認將 offset 存儲在 Kafka

的一個內置的 topic 中。除此之外, Kafka 還可以選擇自定義存儲 offset。offset 的維護是相當繁瑣的, 因爲需要考慮到消費者的 Rebalace。當有新的消費者加入消費者組、 已有的消費者推出消費者組或者所訂閱的主題的分區發生變化,就會觸發到分區的重新分配,重新分配的過程叫做 Rebalance。消費者發生 Rebalance 之後,每個消費者消費的分區就會發生變化。 因此消費者要首先獲取到自己被重新分配到的分區,並且定位到每個分區最近提交的 offset 位置繼續消費。

Kafka的面試問題

Kafka 中的 ISR(InSyncRepli)、 OSR(OutSyncRepli)、 AR(AllRepli)代表什麼?

Kafka 中的 HW、 LEO 等分別代表什麼?

Kafka 中是怎麼體現消息順序性的?

Kafka 中的分區器、序列化器、攔截器是否瞭解?它們之間的處理順序是什麼?

Kafka 生產者客戶端的整體結構是什麼樣子的?使用了幾個線程來處理?分別是什麼?

“消費組中的消費者個數如果超過 topic 的分區,那麼就會有消費者消費不到數據”這句話是否正確?

消費者提交消費位移時提交的是當前消費到的最新消息的 offset 還是 offset+1?

有哪些情形會造成重複消費?

那些情景會造成消息漏消費?

當你使用 kafka-topics.sh 創建(刪除)了一個 topic 之後Kafka背後會執行什麼邏輯?

1)會在 zookeeper 中的/brokers/topics 節點下創建一個新的 topic 節點,如:

/brokers/topics/first

2)觸發 Controller 的監聽程序

3) kafka Controller 負責 topic 的創建工作,並更新 metadata cache

topic 的分區數可不可以增加?如果可以怎麼增加?如果不可以,那又是爲什麼?

topic 的分區數可不可以減少?如果可以怎麼減少?如果不可以,那又是爲什麼?

Kafka 有內部的 topic 嗎?如果有是什麼?有什麼所用?

Kafka 分區分配的概念?

簡述 Kafka 的日誌目錄結構?

如果我指定了一個 offset, Kafka Controller 怎麼查找到對應的消息?

聊一聊 Kafka Controller 的作用?

Kafka 中有那些地方需要選舉?這些地方的選舉策略又有哪些?

失效副本是指什麼?有那些應對措施?

Kafka 的哪些設計讓它有如此高的性能?

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