<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Kafka 精妙的高性能設(shè)計(jì)(上篇)

          共 3872字,需瀏覽 8分鐘

           ·

          2021-12-09 19:30

          大家好,我是武哥。
          這是《吃透 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é)。

          ?1. 如何理解高性能設(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)。

          ?2. 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)化手段做了歸類(lèi)。

          圖 2:Kafka 高性能設(shè)計(jì)的全景圖

          有了這張全景圖,下面我再挨個(gè)分析下每個(gè)手段背后的大致原理,并嘗試解讀下 Kafka 的設(shè)計(jì)哲學(xué)。

          ?3. 生產(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í)非??欤?/span>不亞于內(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,都支持自定義類(lèi)型,只需要提供相應(yīng)的序列化和反序列化器即可。因此,用戶(hù)可以根據(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)?/span> Broker 的計(jì)算壓力。
          可見(jiàn),沒(méi)有最好的設(shè)計(jì),只有最合適的設(shè)計(jì),這就是架構(gòu)的本源。

          ?4. 寫(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í)方法,這些技巧同樣可以幫助你吃透其他高性能的中間件。

          推薦閱讀:

          如出一轍。。。

          Java 中的監(jiān)控與管理原理概述

          《吃透 MQ 系列》之 Kafka 架構(gòu)設(shè)計(jì)的任督二脈

          《吃透 MQ 系列》之扒開(kāi) Kafka 的神秘面紗

          《吃透 MQ 系列》之 Kafka 存儲(chǔ)選型的奧秘



          關(guān)號(hào)互聯(lián)網(wǎng)全棧架構(gòu)價(jià)。

          瀏覽 35
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美另类欧美另类欧美另类 | 欧美成人三级片网站 | 亚洲电影无码 | 免费最婬荡的毛片A | 欧美一级做一级a 做片性视频 |