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

