本篇文章給大家分享的是有關(guān)Kafka的生產(chǎn)者優(yōu)秀架構(gòu)設(shè)計的示例分析,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
濠江網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站設(shè)計等網(wǎng)站項目制作,到程序開發(fā),運營維護(hù)。創(chuàng)新互聯(lián)從2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。Kafka 是一個高吞吐量的分布式的發(fā)布訂閱消息系統(tǒng),在全世界都很流行,在大數(shù)據(jù)項目里面使用尤其頻繁。筆者看過多個大數(shù)據(jù)開源產(chǎn)品的源碼,感覺 Kafka 的源碼是其中質(zhì)量比較上乘的一個,這得益于作者高超的編碼水平和高超的架構(gòu)設(shè)計能力。
Kafka 的核心源碼分為兩部分:客戶端源碼和服務(wù)端源碼,客戶端又分為生產(chǎn)者和消費者,而個人認(rèn)為 Kafka 的源碼里面生產(chǎn)者的源碼技術(shù)含量最高,所以今天給大家剖析 Kafka 的生產(chǎn)者的架構(gòu)設(shè)計,Kafka 是一個飛速發(fā)展的消息系統(tǒng),其架構(gòu)也在一直演進(jìn)中,我們今天分析的 Kafka 的版本是比較成熟穩(wěn)定的 Kafka1.0.0 版本源碼。
圖1 Kafka核心模塊
生產(chǎn)者流程概述
先給大家介紹一下生產(chǎn)者的大概的運行的流程。
圖2 Kafka運行方式
如上圖所示:步驟一:一條消息過來首先會被封裝成為一個 ProducerRecord 對象。
步驟二:接下來要對這個對象進(jìn)行序列化,因為 Kafka 的消息需要從客戶端傳到服務(wù)端,涉及到網(wǎng)絡(luò)傳輸,所以需要實現(xiàn)序列。Kafka 提供了默認(rèn)的序列化機(jī)制,也支持自定義序列化(這種設(shè)計也值得我們積累,提高項目的擴(kuò)展性)。
步驟三:消息序列化完了以后,對消息要進(jìn)行分區(qū),分區(qū)的時候需要獲取集群的元數(shù)據(jù)。分區(qū)的這個過程很關(guān)鍵,因為這個時候就決定了,我們的這條消息會被發(fā)送到 Kafka 服務(wù)端到哪個主題的哪個分區(qū)了。
步驟四:分好區(qū)的消息不是直接被發(fā)送到服務(wù)端,而是放入了生產(chǎn)者的一個緩存里面。在這個緩存里面,多條消息會被封裝成為一個批次(batch),默認(rèn)一個批次的大小是 16K。
步驟五:Sender 線程啟動以后會從緩存里面去獲取可以發(fā)送的批次。
步驟六:Sender 線程把一個一個批次發(fā)送到服務(wù)端。大家要注意這個設(shè)計,在 Kafka0.8 版本以前,Kafka 生產(chǎn)者的設(shè)計是來一條數(shù)據(jù),就往服務(wù)端發(fā)送一條數(shù)據(jù),頻繁的發(fā)生網(wǎng)絡(luò)請求,結(jié)果性能很差。后面的版本再次架構(gòu)演進(jìn)的時候把這兒改成了批處理的方式,性能指數(shù)級的提升,這個設(shè)計值得我們積累。
生產(chǎn)者細(xì)節(jié)深度剖析
接下來我們生產(chǎn)者這兒技術(shù)含量比較高的一個地方,前面概述那兒我們看到,一個消息被分區(qū)以后,消息就會被放到一個緩存里面,我們看一下里面具體的細(xì)節(jié)。默認(rèn)緩存塊的大小是 32M,這個緩存塊里面有一個重要的數(shù)據(jù)結(jié)構(gòu):batches,這個數(shù)據(jù)結(jié)構(gòu)是 key-value 的結(jié)果,key 就是消息主題的分區(qū),value 是一個隊列,里面存的是發(fā)送到對應(yīng)分區(qū)的批次,Sender 線程就是把這些批次發(fā)送到服務(wù)端。
圖3 生產(chǎn)者架構(gòu)
01 / 生產(chǎn)者高級設(shè)計之自定義數(shù)據(jù)結(jié)構(gòu)
生產(chǎn)者把批次信息用 batches 這個對象進(jìn)行存儲。如果是大家,大家會考慮用什么數(shù)據(jù)結(jié)構(gòu)去存儲批次信息?
Kafka 這兒采取的方式是自定義了一個數(shù)據(jù)結(jié)構(gòu):CopyOnWriteMap。熟悉 Java 的同學(xué)都知道,JUC 下面是有一個 CopyOnWriteArrayList 的數(shù)據(jù)結(jié)構(gòu)的,但是沒有 CopyOnWriteMap,我這兒給大家解釋一下 Kafka 為什么要設(shè)計這樣的一個數(shù)據(jù)結(jié)構(gòu)。
1.他們存儲的信息的是 key-value 的結(jié)構(gòu),key 是分區(qū),value 是要存到這個分區(qū)的對應(yīng)批次(批次可能有多個,所以用的是隊列),故因為是 key-value 的數(shù)據(jù)結(jié)構(gòu),所以鎖定用 Map 數(shù)據(jù)結(jié)構(gòu)。
2.這個 Kafka 生產(chǎn)者面臨的是一個高并發(fā)的場景,大量的消息會涌入這個這個數(shù)據(jù)結(jié)構(gòu),所以這個數(shù)據(jù)結(jié)構(gòu)需要保證線程安全,這樣我們就不能使用 HashMap 這樣的數(shù)據(jù)結(jié)構(gòu)了。
3.這個數(shù)據(jù)結(jié)構(gòu)需要支持的是讀多寫少的場景。讀多是因為每條消息過來都會根據(jù) key 讀取 value 的信息,假如有 1000 萬條消息,那么就會讀取 batches 對象 1000 萬次。寫少是因為,比如我們生產(chǎn)者發(fā)送數(shù)據(jù)需要往一個主題里面去發(fā)送數(shù)據(jù),假設(shè)這個主題有 50 個分區(qū),那么這個 batches 里面就需要寫 50 個 key-value 數(shù)據(jù)就可以了(大家要搞清楚我們雖然要寫 1000 萬條數(shù)據(jù),但是這 1000 萬條是寫入 queue 隊列的 batch 里的,并不是直接寫入 batches,所以就我們剛剛說的這個場景,batches 里只需要最多寫 50 條數(shù)據(jù)就可以了)。
根據(jù)第二和第三個場景我們總結(jié)出來,Kafka 這兒需要一個能保證線程安全的,支持讀多寫少的 Map 數(shù)據(jù)結(jié)構(gòu)。但是 Java 里面并沒有提供出來的這樣的一個數(shù)據(jù),唯一跟這個需求比較接近的是 CopyOnWriteArrayList,但是偏偏它又不是 Map 結(jié)構(gòu),所以 Kafka 這兒模仿 CopyOnWriteArrayList 設(shè)計了 CopyOnWriteMap。采用了讀寫分離的思想解決了線程安全且支持讀多寫少等問題。
高效的數(shù)據(jù)結(jié)構(gòu)保證了生產(chǎn)者的性能。(CopyOnWriteArrayList 不熟悉的同學(xué),可以嘗試百度學(xué)習(xí))。這兒筆者建議大家可以去看看 Kafka 生產(chǎn)者往 batches 里插入數(shù)據(jù)的源碼,生產(chǎn)者為了保證插入數(shù)據(jù)的高性能,采用了多線程,又為了線程安全,使用了分段加鎖等多種手段,源碼非常精彩。
02 / 生產(chǎn)者高級設(shè)計之內(nèi)存池設(shè)計
剛剛我們看到 batches 里面存儲的是批次,批次默認(rèn)的大小是 16K,整個緩存的大小是 32M,生產(chǎn)者每封裝一個批次都需要去申請內(nèi)存,正常情況下如果一個批次發(fā)送出去了以后,那么這 16K 的內(nèi)存就等著 GC 來回收了。但是如果是這樣的話,就可能會頻繁的引發(fā) FullGC,故而影響生產(chǎn)者的性能,所以在緩存里面設(shè)計了一個內(nèi)存池(類似于我們平時用的數(shù)據(jù)庫的連接池),一個 16K 的內(nèi)存用完了以后,把數(shù)據(jù)清空,放入到內(nèi)存池里,下個批次用的時候直接從里面獲取就可以。這樣大大的減少了 GC 的頻率,保證了生產(chǎn)者的穩(wěn)定和高效(Java 的 GC 問題是一個頭疼的問題,所以這種設(shè)計也非常值得我們?nèi)シe累)。
以上就是Kafka的生產(chǎn)者優(yōu)秀架構(gòu)設(shè)計的示例分析,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。