kafka全面理解
什么是消息隊(duì)列,它的好處是什么?
解藕
將消息寫(xiě)入消息隊(duì)列,需要消息的系統(tǒng)自己從消息隊(duì)列中訂閱,從而上游系統(tǒng)不需要做任何修改
例如有上游系統(tǒng)a,它有3個(gè)下游系統(tǒng)b,c,d,為了使b,c,d能拿到a的數(shù)據(jù),a需要在代碼中去調(diào)用這3個(gè)系統(tǒng)。如果有一天,b不再使用a的數(shù)據(jù)了或b的接口發(fā)生了變化,a還需要修改代碼。而使用消息隊(duì)列,就只管往隊(duì)列里發(fā)送數(shù)據(jù),需要的下游自己去隊(duì)列里取數(shù)據(jù)即可。
異步
不用同步等待下游將數(shù)據(jù)處理完,將消息發(fā)到消息隊(duì)列中即可返回,不阻礙主流程。
例如上游系統(tǒng)a是主業(yè)務(wù),b,c,d是非主要業(yè)務(wù),沒(méi)有必要同步等待3個(gè)下游都返回主業(yè)務(wù)才繼續(xù)。使用消息隊(duì)列可以實(shí)現(xiàn)異步,提高吞吐量。
削峰
上游數(shù)據(jù)有突發(fā)流量,下游可能扛不住,kafka在中間可以起到一個(gè)緩沖的作用,把消息暫存在kafka中,下游服務(wù)就可以按照自己的節(jié)奏慢慢處理。
kafka概念
broker
broker是kafka實(shí)例。
replication
每一個(gè)partition有多副本,當(dāng)主節(jié)點(diǎn)發(fā)生故障時(shí),會(huì)選擇一個(gè)副本作為主節(jié)點(diǎn)。kafka是主寫(xiě)主讀的。
topic
topic是消息的分類(lèi),一個(gè)topic可以供任意多個(gè)消費(fèi)組消費(fèi)。
partition
topic的分區(qū),每個(gè)topic的數(shù)據(jù)可以被分成多個(gè)partition,可以不在一個(gè)機(jī)器上,由此來(lái)實(shí)現(xiàn)kafka的伸縮性。各個(gè)partition的數(shù)據(jù)是不重復(fù)的,相同partition的數(shù)據(jù)是按照發(fā)送順序有序的。任何partition只有一個(gè)leader,只有l(wèi)eader是對(duì)外提供服務(wù)的。leader接收到數(shù)據(jù)后,follower會(huì)不停給他發(fā)送請(qǐng)求嘗試去拉取最新的數(shù)據(jù),拉取到自己本地后,寫(xiě)入磁盤(pán)中。每個(gè)partition都有多個(gè)副本,相同partition的各個(gè)副本分布在不同的broker上。
consumer group/consumer
一個(gè)consumer group是一個(gè)topic的訂閱者,一個(gè)topic可以被多個(gè)consumer group訂閱,各個(gè)consumer group是相互獨(dú)立的。一個(gè)consumer group內(nèi)部可以有多個(gè)consumer,多個(gè)consumer不會(huì)消費(fèi)相同的partition的消息。最多有效的consumer數(shù)與partition數(shù)相同,如果consumer數(shù)多于partition數(shù),那么多出來(lái)的consumer不會(huì)消費(fèi)到任何消息。
rebalance
消費(fèi)組內(nèi)某個(gè)消費(fèi)者掛掉后,其他消費(fèi)者自動(dòng)重新分配訂閱topic的partition的過(guò)程。rebalance是消費(fèi)者端實(shí)現(xiàn)高可用的重要手段。
kafka的特性
高吞吐、低延遲:kakfa 最大的特點(diǎn)就是收發(fā)消息非???,kafka 每秒可以處理幾十萬(wàn)條消息,它的最低延遲只有幾毫秒。 高伸縮性:每個(gè)主題(topic) 包含多個(gè)分區(qū)(partition),主題中的分區(qū)可以分布在不同的主機(jī)(broker)中。 持久性、可靠性:Kafka 能夠允許數(shù)據(jù)的持久化存儲(chǔ),消息被持久化到磁盤(pán),并支持?jǐn)?shù)據(jù)備份防止數(shù)據(jù)丟失,Kafka 底層的數(shù)據(jù)存儲(chǔ)是基于 Zookeeper 存儲(chǔ)的,Zookeeper 我們知道它的數(shù)據(jù)能夠持久存儲(chǔ)。 容錯(cuò)性:允許集群中的節(jié)點(diǎn)失敗,某個(gè)節(jié)點(diǎn)宕機(jī),Kafka 集群能夠正常工作 高并發(fā):支持?jǐn)?shù)千個(gè)客戶端同時(shí)讀寫(xiě)
kafka為何快
頁(yè)緩存+順序?qū)懭?/span>
kafka 寫(xiě)數(shù)據(jù)的時(shí)候,非常關(guān)鍵的一點(diǎn),它是以磁盤(pán)順序?qū)懙姆绞絹?lái)寫(xiě)的。僅僅將數(shù)據(jù)追加到文件的末尾,不是在文件的隨機(jī)位置來(lái)修改數(shù)據(jù)。
寫(xiě)入磁盤(pán)文件的時(shí)候,可以直接寫(xiě)入這個(gè) OS Cache 里,也就是僅僅寫(xiě)入內(nèi)存中,接下來(lái)由操作系統(tǒng)自己決定什么時(shí)候把 OS Cache 里的數(shù)據(jù)真的刷入磁盤(pán)文件中。
零拷貝
如果Kafka從磁盤(pán)中讀取數(shù)據(jù)發(fā)送給下游的消費(fèi)者,大概過(guò)程是:
先看看要讀的數(shù)據(jù)在不在os cache中,如果不在的話就從磁盤(pán)文件里讀取數(shù)據(jù)后放入os cache 從操作系統(tǒng)的os cache 里拷貝數(shù)據(jù)到應(yīng)用程序進(jìn)程的緩存里 從應(yīng)用程序進(jìn)程的緩存里拷貝數(shù)據(jù)到操作系統(tǒng)層面的Socket緩存里 從Soket緩存里提取數(shù)據(jù)后發(fā)送到網(wǎng)卡,最后發(fā)送出去給下游消費(fèi)者
整個(gè)過(guò)程有兩次沒(méi)必要的拷貝
從操作系統(tǒng)的cache里拷貝到應(yīng)用進(jìn)程的緩存里 從應(yīng)用程序緩存里拷貝回操作系統(tǒng)的Socket緩存里。
為了進(jìn)行這兩次拷貝,中間還發(fā)生了好幾次上下文切換,一會(huì)兒是應(yīng)用程序在執(zhí)行,一會(huì)兒上下文切換到操作系統(tǒng)來(lái)執(zhí)行。
所以這種方式來(lái)讀取數(shù)據(jù)是比較消耗性能的
零拷貝
讓操作系統(tǒng)的cache中的數(shù)據(jù)發(fā)送到網(wǎng)卡 網(wǎng)卡傳出給下游的消費(fèi)者
中間跳過(guò)了兩次拷貝數(shù)據(jù)的步驟,Socket緩存中僅僅會(huì)拷貝一個(gè)描述符過(guò)去,不會(huì)拷貝數(shù)據(jù)到Socket緩存
另外:
從磁盤(pán)讀數(shù)據(jù)的時(shí)候,會(huì)先看看os cache內(nèi)存中是否有,如果有的話,其實(shí)讀數(shù)據(jù)都是直接讀內(nèi)存的。
如果kafka集群經(jīng)過(guò)良好的調(diào)優(yōu),大家會(huì)發(fā)現(xiàn)大量的數(shù)據(jù)都是直接寫(xiě)入os cache中,然后讀數(shù)據(jù)的時(shí)候也是從os cache中讀。
相當(dāng)于是Kafka完全基于內(nèi)存提供數(shù)據(jù)的寫(xiě)和讀了,所以這個(gè)整體性能會(huì)極其的高
消息壓縮
批量發(fā)送
參考文章:
https://juejin.im/post/6844903817348136968#heading-8
https://juejin.im/post/6844903495670169607
https://zhuanlan.zhihu.com/p/96957920

