本篇內(nèi)容主要講解“Kafka的設(shè)計(jì)原理及性能應(yīng)用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Kafka的設(shè)計(jì)原理及性能應(yīng)用”吧!
成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供五家渠網(wǎng)站建設(shè)、五家渠做網(wǎng)站、五家渠網(wǎng)站設(shè)計(jì)、五家渠網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、五家渠企業(yè)網(wǎng)站模板建站服務(wù),10多年五家渠做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
達(dá)觀數(shù)據(jù)作為一家提供大數(shù)據(jù)服務(wù)的公司,經(jīng)常會(huì)遇到客戶上報(bào)數(shù)據(jù)的需求。這樣的請(qǐng)求不需要馬上返回處理結(jié)果, 而是需要后臺(tái)將一系列的上報(bào)數(shù)據(jù)進(jìn)行統(tǒng)一歸檔整理挖掘, 然后將結(jié)果數(shù)據(jù)呈現(xiàn)給客戶。這樣的業(yè)務(wù)需求需要達(dá)觀提供數(shù)據(jù)暫存服務(wù),也就是說(shuō)我們需要一個(gè)系統(tǒng)在生產(chǎn)者(客戶上報(bào)數(shù)據(jù))和消費(fèi)者(后臺(tái)數(shù)據(jù)處理)之間進(jìn)行溝通,簡(jiǎn)而言之叫系統(tǒng)間通信消息系統(tǒng),這種模型就是經(jīng)典的生產(chǎn)者(producer)、消費(fèi)者(consumer)模型。
然而有一個(gè)消息系統(tǒng)正好是為了應(yīng)對(duì)這種業(yè)務(wù)場(chǎng)景而生,它就是kafka。那么kafka到底是一個(gè)什么樣的系統(tǒng)?有什么特點(diǎn)?實(shí)際吞吐表現(xiàn)又如何?帶著這些問(wèn)題,我們一起來(lái)了解一下。
首先根據(jù)官網(wǎng)介紹,知道kafka是一個(gè)分布式流處理平臺(tái),一個(gè)可處理企業(yè)級(jí)發(fā)布/訂閱的消息系統(tǒng),并且具有高容錯(cuò)性和消費(fèi)及時(shí)性等特點(diǎn),那么它是怎么做到這一點(diǎn)的呢?接著往下看。
主題(topic)和日志(log)設(shè)置是kafka一大特色,一個(gè)kafka集群可以創(chuàng)建多個(gè)topic, 每個(gè)topic都相當(dāng)于一個(gè)消息隊(duì)列,這就意味著可以將不同格式的數(shù)據(jù)發(fā)布到不同的topic中,減小消費(fèi)這些數(shù)據(jù)時(shí)的邏輯難度。那么每個(gè)topic中處理的數(shù)據(jù)結(jié)構(gòu)是怎樣呢?我們先來(lái)看一張topic的解剖圖:
圖1:topic原理解析圖
從圖1中可以看到, 消息傳送過(guò)來(lái)時(shí)kafka會(huì)通過(guò)負(fù)載均衡將消息最終寫(xiě)入到磁盤(pán)上一個(gè)特定分區(qū)(partition)。由于在同一個(gè)partition上這些消息都是順序存儲(chǔ)的, 所以對(duì)一個(gè)特定分區(qū)每條消息都會(huì)有一個(gè)基于起始位置的偏移量(offset), 因此我們?cè)诤罄m(xù)消費(fèi)時(shí)只需要指明從哪個(gè)partition中哪個(gè)offset開(kāi)始消費(fèi),就能達(dá)到重復(fù)消費(fèi)目的。
1)雖然kafka可以通過(guò)增加partition方式來(lái)增加負(fù)載,但是它的數(shù)據(jù)最終是被寫(xiě)入到磁盤(pán)中。比如機(jī)械磁盤(pán)寫(xiě)入效率是很低的, 難道我們需要增大一個(gè)topic的負(fù)載給它設(shè)置更多的partition嗎?
機(jī)械磁盤(pán)驅(qū)動(dòng)器吞吐量跟尋道延時(shí)是強(qiáng)關(guān)聯(lián),也就是說(shuō),線性讀寫(xiě)速度遠(yuǎn)大于隨機(jī)讀寫(xiě)。例如,在67200rpm SATA RAID-5磁盤(pán)陣列中, 隨機(jī)寫(xiě)速度大約是100k/s, 然而線性寫(xiě)速度可以達(dá)到600M/s,后者大約是前者的6000倍。通過(guò)圖1可知, kafka采用的即是后者, 利用操作系統(tǒng)read-ahead和write-behind技術(shù),極大提升磁盤(pán)訪問(wèn)性能;設(shè)置partition數(shù)量固然可以從磁盤(pán)讀寫(xiě)角度增大topic負(fù)載,但是partition數(shù)量過(guò)多會(huì)導(dǎo)致cpu計(jì)算量增大,所以***辦法是根據(jù)不同配置的機(jī)器, 不同的業(yè)務(wù)場(chǎng)景設(shè)置不同的partition數(shù)量。
2)偏移量offset存儲(chǔ)類型是什么, 如果消息足夠大,offset的值是否會(huì)重新置0, 如果置0,后續(xù)消費(fèi)是否會(huì)紊亂?
kafka offset 是一個(gè)日志序列號(hào)( log sequence number),不必?fù)?dān)心offset 長(zhǎng)度問(wèn)題。那么這個(gè)日志序列號(hào)到底有多大,舉個(gè)例子:如果一個(gè)partition一天接收1T日志, 這個(gè)offset至少可以使用1百萬(wàn)年。由于offset足夠用,而且不會(huì)被置0,所以從這個(gè)角度講消費(fèi)紊亂情況是不會(huì)出現(xiàn)的。
3)寫(xiě)入磁盤(pán)的日志會(huì)被***保留嗎?如果想刪除過(guò)期消息, 需要怎么操作?
可以通過(guò)配置文件中l(wèi)og.retention參數(shù)設(shè)置消息過(guò)期時(shí)間,超過(guò)過(guò)期時(shí)間的消息會(huì)被系統(tǒng)刪除,刪除的消息不可再被重新消費(fèi)。
通過(guò)前文介紹我們已經(jīng)了解到kafka通過(guò)partition和順序讀寫(xiě)磁盤(pán)的方式達(dá)到很高吞吐量,可是單臺(tái)機(jī)器吞吐量再高一旦該機(jī)發(fā)生故障宕掉就會(huì)對(duì)業(yè)務(wù)產(chǎn)生災(zāi)難性影響,怎么處理這個(gè)問(wèn)題呢?想必你已經(jīng)知道了,那就是采用集群的方式,一旦一臺(tái)機(jī)器發(fā)生故障客戶端可以選擇鏈接其它機(jī)器, 保證業(yè)務(wù)穩(wěn)定性。每一個(gè)partition 都會(huì)有一個(gè)服務(wù)器來(lái)作為***(leader), 另外一個(gè)或者多個(gè)服務(wù)器(server)來(lái)作為跟隨者(follower),leader會(huì)處理所有的讀寫(xiě)請(qǐng)求,而follower則會(huì)從leader那里備份數(shù)據(jù), 如果一個(gè)leader失敗了, 其它的follower會(huì)自動(dòng)選舉一個(gè)成為一個(gè)新的leader, 所以對(duì)于一個(gè)server來(lái)說(shuō),他可能是某些partition下的leader, 而對(duì)于另外一些partition來(lái)說(shuō)則是follower,這樣設(shè)計(jì)可以將負(fù)載更好均衡。
1)搭建kafka集群時(shí)有沒(méi)有什么小細(xì)節(jié)需要值得注意的?
kafka官網(wǎng)已經(jīng)有詳細(xì)的搭建過(guò)程,在此不贅述。建議正式項(xiàng)目中不要采用偽集群(多個(gè)broker運(yùn)行在同一臺(tái)物理機(jī)上)的搭建方式,而且zookeeper集群和kafka集群***不要出現(xiàn)在同一臺(tái)實(shí)體機(jī)上,這樣會(huì)影響kafka順序讀寫(xiě)效率。
2)在kafka集群中如果一個(gè)server失敗, 怎樣保證數(shù)據(jù)完整性?
在kafka配置文件中有一個(gè)復(fù)制因子控制參數(shù),如果將該參數(shù)設(shè)置為N,則表示一份數(shù)據(jù)會(huì)被保存N次,而這些數(shù)據(jù)被備份到不同server中,所以當(dāng)設(shè)置復(fù)制因子為N時(shí)即使有N-1臺(tái)server失敗,也會(huì)保證數(shù)據(jù)完整性。
上面講了那么多,無(wú)非是要實(shí)現(xiàn)一個(gè)隊(duì)列的數(shù)據(jù)結(jié)構(gòu)。對(duì)于隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)我們一點(diǎn)也不陌生,由此可以想到對(duì)于kafka的一個(gè)topic 隊(duì)列來(lái)說(shuō),生產(chǎn)消費(fèi)邏輯應(yīng)該是這樣:有很多生產(chǎn)者向topic中寫(xiě)入數(shù)據(jù),另外一端則有許多消費(fèi)者消費(fèi)數(shù)據(jù)。(見(jiàn)圖2)
圖2:生產(chǎn)者消費(fèi)者原理解析圖
然而實(shí)際上kafka生產(chǎn)者消費(fèi)者模式有它的特殊性,那么kafka這個(gè)隊(duì)列是怎樣實(shí)現(xiàn)入隊(duì)和出隊(duì)的?接下來(lái)我們一起來(lái)看看kafka生產(chǎn)者消費(fèi)者模式。
生產(chǎn)者:生產(chǎn)者(producer)顧名思義,就是向kafka隊(duì)列中發(fā)布消息的,即入隊(duì)操作者。生產(chǎn)者功能是在topic中選擇一個(gè)partion 然后向這個(gè)partition中發(fā)送數(shù)據(jù)。選擇partition的過(guò)程就是一個(gè)負(fù)載均衡的方式, 比如可以采用輪詢或者自己設(shè)定partition選擇函數(shù)來(lái)實(shí)現(xiàn)負(fù)載均衡。當(dāng)然如果使用封裝的api比如(https://github.com/dpkp/kafka-python)就大可不必關(guān)心負(fù)載均衡問(wèn)題。會(huì)有默認(rèn)的負(fù)載均衡函數(shù)來(lái)實(shí)現(xiàn)這一功能。
消費(fèi)者: 消費(fèi)者(consumer)功能是從隊(duì)列中讀取數(shù)據(jù)并進(jìn)行相應(yīng)邏輯處理,但是kafka消費(fèi)者有特殊之處。kafka增加了一個(gè)組(group)的概念,一個(gè)topic可以有多個(gè)group, 當(dāng)多個(gè)consumer從屬于一個(gè)組時(shí),一條消息將被發(fā)往所有組,但是在組內(nèi),這條消息只會(huì)被一個(gè)consumer消費(fèi)。由此說(shuō)來(lái)一個(gè)group才是一個(gè)真正“邏輯消費(fèi)者(logic consumer)”。相關(guān)邏輯如圖3所示。
消息順序性:通過(guò)圖3我們知道消息的消費(fèi)情況,那么一個(gè)消息流消費(fèi)情況會(huì)是怎樣的?其實(shí)在高等級(jí)api中由于指定了負(fù)載均衡規(guī)則,同一個(gè)生產(chǎn)者發(fā)布兩條不同消息數(shù)據(jù)時(shí)會(huì)根據(jù)相應(yīng)規(guī)則發(fā)送到一個(gè)特定partition中,在消費(fèi)時(shí)會(huì)按照同樣規(guī)則從partition中取出數(shù)據(jù),這樣就能保證兩條數(shù)據(jù)消費(fèi)的先后順序,從而保證了消息順序性。
1)對(duì)于一個(gè)具有多個(gè)consumer的topic,我要實(shí)現(xiàn)一條消息被多個(gè)consumer消費(fèi)和一條消息只被一個(gè)consumer消費(fèi),那我需要怎么設(shè)置group?
將多個(gè)consumer設(shè)置為同一個(gè)組可以實(shí)現(xiàn)一條消息只被多個(gè)consumer消費(fèi), 將所有的consumer都設(shè)置為不同組,一條消息將會(huì)被所有consumer消費(fèi)。
2)如果有一批數(shù)據(jù)消費(fèi)時(shí)必須嚴(yán)格按照入隊(duì)先后順序來(lái)消費(fèi),需要怎樣設(shè)置生產(chǎn)者和消費(fèi)者。
如果數(shù)據(jù)量小,可以將topic設(shè)置為一個(gè)partition;如果數(shù)據(jù)量較大,可以將一個(gè)生產(chǎn)者寫(xiě)死負(fù)載均衡函數(shù),將數(shù)據(jù)發(fā)送到一個(gè)特定partition上,消費(fèi)數(shù)據(jù)時(shí)指定消費(fèi)者消費(fèi)的partition,和offset來(lái)順序消費(fèi)數(shù)據(jù)。
圖3:多個(gè)消費(fèi)者組時(shí)消息流向原理圖
kafka是跨語(yǔ)言消息隊(duì)列系統(tǒng),github上提供了Java, Python等多種語(yǔ)言客戶端,為了簡(jiǎn)單起見(jiàn),我們這里采用kafka-python(https://github.com/dpkp/kafka-python)作為客戶端來(lái)鏈接kafka集群做測(cè)試。
測(cè)試環(huán)境:
1, broker 數(shù)量:3
2, 備份因子數(shù):2
3, 磁盤(pán)信息:200G普通機(jī)械硬盤(pán)
4, cpu參數(shù):8核8線程
5, 語(yǔ)言: Python2.7
6, 客戶端: kafka-python
7, partition 數(shù)量: 5
單進(jìn)程producer 發(fā)送10條消息測(cè)試(如圖4):
圖4:一個(gè)生產(chǎn)者發(fā)送消息延時(shí)結(jié)果圖
統(tǒng)計(jì)上圖數(shù)據(jù)可知平均延時(shí):0.004488707,也就是說(shuō)qps可以達(dá)到2000,這樣的成績(jī)無(wú)疑是驚人的。那么在多進(jìn)程情況下kafka表現(xiàn)還會(huì)好嗎?我們?cè)O(shè)置10個(gè)進(jìn)程,看看kafka在10個(gè)進(jìn)程下的延時(shí)會(huì)有較大的變化嗎?如圖5(打印消息過(guò)多,截取部分結(jié)果圖):
圖5:多個(gè)生產(chǎn)者發(fā)送消息延時(shí)結(jié)果圖(部分)
由圖5可知10 個(gè)進(jìn)程每個(gè)進(jìn)程發(fā)送10條消息,平均延時(shí)為0.00050380466秒, qps接近200000,由于kafka支持?jǐn)?shù)千個(gè)客戶端同時(shí)讀寫(xiě),所以kafka吞吐能力是驚人的,更多測(cè)試歡迎大家去完成。
1,在垂直搜索中的應(yīng)用:
我們知道搜索引擎需要定時(shí)對(duì)文檔進(jìn)行更新, 如果我們把需要更新內(nèi)容暫存到 kafka,這樣索引更新時(shí),只需要從對(duì)應(yīng) partition 中從上一次取過(guò)的 offset 處繼續(xù)取數(shù)據(jù),就能達(dá)到增量更新目的,而過(guò)期數(shù)據(jù)會(huì)被自動(dòng)清理, 減少了操作冗余性和復(fù)雜性。
2,在用戶畫(huà)像以及相關(guān)推薦中的應(yīng)用:
和用戶畫(huà)像之前上報(bào)的用戶點(diǎn)擊行為數(shù)據(jù)不同,相關(guān)推薦之前的海量 item 數(shù)據(jù)上報(bào)對(duì)數(shù)據(jù)準(zhǔn)確性要求更高,試想如果一條 item 數(shù)據(jù)因?yàn)樘幚硎《鴽](méi)有正確入庫(kù),那么相關(guān)推薦時(shí)就永遠(yuǎn)不會(huì)出現(xiàn)這條 item, 所以這就對(duì)“可回滾”提出了更加嚴(yán)格要求。然而在 kafka 中,也只需要將消費(fèi)的 offset 重新置為消費(fèi)失敗時(shí)的 offset,修復(fù)入庫(kù)問(wèn)題重新消費(fèi)即可。
當(dāng)然 kafka 還有更加廣泛的應(yīng)用,這里就不一一討論,根據(jù)官網(wǎng)的介紹,kafka 在網(wǎng)站行為追蹤(Website Activity Tracking)、數(shù)據(jù)監(jiān)控, 流處理等眾多方面有特長(zhǎng),如果你對(duì) kafka 原理有研究或者有實(shí)際應(yīng)用方面有心得,歡迎來(lái)討論,謝謝!
關(guān)于達(dá)觀數(shù)據(jù)
達(dá)觀數(shù)據(jù)專注于企業(yè)大數(shù)據(jù)技術(shù)服務(wù),以***的多層智能挖掘算法,實(shí)現(xiàn)對(duì)海量用戶行為和文本數(shù)據(jù)的深入分析和挖掘,為企業(yè)提供智能文本分析、精準(zhǔn)用戶行為建模、個(gè)性化推薦、智能搜索等***數(shù)據(jù)挖掘功能。
到此,相信大家對(duì)“Kafka的設(shè)計(jì)原理及性能應(yīng)用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!