我們?cè)趯W(xué)習(xí)一個(gè)東西的時(shí)候钾菊,往往只有真正了解它背后的含義帅矗,才能一步一步的掌握它,直到運(yùn)籌帷幄煞烫。對(duì)于Kafka來說浑此,我也是一個(gè)小白,本篇文章我就以一個(gè)小白的角度來初探一下Kafka滞详,本篇文章基于官方文檔凛俱,順便說一句官方文檔真的很重要紊馏,且讀且珍惜。
背景
Kafka最早是由LinkedIn公司開發(fā)的最冰,作為其自身業(yè)務(wù)消息處理的基礎(chǔ)瘦棋,后LinkedIn公司將Kafka捐贈(zèng)給Apache,現(xiàn)在已經(jīng)成為Apache的一個(gè)頂級(jí)項(xiàng)目了暖哨,Kafka作為一個(gè)高吞吐的分布式的消息系統(tǒng)赌朋,目前已經(jīng)被很多公司應(yīng)用在實(shí)際的業(yè)務(wù)中了,并且與許多數(shù)據(jù)處理框架相結(jié)合篇裁,比如Hadoop沛慢,Spark等。
消息系統(tǒng)
在實(shí)際的業(yè)務(wù)需求中达布,我們需要處理各種各樣的消息团甲,比如Page View,日志,請(qǐng)求等黍聂,那么一個(gè)好的消息系統(tǒng)應(yīng)該擁有哪些功能呢躺苦?
- 擁有消息發(fā)布和訂閱的功能,類似于消息隊(duì)列或者企業(yè)消息傳送系統(tǒng)产还;
- 能存儲(chǔ)消息流匹厘,并具備容錯(cuò)性;
- 能夠?qū)崟r(shí)的處理消息脐区;
以上3點(diǎn)是作為一個(gè)好的消息系統(tǒng)的最基本的能力愈诚。
那么Kafka為什么會(huì)誕生呢?
其實(shí)在我們工作中牛隅,相信有很多也接觸過消息隊(duì)列炕柔,甚至自己也寫過簡(jiǎn)單的消息系統(tǒng),它最基本應(yīng)該擁有發(fā)布/訂閱的功能媒佣,如下圖所示:
其中消費(fèi)者A與消費(fèi)者B都訂閱了消息源A和消息源B匕累,這種模式很簡(jiǎn)單,但是相對(duì)來說也有弊端丈攒,比如以下兩點(diǎn):
- 該模式下消費(fèi)者需要實(shí)時(shí)去處理消息哩罪,因?yàn)檫@里消息源和消費(fèi)者都不會(huì)維護(hù)一個(gè)消息隊(duì)列(維護(hù)代價(jià)太大),這將會(huì)導(dǎo)致消費(fèi)者若是暫時(shí)沒有能力消費(fèi)巡验,則消息會(huì)丟失际插,當(dāng)然也就不能獲得歷史的消息;
- 消息源需要維護(hù)原本不屬于它的工作显设,比如維護(hù)訂閱者(消費(fèi)者)的信息框弛,向多個(gè)消費(fèi)者發(fā)送消息,亦或者有些還需要處理消息反饋捕捂,這是原本純粹的消息源就會(huì)變得越來越復(fù)雜瑟枫;
當(dāng)然這些問題都是可以改進(jìn)的斗搞,比如我們可以在消息源和消費(fèi)者中間增加一個(gè)消息隊(duì)列,如下圖所示:
從圖中我們可以看出慷妙,現(xiàn)在消息源只需要將消息發(fā)送到消息隊(duì)列中就行僻焚,至于其他就將給消息隊(duì)列去完成,我們可以在消息隊(duì)列持久化消息膝擂,主動(dòng)推消息給已經(jīng)訂閱了該消息隊(duì)列的消費(fèi)者虑啤,那么這種模式還有什么缺點(diǎn)嗎?
答案是有架馋,上圖只是兩個(gè)消息隊(duì)列狞山,我們維護(hù)起來并不困難,但是如果有成百上千個(gè)呢叉寂?那不得gg萍启,其實(shí)我們可以發(fā)現(xiàn),消息隊(duì)列的功能都很類似屏鳍,無非就是持久化消息勘纯,推送消息,給出反饋等功能钓瞭,結(jié)構(gòu)也非常類似屡律,主要是消息內(nèi)容,當(dāng)然如果要通用化降淮,消息結(jié)構(gòu)也要盡可能通用化,與具體平臺(tái)具體語言無關(guān)搏讶,比如用JSON格式等佳鳖,所有我們可以演變出以下的消息系統(tǒng):
這個(gè)方式看起來只是把上面的隊(duì)列合并到了一起,其實(shí)并不那么簡(jiǎn)單媒惕,因?yàn)檫@個(gè)消息隊(duì)列集合要具備以下幾個(gè)功能:
- 能統(tǒng)一管理所有的消息隊(duì)列系吩,不是特殊需求不需要開發(fā)者自己去維護(hù);
- 高效率的存儲(chǔ)消息妒蔚;
- 消費(fèi)者能快速的找到想要消費(fèi)的消息穿挨;
當(dāng)然這些只是最基本的功能,還有比如多節(jié)點(diǎn)容錯(cuò)肴盏,數(shù)據(jù)備份等科盛,一個(gè)好的消息系統(tǒng)需要處理的東西非常多,很慶幸菜皂,Kafka幫我們做到了贞绵。
Kafka
在具體了解Kafka的細(xì)節(jié)前,我們先來看一下它的一些基本概念:
- Kafka是運(yùn)行在一個(gè)集群上恍飘,所以它可以擁有一個(gè)或多個(gè)服務(wù)節(jié)點(diǎn)榨崩;
- Kafka集群將消息存儲(chǔ)在特定的文件中谴垫,對(duì)外表現(xiàn)為Topics;
- 每條消息記錄都包含一個(gè)key,消息內(nèi)容以及時(shí)間戳母蛛;
從上面幾點(diǎn)我們大致可以推測(cè)Kafka是一個(gè)分布式的消息存儲(chǔ)系統(tǒng)翩剪,那么它就僅僅這么點(diǎn)功能嗎,我們繼續(xù)看下面彩郊。
Kafka為了擁有更強(qiáng)大的功能前弯,提供了四大核心接口:
- Producer API允許了應(yīng)用可以向Kafka中的topics發(fā)布消息;
- Consumer API允許了應(yīng)用可以訂閱Kafka中的topics,并消費(fèi)消息焦辅;
- Streams API允許應(yīng)用可以作為消息流的處理者博杖,比如可以從topicA中消費(fèi)消息,處理的結(jié)果發(fā)布到topicB中筷登;
- Connector API提供Kafka與現(xiàn)有的應(yīng)用或系統(tǒng)適配功能剃根,比如與數(shù)據(jù)庫(kù)連接器可以捕獲表結(jié)構(gòu)的變化;
它們與Kafka集群的關(guān)系可以用下圖表示:
在了解了Kafka的一些基本概念后前方,我們具體來看看它的一些組成部分狈醉。
Topics
顧名思義Topics是一些主題的集合,更通俗的說Topic就像一個(gè)消息隊(duì)列惠险,生產(chǎn)者可以向其寫入消息苗傅,消費(fèi)者可以從中讀取消息,一個(gè)Topic支持多個(gè)生產(chǎn)者或消費(fèi)者同時(shí)訂閱它班巩,所以其擴(kuò)展性很好渣慕。Topic又可以由一個(gè)或多個(gè)partition(分區(qū))組成,比如下圖:
其中每個(gè)partition中的消息是有序的抱慌,但相互之間的順序就不能保證了逊桦,若Topic有多個(gè)partition,生產(chǎn)者的消息可以指定或者由系統(tǒng)根據(jù)算法分配到指定分區(qū)抑进,若你需要所有消息都是有序的强经,那么你最好只用一個(gè)分區(qū)。另外partition支持消息位移讀取寺渗,消息位移有消費(fèi)者自身管理匿情,比如下圖:
由上圖可以看出,不同消費(fèi)者對(duì)同一分區(qū)的消息讀取互不干擾信殊,消費(fèi)者可以通過設(shè)置消息位移(offset)來控制自己想要獲取的數(shù)據(jù)炬称,比如可以從頭讀取,最新數(shù)據(jù)讀取涡拘,重讀讀取等功能转砖。
關(guān)于Topic的分區(qū)策略以及與消費(fèi)者間平衡后續(xù)文章會(huì)繼續(xù)深入講解。
Distribution
上文說到過,Kafka是一個(gè)分布式的消息系統(tǒng)府蔗,所以當(dāng)我們配置了多個(gè)Kafka Server節(jié)點(diǎn)后晋控,它就擁有分布式的能力,比如容錯(cuò)等姓赤,partition會(huì)被分布在各個(gè)Server節(jié)點(diǎn)上赡译,同時(shí)它們中間又有一個(gè)leader,它會(huì)處理所有的讀寫請(qǐng)求不铆,其他followers會(huì)復(fù)制leader上的數(shù)據(jù)信息蝌焚,一旦當(dāng)leader因?yàn)槟承┕收隙鵁o法提供服務(wù)后,就會(huì)有一個(gè)follower被推舉出來成為新的leader來處理這些請(qǐng)求誓斥。
Geo-Replication
異地備份是作為主流分布式系統(tǒng)的基礎(chǔ)功能只洒,用于集群中數(shù)據(jù)的備份和恢復(fù),Kafka利用MirrorMaker來實(shí)現(xiàn)這個(gè)功能劳坑,用戶只需簡(jiǎn)單的進(jìn)行相應(yīng)配置即可毕谴。
Producers
Producers作為消息的生產(chǎn)者,可以自己指定將消息發(fā)布到訂閱Topic中的指定分區(qū)距芬,策略可以自己指定涝开,比如語義或者結(jié)構(gòu)類似的消息發(fā)布在同一分區(qū),當(dāng)然也可以由系統(tǒng)循環(huán)發(fā)布在每一個(gè)分區(qū)上框仔。
Consumers
Consumers是一群消費(fèi)者的集合舀武,可以稱之為消費(fèi)者組,是一種更高層次的的抽象离斩,向Topic訂閱消費(fèi)消息的單位是Consumers银舱,當(dāng)然它其中也可以只有一個(gè)消費(fèi)者(consumer)。下面是關(guān)于consumer的兩條原則:
- 假如所有消費(fèi)者都在同一個(gè)消費(fèi)者組中跛梗,那么它們將協(xié)同消費(fèi)訂閱Topic的部分消息(根據(jù)分區(qū)與消費(fèi)者的數(shù)量分配)纵朋,保存負(fù)載平衡;
- 假如所有消費(fèi)者都在不同的消費(fèi)者組中茄袖,并且訂閱了同個(gè)Topic,那么它們將可以消費(fèi)Topic的所有消息嘁锯;
下面是一個(gè)簡(jiǎn)單的例子宪祥,幫助大家理解:
上圖中有兩個(gè)Server節(jié)點(diǎn),有一個(gè)Topic被分為四個(gè)分區(qū)(P0-P4)分別被分配在兩個(gè)節(jié)點(diǎn)上家乘,另外還有兩個(gè)消費(fèi)者組(GA蝗羊,GB),其中GA有兩個(gè)消費(fèi)者實(shí)例仁锯,GB有四個(gè)消費(fèi)者實(shí)例耀找。
從圖中我們可以看出,首先訂閱Topic的單位是消費(fèi)者組,另外我們發(fā)現(xiàn)Topic中的消息根據(jù)一定規(guī)則將消息推送給具體消費(fèi)者野芒,主要原則如下:
- 若消費(fèi)者數(shù)小于partition數(shù)蓄愁,且消費(fèi)者數(shù)為一個(gè),那么它就消費(fèi)所有消息狞悲;
- 若消費(fèi)者數(shù)小于partition數(shù)撮抓,假設(shè)消費(fèi)者數(shù)為N,partition數(shù)為M摇锋,那么每個(gè)消費(fèi)者能消費(fèi)的分區(qū)數(shù)為M/N或M/N+1丹拯;
- 若消費(fèi)者數(shù)等于partition數(shù),那么每個(gè)消費(fèi)者都會(huì)均等分配到一個(gè)分區(qū)的消息荸恕;
- 若消費(fèi)者數(shù)大于partition數(shù)乖酬,則將會(huì)出現(xiàn)部分消費(fèi)者得不到消息分區(qū),出現(xiàn)空閑的情況融求;
總的來說咬像,Kafka會(huì)根據(jù)消費(fèi)者組的情況均衡分配消息,比如有消息著實(shí)例宕機(jī)双肤,亦或者有新的消費(fèi)者加入等情況施掏。
Guarantees
kafka作為一個(gè)高水準(zhǔn)的系統(tǒng),提供了以下的保證:
- 消息的添加是有序的茅糜,生產(chǎn)者越早向訂閱的Topic發(fā)送的消息七芭,會(huì)更早的被添加到Topic中,當(dāng)然它們可能被分配到不同的分區(qū)蔑赘;
- 消費(fèi)者在消費(fèi)Topic分區(qū)中的消息時(shí)是有序的狸驳;
- 對(duì)于有N個(gè)復(fù)制節(jié)點(diǎn)的Topic,系統(tǒng)可以最多容忍N(yùn)-1個(gè)節(jié)點(diǎn)發(fā)生故障缩赛,而不丟失任何提交給該Topic的消息丟失耙箍;
相關(guān)這些點(diǎn)的細(xì)節(jié),我準(zhǔn)備再后續(xù)文章中再慢慢深入酥馍。
Kafka as a Messaging System
說了這么多辩昆,前面也講了消息系統(tǒng)的演變過程,那么Kafka相比其他的消息系統(tǒng)優(yōu)勢(shì)具體在哪里旨袒?
傳統(tǒng)的消息系統(tǒng)模型主要有兩種:消息隊(duì)列和發(fā)布/訂閱汁针。
1.消息隊(duì)列
特性 | 描述 |
---|---|
表現(xiàn)形式 | 一組消費(fèi)者從消息隊(duì)列中獲取消息,消息會(huì)被推送給組中的某一個(gè)消費(fèi)者 |
優(yōu)勢(shì) | 水平擴(kuò)展砚尽,可以將消息數(shù)據(jù)分開處理 |
劣勢(shì) | 消息隊(duì)列不是多用戶的施无,當(dāng)一條消息記錄被一個(gè)進(jìn)程讀取后,消息便會(huì)丟失 |
2.發(fā)布/訂閱
特性 | 描述 |
---|---|
表現(xiàn)形式 | 消息會(huì)廣播發(fā)送給所有消費(fèi)者 |
優(yōu)勢(shì) | 可以多進(jìn)程共享消息 |
劣勢(shì) | 每個(gè)消費(fèi)者都會(huì)獲得所有消息必孤,無法通過添加消費(fèi)進(jìn)程提高處理效率 |
從上面兩個(gè)表中可以看出兩種傳統(tǒng)的消息系統(tǒng)模型的優(yōu)缺點(diǎn)猾骡,所以Kafka在前人的肩膀上進(jìn)行了優(yōu)化,吸收他們的優(yōu)點(diǎn),主要體現(xiàn)在以下兩方面:
- 通過Topic方式來達(dá)到消息隊(duì)列的功能
- 通過消費(fèi)者組這種方式來達(dá)到發(fā)布/訂閱的功能
Kafka通過結(jié)合這兩點(diǎn)(這兩點(diǎn)的具體描述查看上面章節(jié))兴想,完美的解決了它們兩者模式的缺點(diǎn)幢哨。
Kafka as a Storage System
存儲(chǔ)消息也是消息系統(tǒng)的一大功能,Kafka相對(duì)普通的消息隊(duì)列存儲(chǔ)來說襟企,它的表現(xiàn)實(shí)在好的太多嘱么,首先Kafka支持寫入確認(rèn),保證消息寫入的正確性和連續(xù)性顽悼,同時(shí)Kafka還會(huì)對(duì)寫入磁盤的數(shù)據(jù)進(jìn)行復(fù)制備份曼振,來實(shí)現(xiàn)容錯(cuò),另外Kafka對(duì)磁盤的使用結(jié)構(gòu)是一致的蔚龙,就說說不管你的服務(wù)器目前磁盤存儲(chǔ)的消息數(shù)據(jù)有多少冰评,它添加消息數(shù)據(jù)的效率是相同的。
Kafka的存儲(chǔ)機(jī)制很好的支持消費(fèi)者可以隨意控制自身所需要讀取的數(shù)據(jù)木羹,在很多時(shí)候你也可以將Kafka作為一個(gè)高性能甲雅,低延遲的分布式文件系統(tǒng)。
Kafka for Stream Processing
Kafka作為一個(gè)完美主義代表者坑填,光有普通的讀寫抛人,存儲(chǔ)等功能是不夠的,它還提供了實(shí)時(shí)處理消息流的接口脐瑰。
很多時(shí)候原始的數(shù)據(jù)并不是我們想要的妖枚,我們想要的是經(jīng)過處理后的數(shù)據(jù)結(jié)果,比如通過一天的搜索數(shù)據(jù)得出當(dāng)天的搜索熱點(diǎn)等苍在,你可以利用Streams API來實(shí)現(xiàn)自己想要的功能绝页,比如從輸入Topic中獲取數(shù)據(jù),然后再發(fā)布到具體的輸出Topic中寂恬。
Kafka的流處理可以解決諸如處理無序數(shù)據(jù)续誉、數(shù)據(jù)的復(fù)雜轉(zhuǎn)換等問題。
總結(jié)
消息傳遞初肉、存儲(chǔ)酷鸦、流處理這么功能單一來看確實(shí)很普通,但如何把它們完美的結(jié)合到一起牙咏,就是一種優(yōu)雅的體現(xiàn)臼隔,Kafka做到了這一點(diǎn)。
相比HDFS分布式文件存儲(chǔ)系統(tǒng)眠寿,雖然它能支持高效存儲(chǔ)并且批處理數(shù)據(jù),但是它只支持處理過去的歷史數(shù)據(jù)焦蘑。
相比普通的消息系統(tǒng)來說盯拱,雖然能處理現(xiàn)在至未來的數(shù)據(jù),但是它并不沒有存儲(chǔ)歷史的數(shù)據(jù)。
Kafka集眾家之所長(zhǎng)狡逢,使整個(gè)系統(tǒng)能兼顧各方面的需求宁舰,可以用一個(gè)詞來說: “完美”!
本文從消息系統(tǒng)的演變講起奢浑,到Kafka的具體組成蛮艰,最后到Kafka的三大特性寿酌,旨在幫助大家能夠大概的了解Kafka是什么的尤蒿,到底有什么作用逗载,當(dāng)然這只是一個(gè)小白的簡(jiǎn)單理解钝满,如有寫得不對(duì)的地方陕赃,希望大家能夠指出随闽,不勝感激议经。