關(guān)于Kafka,你需要知道的一切
前言
Kafka 一開始是LinkedIn這家公司研發(fā)的技術(shù),它是一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng),現(xiàn)在已成為大多數(shù)公司使用的技術(shù),我們公司也不例外。那么你對kafka的了解有多少呢?那么本文就帶你過一過kafka中的一些關(guān)鍵要點。
為什么我們需要Kafka?

訂單發(fā)生時通知其他服務(wù)
在我們深入研究之前,有必要重新審視一下 Kafka 最初被發(fā)明的原因。
想象一下為一家電子商務(wù)公司維護一組微服務(wù)。
下訂單時,訂單服務(wù)要通知很多服務(wù),如下:
- 錢包服務(wù)從用戶賬戶中扣除金額
- 倉庫服務(wù)扣除物品的庫存數(shù)量
- 物流服務(wù)發(fā)貨
當(dāng)訂單服務(wù)要通知更多的服務(wù)時,復(fù)雜度就要進一步提高。
訂單服務(wù)器需要做以下事情:
- 跟蹤都通知了誰
- 確保所有其他服務(wù)確實收到并處理
- 和其他服務(wù)建立直接的連接和處理不同的響應(yīng)
發(fā)現(xiàn)沒有,這很難擴展,如果接入更多的系統(tǒng),訂單系統(tǒng)的開發(fā)天天996了。
因此,Kafka就很好的解決這樣的問題。
消息隊列與發(fā)布訂閱

訂單服務(wù)器只是將消息發(fā)布到 Pub-Sub/Message Queue
消息隊列和發(fā)布訂閱系統(tǒng)都是解決上述問題的關(guān)鍵。
也就是說,不是讓訂單服務(wù)維護直接和各種系統(tǒng)打交道,而是將事件發(fā)布或者推送到中間隊列中,對隊列感興趣的服務(wù)器(通常稱為消費者)訂閱隊列并相應(yīng)地消費事件。
那么消息隊列和發(fā)布訂閱系統(tǒng)有什么區(qū)別呢?
消息隊列
消息隊列是一種類似隊列的結(jié)構(gòu),其中消息被發(fā)布并且僅被消費一次。這對于非冪等的進程很方便,事件應(yīng)該只由一個消費者處理,RabbitMQ 最初被設(shè)計成一個消息隊列。
發(fā)布-訂閱系統(tǒng)
另一方面,發(fā)布訂閱系統(tǒng)允許多個消費者多次使用一條消息。訂單事件被多個系統(tǒng)訂閱消費,所以更適合發(fā)布訂閱系統(tǒng)模式。Kafka 被設(shè)計為既是消息隊列又是發(fā)布訂閱系統(tǒng)。
Kafka組件
為了充分理解 Kafka 的工作原理,讓我們剖析 下Kafka 的各個組件。
Kafka Broker 和集群

Kafka 代理和集群
Kafka 只不過是一個管理數(shù)據(jù)發(fā)布和消費的服務(wù)。
一個Kafka Broker就是一個Kafka服務(wù)。維護同一組主題的一組Broker稱為 Kafka 集群。
發(fā)布者Publisher

發(fā)布者發(fā)布到 Kafka 代理
將數(shù)據(jù)發(fā)布到 Kafka Broker的服務(wù)稱為發(fā)布者。我們之前提到的Order服務(wù)是發(fā)布者的一個例子。
消費者Consumer

消費者從 Kafka 代理消費
另一方面,消費者是訂閱和消費來自 Kafka 主題的數(shù)據(jù)的服務(wù)。
在我們前面的示例中,Wallet服務(wù)器、Warehouse服務(wù)器和Logistic服務(wù)器充當(dāng)Order主題的消費者。
主題Topic

Kafka 代理中的不同主題
Kafka 代理維護不同類型的事件,例如:
- 訂單創(chuàng)建事件
- 訂單取消事件
- 缺貨事件
這些事件中的每一個都是大量的數(shù)據(jù)流。主題只是一種事件或數(shù)據(jù)流。
發(fā)布到 Kafka 時,發(fā)布者指定消息應(yīng)發(fā)布到的主題。
主題是一個只能追加的日志。將消息附加到主題類似于將數(shù)據(jù)附加到隊列,它需要 O(1) 常數(shù)時間,因此速度非???。
分區(qū)Partition

主題被分片成分區(qū)
主題是存儲在 Kafka Broker上的追加的日志。
隨著消息數(shù)量的增加,Broker在特定主題上存儲的數(shù)據(jù)量是有限的,那怎么辦呢?
可以將一個主題拆分為多個分區(qū),而不是將所有數(shù)據(jù)一直追加到同一個主體日志中,而是每個分區(qū)存儲特定主題的一部分?jǐn)?shù)據(jù),這類似于數(shù)據(jù)庫分片。
主題基于分區(qū)進行分片。同一主題的分區(qū)可以存儲在相同或不同的 Kafka Broker上。這使得 Kafka 具有高度可擴展性。
發(fā)布者在發(fā)布之前指定消息的主題和分區(qū)。因此,發(fā)布者有責(zé)任確保分區(qū)邏輯不會導(dǎo)致熱分區(qū)。
偏移量offset

分區(qū)中的偏移量
偏移量是分區(qū)中消息的唯一索引。
當(dāng) Kafka 將數(shù)據(jù)推送給消費者時,它會增加并跟蹤當(dāng)前的偏移量。
有兩種類型的偏移量值得強調(diào):
- 當(dāng)前偏移量:保存在Consumer客戶端中,它表示Consumer希望收到的下一條消息的序號。
- 提交的偏移量: 保存在Broker上,它表示Consumer已經(jīng)確認(rèn)消費過的消息的序號。
消費者組
如前所述,Kafka 既是消息隊列又是發(fā)布訂閱系統(tǒng)。這是通過消費者群體優(yōu)雅地設(shè)計的。

Consumer可以消費多個partition,但是每個partition只能被同組的一個consumer消費
消費者組由一組消費相同主題的消費者組成。
一個消費者一次可以消費多個分區(qū)。但是,每個分區(qū)只能由同一組中的一個且只有一個消費者使用。

一個分區(qū)可以被來自不同消費者組的多個消費者消費
消費者組是相互獨立的,不同的組可以同時使用同一主題并使用不同的偏移量。
通過將所有消費者放在同一組中來實現(xiàn)隊列,同一分區(qū)中的消息不會被來自相似組的不同消費者并發(fā)消費。
在分區(qū)級別實現(xiàn)隊列。因此,如果想要保證順序處理數(shù)據(jù)流,發(fā)布者必須確保數(shù)據(jù)始終被推送到同一個分區(qū)。
另一方面,發(fā)布訂閱系統(tǒng)是通過多個消費者組實現(xiàn)的。消費者群體彼此之間一無所知,并使用單獨的偏移量消費數(shù)據(jù)。
在前面的例子中,Wallet服務(wù)器和Logistic服務(wù)器分別屬于不同的消費者組,分別消費數(shù)據(jù)。
重新平衡和分區(qū)分配

當(dāng)新消費者加入時,Kafka 會重新平衡
如果一組中只有一個消費者,則該消費者將負(fù)責(zé)消費所有可用分區(qū)。
當(dāng)一個新的consumer加入group時,比如增加了一個新的server實例,Kafka會進行rebalancing,將一部分partitions分配給新的consumer。
這確保了每個消費者共享相同數(shù)量的工作,從而使 Kafka 具有可擴展性。
Kafka 使用自己的重新平衡策略進行分區(qū)重新分配,這值得另一篇單獨的文章來介紹。
復(fù)制Replica

副本在分區(qū)級別創(chuàng)建,可以存儲在相同/不同的代理中
單點故障是每個分布式系統(tǒng)的噩夢,Kafka也不例外。
如果Broker出現(xiàn)故障,存儲在代理上的分區(qū)可能不可用。因此,副本是在分區(qū)級別創(chuàng)建的。
為每個分區(qū)創(chuàng)建副本,并存儲在不同的 Kafka 代理上。為每個分區(qū)選舉一個領(lǐng)導(dǎo)者來為發(fā)布者和消費者服務(wù)。
副本不斷從leader同步數(shù)據(jù)。當(dāng) leader 宕機時,Zookeeper 會加入進來幫助進行 leader 的選舉。
Zookeeper
正如您可能正在思考的那樣,我們的難題中缺少一些部分。
- 我們?nèi)绾沃烂總€分區(qū)的領(lǐng)導(dǎo)者?
- 如何知道每個主題的分區(qū)數(shù)?
- 我們?nèi)绾沃烂總€消費者組的最新偏移量?
- 我們?nèi)绾沃烂總€消費者組中有多少消費者?
這就是Zookeeper發(fā)揮作用的地方。它是一個分布式協(xié)調(diào)服務(wù)系統(tǒng),用于存儲元數(shù)據(jù)并協(xié)調(diào) Kafka 中的分布式系統(tǒng)。
主要涉及以下方面:
- 領(lǐng)導(dǎo)者選舉——確保每個分區(qū)都有一個領(lǐng)導(dǎo)者
- 集群成員資格——跟蹤集群中的所有功能代理
- 主題配置——跟蹤所有可用主題、分區(qū)及其副本
- 訪問控制列表——跟蹤每個組中消費者的數(shù)量及其訪問權(quán)限
- 配額——跟蹤每個客戶端可以讀取和寫入的數(shù)據(jù)量
長輪詢
Kafka 如何向消費者推送消息?
RabbitMQ 采用推送模型。代理與消費者保持持久的 TCP 連接,并在有可用數(shù)據(jù)時將數(shù)據(jù)推送給他們。
然而,推送模型可能會淹沒消費者。如果代理推送數(shù)據(jù)的速度快于消費者處理數(shù)據(jù)的速度,消費者可能會落后。RabbitMQ 確實有一個解決方案,這邊就不展開討論了。
長輪詢等待方式方法
Kafka 使用拉模型,也就是長輪詢。消費者定期從代理拉取數(shù)據(jù)。因此,消費者只有在準(zhǔn)備好時才能拉取數(shù)據(jù)。但是,如果分區(qū)上沒有數(shù)據(jù),來自消費者的定期輪詢可能會導(dǎo)致資源浪費。
Kafka通過使用“l(fā)ong polling”等待模式的方式解決了這個問題。簡而言之,如果分區(qū)上沒有數(shù)據(jù),Kafka 不會返回空響應(yīng)。相反,broker保持連接并等待數(shù)據(jù)進入,然后再將其返回給消費者。
這減輕了當(dāng)分區(qū)上沒有數(shù)據(jù)時消費者頻繁輪詢并防止資源浪費。
總結(jié)
本文總結(jié)了Kafka這個組件的基礎(chǔ)知識,希望讓大家對Kafka有一個宏觀的認(rèn)識,感興趣的再深入分析底層的實現(xiàn)機制。































