新聞中心
九張圖帶你了解Kafka
作者:聞數(shù)起舞 2020-06-28 07:39:44
開(kāi)發(fā)
架構(gòu)
Kafka 現(xiàn)在,每個(gè)公司都在互聯(lián)網(wǎng)系統(tǒng)中使用Kafka。 Kafka似乎是解決分布式并提高系統(tǒng)吞吐量的最佳松耦合解決方案之一。

讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名申請(qǐng)、網(wǎng)站空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、武陵源網(wǎng)站維護(hù)、網(wǎng)站推廣。
現(xiàn)在,每個(gè)公司都在互聯(lián)網(wǎng)系統(tǒng)中使用Kafka。 Kafka似乎是解決分布式并提高系統(tǒng)吞吐量的最佳松耦合解決方案之一。
我大約6年前開(kāi)始使用Kafka。 當(dāng)時(shí),我在Aerohive工作。 為了解決企業(yè)wifi設(shè)備帶來(lái)的大量日志,傳統(tǒng)的消息傳遞系統(tǒng)RabbitMQ和ActiveMQ已經(jīng)不堪重負(fù)。
此時(shí),Kafka誕生了(2012年),并提供了一個(gè)完美的解決方案。
重要要點(diǎn):
- 解釋消息隊(duì)列及其優(yōu)勢(shì)
- 解釋卡夫卡中的組成部分(經(jīng)紀(jì)人,生產(chǎn)者,消費(fèi)者,消費(fèi)者組)
- 解釋為什么卡夫卡這么快
什么是消息系統(tǒng)?
在了解Kafka之前,如果您不知道什么是Message Queue,則需要添加它。 如果您已經(jīng)知道,則可以跳到下一段。
> Morden Distributed System
如上圖所述,Message Queue是一個(gè)在兩個(gè)系統(tǒng)之間傳輸和存儲(chǔ)消息的中間件。 其外觀(guān)具有以下優(yōu)點(diǎn):
- 去耦:只要您確保雙方遵守相同的接口約束,就可以獨(dú)立擴(kuò)展或修改雙方的處理。
- 冗余:消息隊(duì)列將數(shù)據(jù)保留到完成處理為止,從而避免了數(shù)據(jù)丟失的風(fēng)險(xiǎn)。 在許多消息隊(duì)列采用的"插入-獲取-刪除"范式中,從隊(duì)列中刪除消息之前,您的處理系統(tǒng)需要清楚地表明該消息已被處理,以確保您的數(shù)據(jù)安全保存。 完成使用它。
- 可伸縮性:由于消息隊(duì)列使您的處理脫鉤,因此,只要添加其他處理,就很容易增加消息入隊(duì)和處理的頻率。
- 靈活性和高峰處理能力:在流量急劇增加的情況下,應(yīng)用程序仍然需要繼續(xù)發(fā)揮作用,但是這種突發(fā)流量并不是標(biāo)準(zhǔn)的。 毫無(wú)疑問(wèn),以能夠處理高峰訪(fǎng)問(wèn)為標(biāo)準(zhǔn)來(lái)投資資源是巨大的浪費(fèi)。 消息隊(duì)列的使用可使關(guān)鍵組件承受突然的訪(fǎng)問(wèn)壓力,而不會(huì)由于意外的過(guò)載請(qǐng)求而完全崩潰。
- 可恢復(fù)性:當(dāng)系統(tǒng)的某些部分發(fā)生故障時(shí),它不會(huì)影響整個(gè)系統(tǒng)。 消息隊(duì)列減少了進(jìn)程之間的耦合,因此,即使處理消息的進(jìn)程掛斷了,恢復(fù)系統(tǒng)后仍可以處理添加到隊(duì)列中的消息。
- 順序保證:在大多數(shù)使用情況下,數(shù)據(jù)處理的順序至關(guān)重要。 大多數(shù)消息隊(duì)列最初都是經(jīng)過(guò)排序的,可以保證數(shù)據(jù)將按特定順序進(jìn)行處理。 (Kafka保證分區(qū)中消息的順序)
- 緩沖:有助于控制和優(yōu)化通過(guò)系統(tǒng)的數(shù)據(jù)流速度,并解決生產(chǎn)消息和消耗消息的不一致處理速度。
- 異步通信:很多時(shí)候,用戶(hù)不希望也不需要立即處理消息。 消息隊(duì)列提供了一種異步處理機(jī)制,該機(jī)制允許用戶(hù)將消息放入隊(duì)列,但不能快速處理。 將所需數(shù)量的消息放入隊(duì)列,然后在需要時(shí)進(jìn)行處理。
同時(shí),我認(rèn)為最大的缺點(diǎn)是復(fù)雜性,其優(yōu)點(diǎn)完全可以忽略不計(jì)。
Kafka如何運(yùn)作?
對(duì)于Kafka而言,從獨(dú)立的角度來(lái)看,其中包括生產(chǎn)者,消費(fèi)者和經(jīng)紀(jì)人。
- 生產(chǎn)者負(fù)責(zé)將消息發(fā)送到代理固定主題
- 代理維護(hù)一組主題并管理該主題中的分區(qū)
- 消費(fèi)者,負(fù)責(zé)從經(jīng)紀(jì)人的相應(yīng)主題中提取消息
> Kafka components
如圖所示,不同的生產(chǎn)者可以將消息發(fā)送到多個(gè)主題的多個(gè)分區(qū),而消費(fèi)者也可以從各種主題中消費(fèi)。
生產(chǎn)者和消費(fèi)者完全孤立。
在此設(shè)計(jì)中,它充分體現(xiàn)了去耦,靈活性和峰值處理能力,訂單保證和異步通信。
Kafka如何在分布式環(huán)境中工作?
1. 集群
多個(gè)代理和副本。
- 副本,分區(qū)副本,以確保分區(qū)的高可用性
- 領(lǐng)導(dǎo)者,副本,生產(chǎn)者和使用者中的角色僅與領(lǐng)導(dǎo)者互動(dòng)
- 追隨者中的一個(gè)角色,副本以復(fù)制領(lǐng)導(dǎo)者中的數(shù)據(jù)。
Kafka如何保證冗余,可恢復(fù)性和高可用性?
即使某些節(jié)點(diǎn)發(fā)生故障,復(fù)制也可以提供高可用性:
- 生產(chǎn)者可以繼續(xù)發(fā)布消息
- 使用者可以繼續(xù)接收消息。 有兩種方案可確保強(qiáng)而一致的數(shù)據(jù)復(fù)制:主備份復(fù)制和基于仲裁的復(fù)制。 兩種方案都需要選舉一位領(lǐng)導(dǎo)者,其他人則作為跟隨者。 所有寫(xiě)操作都發(fā)送給領(lǐng)導(dǎo)者,然后領(lǐng)導(dǎo)者將消息發(fā)送給跟隨者。
基于仲裁的復(fù)制可以使用筏和Paxos等算法,例如Zookeeper,Google Spanner等。在2n +1個(gè)節(jié)點(diǎn)的情況下,最多可以容忍n個(gè)節(jié)點(diǎn)故障。
僅在成功接收到消息后,基于主數(shù)據(jù)庫(kù)的復(fù)制以及其他主數(shù)據(jù)庫(kù)和備份的寫(xiě)入操作才能成功。 對(duì)于n個(gè)節(jié)點(diǎn),最多可以容忍n-1個(gè)節(jié)點(diǎn)故障,例如Microsoft的PacifiaA。
這兩種方法各有優(yōu)缺點(diǎn)。
- 基于仲裁的延遲可能比主備份更好,因?yàn)榛谥俨玫姆椒▋H需要一些節(jié)點(diǎn)即可成功寫(xiě)入以返回。
- 在相同數(shù)量的節(jié)點(diǎn)下,基于主備份的復(fù)制可以承受更多的節(jié)點(diǎn)故障,并且只要一個(gè)節(jié)點(diǎn)處于活動(dòng)狀態(tài)就可以正常工作。
- 在有兩個(gè)節(jié)點(diǎn)的情況下,主備份可以提供容錯(cuò)能力,基于仲裁的方法至少需要三個(gè)節(jié)點(diǎn)。
Kafka采用第二種方法,即主從模式,該方法主要基于容錯(cuò)能力,并且在兩個(gè)節(jié)點(diǎn)的情況下也可以提供高可用性。
如果節(jié)點(diǎn)很慢怎么辦?
首先,這種情況很少發(fā)生。 如果發(fā)生這種情況,您可以設(shè)置超時(shí)參數(shù)來(lái)處理這種情況。
Kafka的復(fù)制適用于分區(qū)。
例如,在上圖中,有四個(gè)代理,一個(gè)主題和兩個(gè)分區(qū)。 復(fù)制因子是三。 當(dāng)生產(chǎn)者發(fā)送消息時(shí),它將選擇一個(gè)分區(qū),例如topic1-part1分區(qū),將消息發(fā)送到該分區(qū)的領(lǐng)導(dǎo)者,broker2,broker3將拉出消息,消息被拉出后,從屬將發(fā)送ack到 主機(jī),這次主機(jī)僅提交此日志。
在此過(guò)程中,生產(chǎn)者有兩種選擇:
- 一種是等待所有副本被成功提取,然后生產(chǎn)者盤(pán)收到成功的響應(yīng)。
- 另一種是等待領(lǐng)導(dǎo)者成功編寫(xiě)并獲得成功的響應(yīng)。
在第一個(gè)中,您可以確保在異常情況下不會(huì)丟失消息,但是延遲會(huì)減少。 后者的等待時(shí)間已大大改善,但是一旦出現(xiàn)異常情況,從屬服務(wù)器將無(wú)法在領(lǐng)導(dǎo)掛起之前提取最新消息。 在這種情況下,可能會(huì)丟失該消息。
2. 客戶(hù)群
消費(fèi)者使用消費(fèi)者組名稱(chēng)標(biāo)記自己,并且發(fā)布到主題的每條記錄都會(huì)傳遞到每個(gè)訂閱消費(fèi)者組中的一個(gè)消費(fèi)者實(shí)例。 使用者實(shí)例可以在單獨(dú)的進(jìn)程中或在單獨(dú)的機(jī)器上。
如果所有使用者實(shí)例都具有相同的使用者組,那么將在這些使用者實(shí)例上有效地平衡記錄。
如果所有使用者實(shí)例具有不同的使用者組,則每條記錄將廣播到所有使用者進(jìn)程形成正式文件
簡(jiǎn)而言之,消費(fèi)者群體是Kafka生態(tài)系統(tǒng)中的真正消費(fèi)者。
3. 控制者
上圖是2015年Kafka Controller的設(shè)計(jì)圖。 Controller和ZK共同構(gòu)建了Kafka的高層架構(gòu),該架構(gòu)主要完成以下任務(wù):
- 管理經(jīng)紀(jì)人和消費(fèi)者的動(dòng)態(tài)加入和離開(kāi)。
- 觸發(fā)負(fù)載平衡。 當(dāng)經(jīng)紀(jì)人或使用者加入或離開(kāi)時(shí),將觸發(fā)負(fù)載均衡算法,從而為一個(gè)使用者組中的多個(gè)使用者進(jìn)行訂閱負(fù)載均衡。
- 維護(hù)每個(gè)分區(qū)的消耗關(guān)系和消耗信息。
為什么Kafka這么快?
Kafka中有一個(gè)過(guò)程,其中大量網(wǎng)絡(luò)數(shù)據(jù)被持久保存到磁盤(pán)(生產(chǎn)者到代理),并且磁盤(pán)文件通過(guò)網(wǎng)絡(luò)發(fā)送(經(jīng)紀(jì)人到消費(fèi)者)。
此過(guò)程的性能直接影響Kafka的整體吞吐量。
1. 零復(fù)制
上圖的左側(cè)是傳統(tǒng)的四個(gè)副本和四個(gè)上下文切換。
- 首先,通過(guò)系統(tǒng)調(diào)用將文件數(shù)據(jù)讀入內(nèi)核狀態(tài)緩沖區(qū)(DMA復(fù)制)
- 然后,應(yīng)用程序?qū)?nèi)存狀態(tài)緩沖區(qū)數(shù)據(jù)讀入用戶(hù)狀態(tài)緩沖區(qū)(CPU副本)
- 接下來(lái),用戶(hù)程序在通過(guò)套接字發(fā)送數(shù)據(jù)時(shí)讀取用戶(hù)狀態(tài)緩沖區(qū)數(shù)據(jù)。復(fù)制到內(nèi)核狀態(tài)緩沖區(qū)(CPU復(fù)制)
- 最后,通過(guò)DMA復(fù)制將數(shù)據(jù)復(fù)制到NIC緩沖區(qū)。 同時(shí),它伴隨著四個(gè)上下文切換。
在上圖的右側(cè),Kafka使用Linux 2.4+內(nèi)核sendfile系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn)零復(fù)制。
- 數(shù)據(jù)通過(guò)DMA復(fù)制到內(nèi)核狀態(tài)緩沖區(qū)
- 它通過(guò)DMA直接復(fù)制到NIC緩沖區(qū),而無(wú)需CPU復(fù)制
因?yàn)閟endfile調(diào)用完成了整個(gè)文件讀取網(wǎng)絡(luò)的傳輸,所以整個(gè)過(guò)程只有兩個(gè)上下文切換,因此性能大大提高了。
準(zhǔn)確地說(shuō),Kafka的數(shù)據(jù)傳輸是通過(guò)TransportLayer完成的,其子類(lèi)PlaintextTransportLayer通過(guò)Java NIO的FileChannel的transferTo和transferFrom方法實(shí)現(xiàn)了零復(fù)制。
2. 順序訪(fǎng)問(wèn)
> Compare
上圖顯示,即使順序讀取磁盤(pán),順序訪(fǎng)問(wèn)的巨大優(yōu)勢(shì)也比基于內(nèi)存的隨機(jī)訪(fǎng)問(wèn)要好。
Kafka中的每條消息都會(huì)被追加,并且不會(huì)從中間寫(xiě)入或刪除消息,以確保順序訪(fǎng)問(wèn)磁盤(pán)。
即使是順序讀取和寫(xiě)入,過(guò)多的小型IO操作也會(huì)導(dǎo)致磁盤(pán)瓶頸,并且這次變成了隨機(jī)讀取和寫(xiě)入。
Kafka的策略是匯總消息并分批發(fā)送,以最大程度地減少對(duì)磁盤(pán)的訪(fǎng)問(wèn)。 因此,Kafka的主題和分區(qū)的數(shù)量不應(yīng)過(guò)多。
通常,經(jīng)過(guò)64個(gè)主題/分區(qū)之后,Kafka的性能將急劇下降。
3. 段日志
- Kafka使用該主題來(lái)管理消息。 每個(gè)主題包含多個(gè)部分,每個(gè)部分對(duì)應(yīng)一個(gè)邏輯日志,并且由多個(gè)部分組成。
- 多個(gè)消息存儲(chǔ)在每個(gè)段中。 它的邏輯位置決定了消息ID,即消息ID可以直接定位到消息的存儲(chǔ)位置,從而避免了ID到位置的附加映射。
- 每個(gè)部分對(duì)應(yīng)于內(nèi)存中的一個(gè)索引,并記錄每個(gè)段中第一條消息的偏移量。
- 發(fā)布者發(fā)送給特定主題的消息將平均分配到多個(gè)部分(隨機(jī)或根據(jù)用戶(hù)指定的回調(diào)函數(shù)),代理接收已發(fā)布的消息并將消息添加到相應(yīng)部分的最后一段。 當(dāng)段上的消息數(shù)達(dá)到配置的值或消息發(fā)布時(shí)間超過(guò)閾值時(shí),段上的消息將刷新到磁盤(pán),只有刷新到磁盤(pán)的消息訂閱者才能訂閱該消息。 段達(dá)到特定大小后,將不再有數(shù)據(jù)寫(xiě)入該段,代理將創(chuàng)建一個(gè)新段。
這種分區(qū)分割和索引設(shè)計(jì)不僅提高了數(shù)據(jù)讀取的效率,而且還提高了數(shù)據(jù)操作的并行性。
4. 高性能Broker
Kafka在Broker中的設(shè)計(jì)也是其如此之快的原因之一。
首先,客戶(hù)端發(fā)送的所有請(qǐng)求都將發(fā)送到接受器。 代理中將默認(rèn)有三個(gè)線(xiàn)程。 這三個(gè)線(xiàn)程稱(chēng)為處理器。
接受者將不會(huì)對(duì)客戶(hù)的請(qǐng)求進(jìn)行任何處理,而是直接對(duì)其進(jìn)行封裝。 將socketChannel發(fā)送到這些處理器以形成隊(duì)列。
發(fā)送的方法是輪詢(xún),即先發(fā)送到第一個(gè)處理器,然后再發(fā)送到第二個(gè),第三個(gè)處理器,然后再返回到第一個(gè)處理器。 當(dāng)使用者線(xiàn)程使用這些socketChannel時(shí),它將獲取請(qǐng)求請(qǐng)求,并且數(shù)據(jù)將伴隨這些請(qǐng)求請(qǐng)求。
默認(rèn)情況下,線(xiàn)程池中有八個(gè)線(xiàn)程。 這些線(xiàn)程用于處理請(qǐng)求和解析請(qǐng)求。 如果請(qǐng)求是書(shū)面請(qǐng)求,則將其寫(xiě)入磁盤(pán)。 如果讀取,則返回結(jié)果。 處理器將從響應(yīng)中讀取響應(yīng)數(shù)據(jù),然后將其返回給客戶(hù)端。
這是Kafka的三層網(wǎng)絡(luò)架構(gòu)。
因此,如果我們需要增強(qiáng)和調(diào)整Kafka,增加處理器并增加線(xiàn)程池中的處理線(xiàn)程,則可以達(dá)到效果。 考慮到處理器生成請(qǐng)求的速度過(guò)快,并且線(xiàn)程數(shù)量不足以及時(shí)處理請(qǐng)求,因此請(qǐng)求和響應(yīng)實(shí)際上是一種緩存效果。
總結(jié)
我希望本文對(duì)您了解和初步了解Kafka,它具有的組件以及為什么可以實(shí)現(xiàn)如此高的性能有所幫助。
Kafka在現(xiàn)代高并發(fā)系統(tǒng)體系結(jié)構(gòu)中扮演著至關(guān)重要的角色,并且仍在快速發(fā)展,例如流媒體。
本文僅從概念和簡(jiǎn)單設(shè)計(jì)原理方面說(shuō)明Kafka。 僅僅掌握它是不夠的。
如果您需要更深入的分析,請(qǐng)參閱官方文檔。
謝謝閱讀!
分享文章:九張圖帶你了解Kafka
URL鏈接:http://m.fisionsoft.com.cn/article/coeceph.html


咨詢(xún)
建站咨詢(xún)
