來源:https://blog.csdn.net/zxl2016/article/details/80278496
一、基本概念
介紹
Kafka是一個分布式的、可分區(qū)的、可復(fù)制的消息系統(tǒng)。它提供了普通消息系統(tǒng)的功能,但具有自己獨特的設(shè)計。
這個獨特的設(shè)計是什么樣的呢?
首先讓我們看幾個基本的消息系統(tǒng)術(shù)語:
Kafka將消息以topic為單位進(jìn)行歸納。
將向Kafka topic發(fā)布消息的程序成為producers.
將預(yù)訂topics并消費(fèi)消息的程序成為consumer.
Kafka以集群的方式運(yùn)行,可以由一個或多個服務(wù)組成,每個服務(wù)叫做一個broker.
producers通過網(wǎng)絡(luò)將消息發(fā)送到Kafka集群,集群向消費(fèi)者提供消息,如下圖所示:

客戶端和服務(wù)端通過TCP協(xié)議通信。Kafka提供了Java客戶端,并且對多種語言都提供了支持。
Topics 和Logs
先來看一下Kafka提供的一個抽象概念:topic.
一個topic是對一組消息的歸納。對每個topic,Kafka 對它的日志進(jìn)行了分區(qū),如下圖所示:

每個分區(qū)都由一系列有序的、不可變的消息組成,這些消息被連續(xù)的追加到分區(qū)中。分區(qū)中的每個消息都有一個連續(xù)的序列號叫做offset,用來在分區(qū)中唯一的標(biāo)識這個消息。
在一個可配置的時間段內(nèi),Kafka集群保留所有發(fā)布的消息,不管這些消息有沒有被消費(fèi)。比如,如果消息的保存策略被設(shè)置為2天,那么在一個消息被發(fā)布的兩天時間內(nèi),它都是可以被消費(fèi)的。之后它將被丟棄以釋放空間。Kafka的性能是和數(shù)據(jù)量無關(guān)的常量級的,所以保留太多的數(shù)據(jù)并不是問題。
實際上每個consumer唯一需要維護(hù)的數(shù)據(jù)是消息在日志中的位置,也就是offset.這個offset有consumer來維護(hù):一般情況下隨著consumer不斷的讀取消息,這offset的值不斷增加,但其實consumer可以以任意的順序讀取消息,比如它可以將offset設(shè)置成為一個舊的值來重讀之前的消息。
以上特點的結(jié)合,使Kafka consumers非常的輕量級:它們可以在不對集群和其他consumer造成影響的情況下讀取消息。你可以使用命令行來"tail"消息而不會對其他正在消費(fèi)消息的consumer造成影響。
將日志分區(qū)可以達(dá)到以下目的:首先這使得每個日志的數(shù)量不會太大,可以在單個服務(wù)上保存。另外每個分區(qū)可以單獨發(fā)布和消費(fèi),為并發(fā)操作topic提供了一種可能。
分布式
每個分區(qū)在Kafka集群的若干服務(wù)中都有副本,這樣這些持有副本的服務(wù)可以共同處理數(shù)據(jù)和請求,副本數(shù)量是可以配置的。副本使Kafka具備了容錯能力。
每個分區(qū)都由一個服務(wù)器作為“l(fā)eader”,零或若干服務(wù)器作為“followers”,leader負(fù)責(zé)處理消息的讀和寫,followers則去復(fù)制leader.如果leader down了,followers中的一臺則會自動成為leader。集群中的每個服務(wù)都會同時扮演兩個角色:作為它所持有的一部分分區(qū)的leader,同時作為其他分區(qū)的followers,這樣集群就會據(jù)有較好的負(fù)載均衡。
Producers
Producer將消息發(fā)布到它指定的topic中,并負(fù)責(zé)決定發(fā)布到哪個分區(qū)。通常簡單的由負(fù)載均衡機(jī)制隨機(jī)選擇分區(qū),但也可以通過特定的分區(qū)函數(shù)選擇分區(qū)。使用的更多的是第二種。
Consumers
發(fā)布消息通常有兩種模式:隊列模式(queuing)和發(fā)布-訂閱模式(publish-subscribe)。隊列模式中,consumers可以同時從服務(wù)端讀取消息,每個消息只被其中一個consumer讀到;發(fā)布-訂閱模式中消息被廣播到所有的consumer中。Consumers可以加入一個consumer 組,共同競爭一個topic,topic中的消息將被分發(fā)到組中的一個成員中。同一組中的consumer可以在不同的程序中,也可以在不同的機(jī)器上。如果所有的consumer都在一個組中,這就成為了傳統(tǒng)的隊列模式,在各consumer中實現(xiàn)負(fù)載均衡。如果所有的consumer都不在不同的組中,這就成為了發(fā)布-訂閱模式,所有的消息都被分發(fā)到所有的consumer中。更常見的是,每個topic都有若干數(shù)量的consumer組,每個組都是一個邏輯上的“訂閱者”,為了容錯和更好的穩(wěn)定性,每個組由若干consumer組成。這其實就是一個發(fā)布-訂閱模式,只不過訂閱者是個組而不是單個consumer。

由兩個機(jī)器組成的集群擁有4個分區(qū) (P0-P3) 2個consumer組. A組有兩個consumerB組有4個
相比傳統(tǒng)的消息系統(tǒng),Kafka可以很好的保證有序性。 傳統(tǒng)的隊列在服務(wù)器上保存有序的消息,如果多個consumers同時從這個服務(wù)器消費(fèi)消息,服務(wù)器就會以消息存儲的順序向consumer分發(fā)消息。雖然服務(wù)器按順序發(fā)布消息,但是消息是被異步的分發(fā)到各consumer上,所以當(dāng)消息到達(dá)時可能已經(jīng)失去了原來的順序,這意味著并發(fā)消費(fèi)將導(dǎo)致順序錯亂。為了避免故障,這樣的消息系統(tǒng)通常使用“專用consumer”的概念,其實就是只允許一個消費(fèi)者消費(fèi)消息,當(dāng)然這就意味著失去了并發(fā)性。
在這方面Kafka做的更好,通過分區(qū)的概念,Kafka可以在多個consumer組并發(fā)的情況下提供較好的有序性和負(fù)載均衡。將每個分區(qū)分只分發(fā)給一個consumer組,這樣一個分區(qū)就只被這個組的一個consumer消費(fèi),就可以順序的消費(fèi)這個分區(qū)的消息。因為有多個分區(qū),依然可以在多個consumer組之間進(jìn)行負(fù)載均衡。注意consumer組的數(shù)量不能多于分區(qū)的數(shù)量,也就是有多少分區(qū)就允許多少并發(fā)消費(fèi)。
Kafka只能保證一個分區(qū)之內(nèi)消息的有序性,在不同的分區(qū)之間是不可以的,這已經(jīng)可以滿足大部分應(yīng)用的需求。如果需要topic中所有消息的有序性,那就只能讓這個topic只有一個分區(qū),當(dāng)然也就只有一個consumer組消費(fèi)它。
###########################################