原文地址:http://www.reibang.com/p/e0f23cb5b0e0
前言:講解透徹瘦棋,從存儲(chǔ)到系統(tǒng),硬件鲜棠,網(wǎng)絡(luò)細(xì)節(jié)綜合考慮
問(wèn):講講kafka為什么這么快?
答:kafka的快是從底層設(shè)計(jì),到充分利用硬件,系統(tǒng),壓縮等等特性,綜合產(chǎn)生的結(jié)果肌厨。
要理解 kafka為什么這么快,要從以下幾個(gè)方面如下:
1.磁盤(pán)讀寫(xiě)原理
2.利用Pagecache+mmap
3.零拷貝
4.存儲(chǔ)設(shè)計(jì)
5.批量讀寫(xiě)
6.批量壓縮
7.消息寫(xiě)入過(guò)程
8.消息讀取過(guò)程
一 磁盤(pán)讀寫(xiě)原理
磁盤(pán)的結(jié)構(gòu)圖:
圖片
當(dāng)需要從磁盤(pán)讀取數(shù)據(jù)時(shí)岔留,要確定讀的數(shù)據(jù)在哪個(gè)磁道夏哭,哪個(gè)扇區(qū):
首先必須找到柱面检柬,即磁頭需要移動(dòng)對(duì)準(zhǔn)相應(yīng)磁道献联,這個(gè)過(guò)程叫做尋道,所耗費(fèi)時(shí)間叫做尋道時(shí)間;
然后目標(biāo)扇區(qū)旋轉(zhuǎn)到磁頭下,這個(gè)過(guò)程耗費(fèi)的時(shí)間叫做旋轉(zhuǎn)時(shí)間何址;
一次訪盤(pán)請(qǐng)求(讀/寫(xiě))完成過(guò)程由三個(gè)動(dòng)作組成
尋道(時(shí)間):磁頭移動(dòng)定位到指定磁道;
旋轉(zhuǎn)延遲(時(shí)間):等待指定扇區(qū)從磁頭下旋轉(zhuǎn)經(jīng)過(guò)里逆;
數(shù)據(jù)傳輸(時(shí)間):數(shù)據(jù)在磁盤(pán)、內(nèi)存與網(wǎng)絡(luò)之間的實(shí)際傳輸
由于存儲(chǔ)介質(zhì)的特性用爪,磁盤(pán)本身存取就比主存慢原押,再加上機(jī)械運(yùn)動(dòng)耗費(fèi),磁盤(pán)的存取速度往往是主存的幾百分之一甚至幾千分之一
怎么樣才能提高磁盤(pán)的讀寫(xiě)效率呢?
根據(jù)數(shù)據(jù)的局部性原理﹐有以下兩種方法
預(yù)讀或者提前讀;
合并寫(xiě)——多個(gè)邏輯上的寫(xiě)操作合并成一個(gè)大的物理寫(xiě)操作中;
即采用磁盤(pán)順序讀寫(xiě)(不需要尋道時(shí)間偎血,只需很少的旋轉(zhuǎn)時(shí)間)诸衔。僅僅將數(shù)據(jù)追加到文件的末尾盯漂,不是在文件的隨機(jī)位置來(lái)修改數(shù)據(jù),磁盤(pán)順序?qū)懙男阅芑旧峡梢愿鷮?xiě)內(nèi)存的性能相差無(wú)幾笨农。
實(shí)驗(yàn)結(jié)果:在一個(gè)6 7200rpm - SATA RAID-5 的磁盤(pán)陣列上線性寫(xiě)的速度大概是300M/秒,但是隨機(jī)寫(xiě)的速度只有50K/秒就缆,兩者- 相差將近10000倍。
二 利用page cache+mmap
1.page cache
圖片
執(zhí)行free -m命令谒亦,看內(nèi)存使用情況竭宰,大家都做過(guò),有幾個(gè)名詞需要解釋下:
Page Cache : 以 Page為單位份招,緩存文件內(nèi)容.cached這列代表當(dāng)前頁(yè)緩存的占用量切揭。
Buffer cache :磁盤(pán)等塊設(shè)備的緩存.Buffers列代表塊緩存的使用量.
數(shù)據(jù)讀寫(xiě)的過(guò)程大致如下圖:
Page Cache(os cache):【操作系統(tǒng)自己管理的緩存】以Page為單位,緩存文件內(nèi)容锁摔。緩存在Page Cache中的文件數(shù)據(jù)廓旬,能夠更快的被用戶讀取。同時(shí)對(duì)于帶buffer的寫(xiě)入操作鄙漏,數(shù)據(jù)在寫(xiě)入到Page Cache中即可立即返回嗤谚,而不需等待數(shù)據(jù)被實(shí)際持久化到磁盤(pán),進(jìn)而提高了上層應(yīng)用讀寫(xiě)文件的整體性能怔蚌。cached這列的數(shù)值表示的是當(dāng)前的頁(yè)緩存(page cache)的占用量巩步,page cache文件的頁(yè)數(shù)據(jù),頁(yè)是邏輯上的概念桦踊,因此page cache是與文件系統(tǒng)同級(jí)的
buffer cache:磁盤(pán)等塊設(shè)備的緩沖椅野,內(nèi)存的這一部分是要寫(xiě)入到磁盤(pán)里的 。buffers列 表示當(dāng)前的塊緩存(buffer cache)占用量籍胯,buffer cache用于緩存塊設(shè)備(如磁盤(pán))的塊數(shù)據(jù)竟闪。塊是物理上的概念,因此buffer cache是與塊設(shè)備驅(qū)動(dòng)程序同級(jí)的杖狼。
Kafka 在寫(xiě)入磁盤(pán)文件的時(shí)候炼蛤,可以直接寫(xiě)入這個(gè) os cache 里,也就是僅僅寫(xiě)入內(nèi)存中蝶涩,接下來(lái)由操作系統(tǒng)自己決定什么時(shí)候把 os cache 里的數(shù)據(jù)真的刷入磁盤(pán)文件中理朋。通過(guò)這一個(gè)步驟,就可以將磁盤(pán)文件 寫(xiě)性能 提升很多了绿聘,因?yàn)槠鋵?shí)這里相當(dāng)于是在寫(xiě)內(nèi)存嗽上,不是在寫(xiě)磁盤(pán),原理圖如下:
image.png
圖片
問(wèn):利用page cache的好處是什么呢?
答:
1.避免broker內(nèi)存消耗.
2.避免GC問(wèn)題.
3.應(yīng)用重啟數(shù)據(jù)不會(huì)丟失.
相比于JMM或者In-memory cache , page cache優(yōu)勢(shì):
1.首先熄攘,操作系統(tǒng)層面的緩存利用率會(huì)更高兽愤,因?yàn)榇鎯?chǔ)的都是緊湊的字節(jié)結(jié)構(gòu)而不是獨(dú)立的對(duì)象。
2.其次,操作系統(tǒng)本身也對(duì)于Page Cache做了大量?jī)?yōu)化浅萧,提供了write-behind逐沙、 read-ahead 以及 flush等多種機(jī)制.
3.再者,即使服務(wù)進(jìn)程重啟,系統(tǒng)緩存依然不會(huì)消失洼畅,避免in-process cache重建緩存的過(guò)程
2.什么是mmap
問(wèn):mmap 又是什么呢?有什么優(yōu)勢(shì)?
答:Mmap即是Memory Mapped Files內(nèi)存文件映射酱吝。
大致意思如下圖:
mmap:
mmap其實(shí)就是把物理上的磁盤(pán)文件的一些地址和page cache地址進(jìn)行一層映射,使得進(jìn)程像讀寫(xiě)硬盤(pán)一樣讀寫(xiě)內(nèi)存,定時(shí)有os幫助我們將數(shù)據(jù)刷寫(xiě)到磁盤(pán),30 s.
三 土思、零拷貝
問(wèn):能詳細(xì)講解一下零拷貝嗎?
答:零拷貝要想明白必須要了解linux,的用戶態(tài)务热,內(nèi)核態(tài),以及磁盤(pán)的數(shù)據(jù)是如何通過(guò)網(wǎng)卡發(fā)送到消費(fèi)者的己儒。
從系統(tǒng)安全和保護(hù)的角度出發(fā)崎岂,在進(jìn)行計(jì)算機(jī)體系結(jié)構(gòu)設(shè)計(jì)時(shí),處理機(jī)的執(zhí)行模式一般分為兩種:
分別稱為內(nèi)核模式(內(nèi)核態(tài))和用戶模式(用戶態(tài))闪湾。
當(dāng)處理機(jī)處于內(nèi)核模式執(zhí)行時(shí)冲甘,意味著系統(tǒng)除了可以執(zhí)行一般指令外,還可以執(zhí)行特權(quán)指令途样,即可以執(zhí)行訪問(wèn)各種控制寄存器的指令江醇、I/O指令以及程序狀態(tài)字。
當(dāng)處理機(jī)處于用戶模式執(zhí)行時(shí)何暇,只能執(zhí)行一般指令陶夜,而不允許執(zhí)行特權(quán)指令。
這樣做可以保護(hù)核心代碼不受用戶程序有意和無(wú)意的攻擊裆站。
顯然条辟,處理機(jī)在運(yùn)行期間需要在內(nèi)核模式和用戶模式之前進(jìn)行切換。
應(yīng)用程序要將磁盤(pán)數(shù)據(jù)通過(guò)網(wǎng)卡發(fā)出去非零拷貝需要:
a.操作系統(tǒng)將數(shù)據(jù)從磁盤(pán)拷貝到內(nèi)核區(qū)的 pagecache
b.用戶程序?qū)?nèi)核區(qū)的 pagecache拷貝到用戶區(qū)緩存
c.用戶程序?qū)⒂脩魠^(qū)的緩存拷貝到socket緩存中
d.操作系統(tǒng)將socket緩存中的數(shù)據(jù)拷貝到網(wǎng)卡的 buffer 上發(fā)送數(shù)據(jù)
大致流程圖如下:
可以發(fā)現(xiàn)一次IO請(qǐng)求操作進(jìn)行了2次上下文切換和4次系統(tǒng)調(diào)用宏胯,而同一份數(shù)據(jù)在緩存中多次拷貝羽嫡,實(shí)際上對(duì)于拷貝來(lái)說(shuō)完全可以直接在內(nèi)核態(tài)中進(jìn)行,也就是省去第2和第3步驟肩袍,變成這樣:
kafka 集群經(jīng)過(guò)良好的調(diào)優(yōu)杭棵,數(shù)據(jù)直接寫(xiě)入 os cache 中,然后讀數(shù)據(jù)的時(shí)候也是從 os cache 中讀氛赐。相當(dāng)于 Kafka 完全基于內(nèi)存提供數(shù)據(jù)的寫(xiě)和讀了魂爪,所以這個(gè)整體性能會(huì)極其的高。
四鹰祸、 存儲(chǔ)設(shè)計(jì)
1.topic進(jìn)行分區(qū)? -->partition
2.partition為了方便超時(shí)刪除等管理,又進(jìn)一步劃分segment
3.每個(gè)saement.又包括了index文件和 log 文件,可以二分查找快速定位數(shù)據(jù).
4.segment 數(shù)據(jù)只允許追加的形式.
5.offset是連續(xù)的支持預(yù)讀和批量寫(xiě).
五 甫窟、批量發(fā)送
很多情況下密浑,系統(tǒng)的瓶頸不是cpu,內(nèi)存,磁盤(pán)io蛙婴,而是網(wǎng)絡(luò)IO。為了減少網(wǎng)絡(luò)通信的次數(shù),往往需要批量發(fā)送,kafka支持尔破。
batch.size消息條數(shù)積累到該閾值街图,立即發(fā)送.
linger.ms不管消息有沒(méi)有積累足夠條數(shù),超過(guò)該時(shí)間就立即發(fā)送
六 浇衬、壓縮
對(duì)于消息隊(duì)列很多情況下,系統(tǒng)的瓶頸不是cpu餐济,內(nèi)存耘擂,磁盤(pán)io,而是網(wǎng)絡(luò)IO.
還有些公司是千兆網(wǎng)卡絮姆,隨便多啟動(dòng)幾個(gè)流任務(wù)就有可能把 kafka流量打滿.
所以壓縮對(duì)于kafka來(lái)說(shuō)節(jié)省網(wǎng)絡(luò)IO是很有必要的醉冤,雖然會(huì)消耗一定cpu.
廣域網(wǎng)上傳輸?shù)臄?shù)據(jù),節(jié)省帶寬,就是節(jié)省錢(qián)!
如果每個(gè)消息都?jí)嚎s篙悯,但是壓縮率相對(duì)很低蚁阳,所以Kafka使用了批量壓縮,即將多個(gè)消息一起壓縮而不是單個(gè)消息壓縮
Kafka允許使用遞歸的消息集合鸽照,批量的消息可以通過(guò)壓縮的形式傳輸并且在日志中也可以保持壓縮格式螺捐,直到被消費(fèi)者解壓縮
Kafka支持多種壓縮協(xié)議,包括Gzip和Snappy壓縮協(xié)議
七矮燎、 消息寫(xiě)的過(guò)程
生產(chǎn)者發(fā)送批量壓縮的數(shù)據(jù)到broker定血,broker通過(guò)MappedByteBuffer的map()函數(shù)映射其地址到你的虛擬內(nèi)存地址。
接著就可以對(duì)這個(gè)MappedByteBuffer執(zhí)行寫(xiě)入操作了诞外,寫(xiě)入的時(shí)候他會(huì)直接進(jìn)入PageCache中澜沟,
然后過(guò)一段時(shí)間之后,由os的線程異步刷入磁盤(pán)中峡谊,可以看上面的示意圖倔喂。
上圖中似乎只有一次數(shù)據(jù)拷貝的過(guò)程,他就是從PageCache里拷貝到磁盤(pán)文件里而已靖苇!這個(gè)就是你使用mmap技術(shù)之后席噩,相比于傳統(tǒng)磁盤(pán)IO的一個(gè)性能優(yōu)化
八 消息讀的過(guò)程
圖片
讀取數(shù)據(jù)的時(shí)候,會(huì)先判斷page cache中是否存在贤壁,存在就可以直接從page cache中消費(fèi)悼枢,所以消費(fèi)實(shí)時(shí)數(shù)據(jù)就會(huì)速度快很多。
但是消費(fèi)歷史數(shù)據(jù)就不得不將歷史數(shù)據(jù)重新加載到page cache脾拆,而且會(huì)污染掉page cache馒索。
PageCache技術(shù)在加載歷史數(shù)據(jù)的時(shí)候,還會(huì)將你加載的數(shù)據(jù)塊的臨近的其他數(shù)據(jù)塊也一起加載到PageCache里去名船,這其實(shí)就是一個(gè)預(yù)讀過(guò)程绰上,對(duì)于需要連續(xù)讀取歷史數(shù)據(jù)的,也是性能的不小優(yōu)化渠驼。