新聞中心
Kafka 精妙的高性能設(shè)計(jì)之一
作者: 駱俊武 2021-08-30 09:30:29
架構(gòu)
Kafka Kafka 的高性能設(shè)計(jì)可以說(shuō)是全方位的,從 Prodcuer 、到 Broker、再到 Consumer,Kafka 在掏空心思地優(yōu)化每一個(gè)細(xì)節(jié),最終才做到了這樣的極致性能。

目前成都創(chuàng)新互聯(lián)公司已為近千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、奎屯網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
這是《吃透 MQ 系列》之 Kafka 的第 4 篇,錯(cuò)過(guò)前 3 篇的,通過(guò)下面的鏈接一睹為快:
第 1 篇:扒開(kāi) Kafka 的神秘面紗
第 2 篇:Kafka 架構(gòu)設(shè)計(jì)的任督二脈
第 3 篇:Kafka 存儲(chǔ)選型的奧秘
第 3 篇文章我深入剖析了 Kafka 選用「日志文件」作為存儲(chǔ)方案的來(lái)龍去脈以及背后「磁盤(pán)順序?qū)?+ 稀疏索引」的精妙設(shè)計(jì)思路。
但是,Kafka 能做到單機(jī)每秒幾十萬(wàn)的吞吐量,它的性能優(yōu)化手段絕不止這一點(diǎn)。
Kafka 的高性能設(shè)計(jì)可以說(shuō)是全方位的,從 Prodcuer 、到 Broker、再到 Consumer,Kafka 在掏空心思地優(yōu)化每一個(gè)細(xì)節(jié),最終才做到了這樣的極致性能。
這篇文章我想先帶大家建立一個(gè)高性能設(shè)計(jì)的思維模式,然后再一探究竟 Kafka 的高性能設(shè)計(jì)方案,最終讓大家更體系地掌握所有知識(shí)點(diǎn),并理解它的設(shè)計(jì)哲學(xué)。
一. 如何理解高性能設(shè)計(jì)?
我們暫且把 Kafka 拋在一邊,先嘗試?yán)斫庀赂咝阅茉O(shè)計(jì)的本質(zhì)。
有過(guò)高并發(fā)開(kāi)發(fā)經(jīng)驗(yàn)的同學(xué),對(duì)于線程池、多級(jí)緩存、IO 多路復(fù)用、零拷貝等技術(shù)概念早就了然于胸,但是返璞歸真,這些技術(shù)手段的本質(zhì)到底是什么?
這其實(shí)是一個(gè)系統(tǒng)性的問(wèn)題,至少需要深入到操作系統(tǒng)層面,從 CPU 和存儲(chǔ)入手,去了解底層的實(shí)現(xiàn)機(jī)制,然后再自底往上,一層一層去解密和貫穿起來(lái)。
但是站在更高的視角來(lái)看,我認(rèn)為:高性能設(shè)計(jì)其實(shí)萬(wàn)變不離其宗,一定是從「計(jì)算和 IO」這兩個(gè)維度出發(fā),去考慮可能的優(yōu)化點(diǎn)。
那「計(jì)算」維度的性能優(yōu)化手段有哪些呢?無(wú)外乎這兩種方式:
1、讓更多的核來(lái)參與計(jì)算:比如用多線程代替單線程、用集群代替單機(jī)等。
2、減少計(jì)算量:比如用索引來(lái)取代全局掃描、用同步代替異步、通過(guò)限流來(lái)減少請(qǐng)求處理量、采用更高效的數(shù)據(jù)結(jié)構(gòu)和算法等。
再看下「IO」維度的性能優(yōu)化手段又有哪些? 可以通過(guò) Linux 系統(tǒng)的 IO 棧圖來(lái)輔助思考。
圖 1:Linux 系統(tǒng)的 IO 棧圖
可以看到,整個(gè) IO 體系結(jié)構(gòu)是分層的,我們能夠從應(yīng)用程序、操作系統(tǒng)、磁盤(pán)等各個(gè)層次來(lái)考慮性能優(yōu)化,而所有這些手段又幾乎圍繞以下兩個(gè)方面展開(kāi):
1、加快 IO 速度:比如用磁盤(pán)順序?qū)懘骐S機(jī)寫(xiě)、用 NIO 代替 BIO、用性能更好的 SSD 代替機(jī)械硬盤(pán)等。
2、減少 IO 次數(shù)或者 IO 數(shù)據(jù)量:比如借助系統(tǒng)緩存或者外部緩存、通過(guò)零拷貝技術(shù)減少 IO 復(fù)制次數(shù)、批量讀寫(xiě)、數(shù)據(jù)壓縮等。
上面這些內(nèi)容可以理解成高性能設(shè)計(jì)的「道」,當(dāng)然絕不是幾百字就可以說(shuō)清楚的,我更多的是拋磚引玉,用另外一個(gè)視角來(lái)看高并發(fā),給大家一個(gè)方向上的指引。
當(dāng)大家抓住了「計(jì)算和 IO」這兩個(gè)最本質(zhì)的東西,然后以這兩點(diǎn)作為根,再去探究這兩個(gè)維度分別有哪些性能優(yōu)化手段?它們的原理又是什么樣的?便能一層一層剝開(kāi)高性能設(shè)計(jì)的神秘面紗,形成可靠的知識(shí)體系。
這種分析方法可用來(lái)研究 Kafka,同樣可以用來(lái)研究我們熟知的 Redis、ES 以及其他高性能的應(yīng)用系統(tǒng)。
二. Kafka 高性能設(shè)計(jì)的全景圖
有了高性能設(shè)計(jì)的思維模式后,我們?cè)倩氐?Kafka 本身進(jìn)行分析。
前文提到過(guò) Kafka 的性能優(yōu)化手段非常豐富,至少有 10 條以上的精妙設(shè)計(jì),雖然我們可以從計(jì)算和 IO 兩個(gè)維度去聯(lián)想這些手段,但是要完整地記住它們,似乎也不是件容易的事。
這樣就引出了另外一個(gè)話題:我們應(yīng)該選用一條什么樣的脈絡(luò),去串聯(lián)這些優(yōu)化手段呢?
之前的文章做過(guò)分析:不管 Kafka 、RocketMQ 還是其他消息隊(duì)列,其本質(zhì)都是「一發(fā)一存一消費(fèi)」。
我們完全可以順著這條主線去做結(jié)構(gòu)化梳理?;谶@個(gè)思路,便形成了下面這張 Kafka 高性能設(shè)計(jì)的全景圖,我按照生產(chǎn)消息、存儲(chǔ)消息、消費(fèi)消息 3 個(gè)模塊,將 Kafka 最具代表性的 12 條性能優(yōu)化手段做了歸類。
圖 2:Kafka 高性能設(shè)計(jì)的全景圖
有了這張全景圖,下面我再挨個(gè)分析下每個(gè)手段背后的大致原理,并嘗試解讀下 Kafka 的設(shè)計(jì)哲學(xué)。
三. 生產(chǎn)消息的性能優(yōu)化手段
我們先從生產(chǎn)消息開(kāi)始看,下面是 Producer 端所采用的 4 條優(yōu)化手段。
1、批量發(fā)送消息
Kafka 作為一個(gè)消息隊(duì)列,很顯然是一個(gè) IO 密集型應(yīng)用,它所面臨的挑戰(zhàn)除了磁盤(pán) IO(Broker 端需要對(duì)消息持久化),還有網(wǎng)絡(luò) IO(Producer 到 Broker,Broker 到 Consumer,都需要通過(guò)網(wǎng)絡(luò)進(jìn)行消息傳輸)。
在上一篇文章已經(jīng)指出過(guò):磁盤(pán)順序 IO 的速度其實(shí)非??欤粊営趦?nèi)存隨機(jī)讀寫(xiě)。這樣網(wǎng)絡(luò) IO 便成為了 Kafka 的性能瓶頸所在。
基于這個(gè)背景, Kafka 采用了批量發(fā)送消息的方式,通過(guò)將多條消息按照分區(qū)進(jìn)行分組,然后每次發(fā)送一個(gè)消息集合,從而大大減少了網(wǎng)絡(luò)傳輸?shù)?overhead。
看似很平常的一個(gè)手段,其實(shí)它大大提升了 Kafka 的吞吐量,而且它的精妙之處遠(yuǎn)非如此,下面幾條優(yōu)化手段都和它息息相關(guān)。
2、消息壓縮
消息壓縮的目的是為了進(jìn)一步減少網(wǎng)絡(luò)傳輸帶寬。而對(duì)于壓縮算法來(lái)說(shuō),通常是:數(shù)據(jù)量越大,壓縮效果才會(huì)越好。
因?yàn)橛辛伺堪l(fā)送這個(gè)前期,從而使得 Kafka 的消息壓縮機(jī)制能真正發(fā)揮出它的威力(壓縮的本質(zhì)取決于多消息的重復(fù)性)。對(duì)比壓縮單條消息,同時(shí)對(duì)多條消息進(jìn)行壓縮,能大幅減少數(shù)據(jù)量,從而更大程度提高網(wǎng)絡(luò)傳輸率。
有文章對(duì) Kafka 支持的三種壓縮算法:gzip、snappy、lz4 進(jìn)行了性能對(duì)比,測(cè)試 2 萬(wàn)條消息,效果如下:
圖 3:壓縮效果對(duì)比,來(lái)源:https://www.jianshu.com/p/d69e27749b00
整體來(lái)看,gzip 壓縮效果最好,但是生成耗時(shí)更長(zhǎng),綜合對(duì)比 lz4 性能最佳。
其實(shí)壓縮消息不僅僅減少了網(wǎng)絡(luò) IO,它還大大降低了磁盤(pán) IO。因?yàn)榕肯⒃诔志没?Broker 中的磁盤(pán)時(shí),仍然保持的是壓縮狀態(tài),最終是在 Consumer 端做了解壓縮操作。
這種端到端的壓縮設(shè)計(jì),其實(shí)非常巧妙,它又大大提高了寫(xiě)磁盤(pán)的效率。
3、高效序列化
Kafka 消息中的 Key 和 Value,都支持自定義類型,只需要提供相應(yīng)的序列化和反序列化器即可。因此,用戶可以根據(jù)實(shí)際情況選用快速且緊湊的序列化方式(比如 ProtoBuf、Avro)來(lái)減少實(shí)際的網(wǎng)絡(luò)傳輸量以及磁盤(pán)存儲(chǔ)量,進(jìn)一步提高吞吐量。
4、內(nèi)存池復(fù)用
前面說(shuō)過(guò) Producer 發(fā)送消息是批量的,因此消息都會(huì)先寫(xiě)入 Producer 的內(nèi)存中進(jìn)行緩沖,直到多條消息組成了一個(gè) Batch,才會(huì)通過(guò)網(wǎng)絡(luò)把 Batch 發(fā)給 Broker。
當(dāng)這個(gè) Batch 發(fā)送完畢后,顯然這部分?jǐn)?shù)據(jù)還會(huì)在 Producer 端的 JVM 內(nèi)存中,由于不存在引用了,它是可以被 JVM 回收掉的。
但是大家都知道,JVM GC 時(shí)一定會(huì)存在 Stop The World 的過(guò)程,即使采用最先進(jìn)的垃圾回收器,也勢(shì)必會(huì)導(dǎo)致工作線程的短暫停頓,這對(duì)于 Kafka 這種高并發(fā)場(chǎng)景肯定會(huì)帶來(lái)性能上的影響。
有了這個(gè)背景,便引出了 Kafka 非常優(yōu)秀的內(nèi)存池機(jī)制,它和連接池、線程池的本質(zhì)一樣,都是為了提高復(fù)用,減少頻繁的創(chuàng)建和釋放。
具體是如何實(shí)現(xiàn)的呢?其實(shí)很簡(jiǎn)單:Producer 一上來(lái)就會(huì)占用一個(gè)固定大小的內(nèi)存塊,比如 64MB,然后將 64 MB 劃分成 M 個(gè)小內(nèi)存塊(比如一個(gè)小內(nèi)存塊大小是 16KB)。
當(dāng)需要?jiǎng)?chuàng)建一個(gè)新的 Batch 時(shí),直接從內(nèi)存池中取出一個(gè) 16 KB 的內(nèi)存塊即可,然后往里面不斷寫(xiě)入消息,但最大寫(xiě)入量就是 16 KB,接著將 Batch 發(fā)送給 Broker ,此時(shí)該內(nèi)存塊就可以還回到緩沖池中繼續(xù)復(fù)用了,根本不涉及垃圾回收。最終整個(gè)流程如下圖所示:
圖 4:Kafka 發(fā)送端的流程
了解了 Producer 端上面 4 條高性能設(shè)計(jì)后,大家一定會(huì)有一個(gè)疑問(wèn):傳統(tǒng)的數(shù)據(jù)庫(kù)或者消息中間件都是想辦法讓 Client 端更輕量,將 Server 設(shè)計(jì)成重量級(jí),僅讓 Client 充當(dāng)應(yīng)用程序和 Server 之間的接口。
但是 Kafka 卻反其道而行之,采取了獨(dú)具一格的設(shè)計(jì)思路,在將消息發(fā)送給 Broker 之前,需要先在 Client 端完成大量的工作,例如:消息的分區(qū)路由、校驗(yàn)和的計(jì)算、壓縮消息等。這樣便很好地分?jǐn)?Broker 的計(jì)算壓力。
可見(jiàn),沒(méi)有最好的設(shè)計(jì),只有最合適的設(shè)計(jì),這就是架構(gòu)的本源。
四. 寫(xiě)在最后
Kafka 在創(chuàng)造一個(gè)以性能為核心導(dǎo)向的解決方案上做得極其出色,它有非常多的設(shè)計(jì)理念值得深入研究和學(xué)習(xí)。
考慮篇幅問(wèn)題,我將 Kafka 的高性能設(shè)計(jì)分成了上下兩篇,下一篇將繼續(xù)展開(kāi)闡述剩余 8 條高性能設(shè)計(jì)手段以及背后的設(shè)計(jì)思想。
看到這里,我更希望大家能建立起高性能設(shè)計(jì)的思維模式以及學(xué)習(xí)方法,這些技巧同樣可以幫助你吃透其他高性能的中間件。
新聞標(biāo)題:Kafka精妙的高性能設(shè)計(jì)之一
URL鏈接:http://fisionsoft.com.cn/article/ccdhsee.html


咨詢
建站咨詢
