偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

終于知道Kafka為什么這么快了!

開源 Kafka
無論 Kafka 作為 MQ 也好,還是作為存儲層也罷,無非就是兩個(gè)功能,一是 Producer 生產(chǎn)的數(shù)據(jù)存到 Broker,二是 Consumer 從 Broker 讀取數(shù)據(jù)。

 無論 Kafka 作為 MQ 也好,還是作為存儲層也罷,無非就是兩個(gè)功能,一是 Producer 生產(chǎn)的數(shù)據(jù)存到 Broker,二是 Consumer 從 Broker 讀取數(shù)據(jù)。

[[337633]]
圖片來自 Pexels

 

那 Kafka 的快也就體現(xiàn)在讀寫兩個(gè)方面了,下面我們就聊聊 Kafka 快的原因。

[[337634]]

 

利用 Partition 實(shí)現(xiàn)并行處理

我們都知道 Kafka 是一個(gè) Pub-Sub 的消息系統(tǒng),無論是發(fā)布還是訂閱,都要指定 Topic。

Topic 只是一個(gè)邏輯的概念。每個(gè) Topic 都包含一個(gè)或多個(gè) Partition,不同 Partition 可位于不同節(jié)點(diǎn)。

一方面,由于不同 Partition 可位于不同機(jī)器,因此可以充分利用集群優(yōu)勢,實(shí)現(xiàn)機(jī)器間的并行處理。

另一方面,由于 Partition 在物理上對應(yīng)一個(gè)文件夾,即使多個(gè) Partition 位于同一個(gè)節(jié)點(diǎn),也可通過配置讓同一節(jié)點(diǎn)上的不同 Partition 置于不同的磁盤上,從而實(shí)現(xiàn)磁盤間的并行處理,充分發(fā)揮多磁盤的優(yōu)勢。

能并行處理,速度肯定會有提升,多個(gè)工人肯定比一個(gè)工人干的快??梢圆⑿袑懭氩煌拇疟P?那磁盤讀寫的速度可以控制嗎?那就先簡單扯扯磁盤 I/O 的那些事。

硬盤性能的制約因素是什么?如何根據(jù)磁盤 I/O 特性來進(jìn)行系統(tǒng)設(shè)計(jì)?

硬盤內(nèi)部主要部件為磁盤盤片、傳動手臂、讀寫磁頭和主軸馬達(dá)。實(shí)際數(shù)據(jù)都是寫在盤片上,讀寫主要是通過傳動手臂上的讀寫磁頭來完成。

實(shí)際運(yùn)行時(shí),主軸讓磁盤盤片轉(zhuǎn)動,然后傳動手臂可伸展讓讀取頭在盤片上進(jìn)行讀寫操作。

磁盤物理結(jié)構(gòu)如下圖所示:

 

由于單一盤片容量有限,一般硬盤都有兩張以上的盤片,每個(gè)盤片有兩面,都可記錄信息,所以一張盤片對應(yīng)著兩個(gè)磁頭。

盤片被分為許多扇形的區(qū)域,每個(gè)區(qū)域叫一個(gè)扇區(qū)。盤片表面上以盤片中心為圓心,不同半徑的同心圓稱為磁道,不同盤片相同半徑的磁道所組成的圓柱稱為柱面。

磁道與柱面都是表示不同半徑的圓,在許多場合,磁道和柱面可以互換使用。

磁盤盤片垂直視角如下圖所示:

 

影響磁盤的關(guān)鍵因素是磁盤服務(wù)時(shí)間,即磁盤完成一個(gè) I/O 請求所花費(fèi)的時(shí)間,它由尋道時(shí)間、旋轉(zhuǎn)延遲和數(shù)據(jù)傳輸時(shí)間三部分構(gòu)成。

機(jī)械硬盤的連續(xù)讀寫性能很好,但隨機(jī)讀寫性能很差,這主要是因?yàn)榇蓬^移動到正確的磁道上需要時(shí)間,隨機(jī)讀寫時(shí),磁頭需要不停的移動,時(shí)間都浪費(fèi)在了磁頭尋址上,所以性能不高。衡量磁盤的重要主要指標(biāo)是 IOPS 和吞吐量。

在許多的開源框架如 Kafka、HBase 中,都通過追加寫的方式來盡可能的將隨機(jī) I/O 轉(zhuǎn)換為順序 I/O,以此來降低尋址時(shí)間和旋轉(zhuǎn)延時(shí),從而最大限度的提高 IOPS。

感興趣的同學(xué)可以看看磁盤 I/O 那些事[1],磁盤讀寫的快慢取決于你怎么使用它,也就是順序讀寫或者隨機(jī)讀寫。

順序?qū)懘疟P

 

Kafka 中每個(gè)分區(qū)是一個(gè)有序的,不可變的消息序列,新的消息不斷追加到 Partition 的末尾,這個(gè)就是順序?qū)憽?/p>

很久很久以前就有人做過基準(zhǔn)測試:《每秒寫入 2 百萬(在三臺廉價(jià)機(jī)器上)》

  1. http://ifeve.com/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines/ 

由于磁盤有限,不可能保存所有數(shù)據(jù),實(shí)際上作為消息系統(tǒng) Kafka 也沒必要保存所有數(shù)據(jù),需要刪除舊的數(shù)據(jù)。

又由于順序?qū)懭氲脑?,所?Kafka 采用各種刪除策略刪除數(shù)據(jù)的時(shí)候,并非通過使用“讀 - 寫”模式去修改文件,而是將 Partition 分為多個(gè) Segment。

每個(gè) Segment 對應(yīng)一個(gè)物理文件,通過刪除整個(gè)文件的方式去刪除 Partition 內(nèi)的數(shù)據(jù)。

這種方式清除舊數(shù)據(jù)的方式,也避免了對文件的隨機(jī)寫操作。

充分利用 Page Cache

引入 Cache 層的目的是為了提高 Linux 操作系統(tǒng)對磁盤訪問的性能。Cache 層在內(nèi)存中緩存了磁盤上的部分?jǐn)?shù)據(jù)。

當(dāng)數(shù)據(jù)的請求到達(dá)時(shí),如果在 Cache 中存在該數(shù)據(jù)且是最新的,則直接將數(shù)據(jù)傳遞給用戶程序,免除了對底層磁盤的操作,提高了性能。Cache 層也正是磁盤 IOPS 為什么能突破 200 的主要原因之一。

在 Linux 的實(shí)現(xiàn)中,文件 Cache 分為兩個(gè)層面,一是 Page Cache,另一個(gè) Buffer Cache,每一個(gè) Page Cache 包含若干 Buffer Cache。

Page Cache 主要用來作為文件系統(tǒng)上的文件數(shù)據(jù)的緩存來用,尤其是針對當(dāng)進(jìn)程對文件有 read/write 操作的時(shí)候。

Buffer Cache 則主要是設(shè)計(jì)用來在系統(tǒng)對塊設(shè)備進(jìn)行讀寫的時(shí)候,對塊進(jìn)行數(shù)據(jù)緩存的系統(tǒng)來使用。

使用 Page Cache 的好處:

  • I/O Scheduler 會將連續(xù)的小塊寫組裝成大塊的物理寫從而提高性能。
  • I/O Scheduler 會嘗試將一些寫操作重新按順序排好,從而減少磁盤頭的移動時(shí)間。
  • 充分利用所有空閑內(nèi)存(非 JVM 內(nèi)存)。如果使用應(yīng)用層 Cache(即 JVM 堆內(nèi)存),會增加 GC 負(fù)擔(dān)。
  • 讀操作可直接在 Page Cache 內(nèi)進(jìn)行。如果消費(fèi)和生產(chǎn)速度相當(dāng),甚至不需要通過物理磁盤(直接通過 Page Cache)交換數(shù)據(jù)。
  • 如果進(jìn)程重啟,JVM 內(nèi)的 Cache 會失效,但 Page Cache 仍然可用。

Broker 收到數(shù)據(jù)后,寫磁盤時(shí)只是將數(shù)據(jù)寫入 Page Cache,并不保證數(shù)據(jù)一定完全寫入磁盤。從這一點(diǎn)看,可能會造成機(jī)器宕機(jī)時(shí),Page Cache 內(nèi)的數(shù)據(jù)未寫入磁盤從而造成數(shù)據(jù)丟失。

但是這種丟失只發(fā)生在機(jī)器斷電等造成操作系統(tǒng)不工作的場景,而這種場景完全可以由 Kafka 層面的 Replication 機(jī)制去解決。

如果為了保證這種情況下數(shù)據(jù)不丟失而強(qiáng)制將 Page Cache 中的數(shù)據(jù) Flush 到磁盤,反而會降低性能。

也正因如此,Kafka 雖然提供了 flush.messages 和 flush.ms 兩個(gè)參數(shù)將 Page Cache 中的數(shù)據(jù)強(qiáng)制 Flush 到磁盤,但是 Kafka 并不建議使用。

零拷貝技術(shù)

Kafka 中存在大量的網(wǎng)絡(luò)數(shù)據(jù)持久化到磁盤(Producer 到 Broker)和磁盤文件通過網(wǎng)絡(luò)發(fā)送(Broker 到 Consumer)的過程。這一過程的性能直接影響 Kafka 的整體吞吐量。

操作系統(tǒng)的核心是內(nèi)核,獨(dú)立于普通的應(yīng)用程序,可以訪問受保護(hù)的內(nèi)存空間,也有訪問底層硬件設(shè)備的權(quán)限。

為了避免用戶進(jìn)程直接操作內(nèi)核,保證內(nèi)核安全,操作系統(tǒng)將虛擬內(nèi)存劃分為兩部分,一部分是內(nèi)核空間(Kernel-space),一部分是用戶空間(User-space)。

傳統(tǒng)的 Linux 系統(tǒng)中,標(biāo)準(zhǔn)的 I/O 接口(例如 read,write)都是基于數(shù)據(jù)拷貝操作的,即 I/O 操作會導(dǎo)致數(shù)據(jù)在內(nèi)核地址空間的緩沖區(qū)和用戶地址空間的緩沖區(qū)之間進(jìn)行拷貝,所以標(biāo)準(zhǔn) I/O 也被稱作緩存 I/O。

這樣做的好處是,如果所請求的數(shù)據(jù)已經(jīng)存放在內(nèi)核的高速緩沖存儲器中,那么就可以減少實(shí)際的 I/O 操作,但壞處就是數(shù)據(jù)拷貝的過程,會導(dǎo)致 CPU 開銷。

我們把 Kafka 的生產(chǎn)和消費(fèi)簡化成如下兩個(gè)過程來看[2]:

  • 網(wǎng)絡(luò)數(shù)據(jù)持久化到磁盤 (Producer 到 Broker)
  • 磁盤文件通過網(wǎng)絡(luò)發(fā)送(Broker 到 Consumer)

①網(wǎng)絡(luò)數(shù)據(jù)持久化到磁盤 (Producer 到 Broker)

傳統(tǒng)模式下,數(shù)據(jù)從網(wǎng)絡(luò)傳輸?shù)轿募枰?4 次數(shù)據(jù)拷貝、4 次上下文切換和兩次系統(tǒng)調(diào)用。

  1. data = socket.read()// 讀取網(wǎng)絡(luò)數(shù)據(jù)  
  2. File file = new File()  
  3. file.write(data)// 持久化到磁盤  
  4. file.flush() 

這一過程實(shí)際上發(fā)生了四次數(shù)據(jù)拷貝:

  • 首先通過 DMA copy 將網(wǎng)絡(luò)數(shù)據(jù)拷貝到內(nèi)核態(tài) Socket Buffer。
  • 然后應(yīng)用程序?qū)?nèi)核態(tài) Buffer 數(shù)據(jù)讀入用戶態(tài)(CPU copy)。
  • 接著用戶程序?qū)⒂脩魬B(tài) Buffer 再拷貝到內(nèi)核態(tài)(CPU copy)。
  • 最后通過 DMA copy 將數(shù)據(jù)拷貝到磁盤文件。

DMA(Direct Memory Access):直接存儲器訪問。DMA 是一種無需 CPU 的參與,讓外設(shè)和系統(tǒng)內(nèi)存之間進(jìn)行雙向數(shù)據(jù)傳輸?shù)挠布C(jī)制。

使用 DMA 可以使系統(tǒng) CPU 從實(shí)際的 I/O 數(shù)據(jù)傳輸過程中擺脫出來,從而大大提高系統(tǒng)的吞吐率。

同時(shí),還伴隨著四次上下文切換,如下圖所示:

 

數(shù)據(jù)落盤通常都是非實(shí)時(shí)的,Kafka 生產(chǎn)者數(shù)據(jù)持久化也是如此。Kafka 的數(shù)據(jù)并不是實(shí)時(shí)的寫入硬盤,它充分利用了現(xiàn)代操作系統(tǒng)分頁存儲來利用內(nèi)存提高 I/O 效率,就是上一節(jié)提到的 Page Cache。

對于 Kafka 來說,Producer 生產(chǎn)的數(shù)據(jù)存到 Broker,這個(gè)過程讀取到 socket buffer 的網(wǎng)絡(luò)數(shù)據(jù),其實(shí)可以直接在內(nèi)核空間完成落盤。

并沒有必要將 socket buffer 的網(wǎng)絡(luò)數(shù)據(jù),讀取到應(yīng)用進(jìn)程緩沖區(qū);在這里應(yīng)用進(jìn)程緩沖區(qū)其實(shí)就是 Broker,Broker 收到生產(chǎn)者的數(shù)據(jù),就是為了持久化。

在此特殊場景下:接收來自 socket buffer 的網(wǎng)絡(luò)數(shù)據(jù),應(yīng)用進(jìn)程不需要中間處理、直接進(jìn)行持久化時(shí)??梢允褂?mmap 內(nèi)存文件映射。

Memory Mapped Files:簡稱 mmap,也有叫 MMFile 的,使用 mmap 的目的是將內(nèi)核中讀緩沖區(qū)(read buffer)的地址與用戶空間的緩沖區(qū)(user buffer)進(jìn)行映射。

從而實(shí)現(xiàn)內(nèi)核緩沖區(qū)與應(yīng)用程序內(nèi)存的共享,省去了將數(shù)據(jù)從內(nèi)核讀緩沖區(qū)(read buffer)拷貝到用戶緩沖區(qū)(user buffer)的過程。

它的工作原理是直接利用操作系統(tǒng)的 Page 來實(shí)現(xiàn)文件到物理內(nèi)存的直接映射。完成映射之后你對物理內(nèi)存的操作會被同步到硬盤上。

使用這種方式可以獲取很大的 I/O 提升,省去了用戶空間到內(nèi)核空間復(fù)制的開銷。

mmap 也有一個(gè)很明顯的缺陷:不可靠,寫到 mmap 中的數(shù)據(jù)并沒有被真正的寫到硬盤,操作系統(tǒng)會在程序主動調(diào)用 Flush 的時(shí)候才把數(shù)據(jù)真正的寫到硬盤。

Kafka 提供了一個(gè)參數(shù) producer.type 來控制是不是主動 Flush;如果 Kafka 寫入到 mmap 之后就立即 Flush,然后再返回 Producer 叫同步(sync)。

寫入 mmap 之后立即返回 Producer 不調(diào)用 Flush 就叫異步(async),默認(rèn)是 sync。

 

零拷貝(Zero-copy)技術(shù)指在計(jì)算機(jī)執(zhí)行操作時(shí),CPU 不需要先將數(shù)據(jù)從一個(gè)內(nèi)存區(qū)域復(fù)制到另一個(gè)內(nèi)存區(qū)域,從而可以減少上下文切換以及 CPU 的拷貝時(shí)間。

它的作用是在數(shù)據(jù)報(bào)從網(wǎng)絡(luò)設(shè)備到用戶程序空間傳遞的過程中,減少數(shù)據(jù)拷貝次數(shù),減少系統(tǒng)調(diào)用,實(shí)現(xiàn) CPU 的零參與,徹底消除 CPU 在這方面的負(fù)載。

目前零拷貝技術(shù)主要有三種類型[3]:

  • 直接 I/O:數(shù)據(jù)直接跨過內(nèi)核,在用戶地址空間與 I/O 設(shè)備之間傳遞,內(nèi)核只是進(jìn)行必要的虛擬存儲配置等輔助工作。
  • 避免內(nèi)核和用戶空間之間的數(shù)據(jù)拷貝:當(dāng)應(yīng)用程序不需要對數(shù)據(jù)進(jìn)行訪問時(shí),則可以避免將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間,mmap,sendfile,splice && tee,sockmap。
  • copy on write:寫時(shí)拷貝技術(shù),數(shù)據(jù)不需要提前拷貝,而是當(dāng)需要修改的時(shí)候再進(jìn)行部分拷貝。

②磁盤文件通過網(wǎng)絡(luò)發(fā)送(Broker 到 Consumer)

傳統(tǒng)方式實(shí)現(xiàn):先讀取磁盤、再用 Socket 發(fā)送,實(shí)際也是進(jìn)過四次 Copy。

  1. buffer = File.read  
  2. Socket.send(buffer) 

這一過程可以類比上邊的生產(chǎn)消息:

  • 首先通過系統(tǒng)調(diào)用將文件數(shù)據(jù)讀入到內(nèi)核態(tài) Buffer(DMA 拷貝)。
  • 然后應(yīng)用程序?qū)?nèi)存態(tài) Buffer 數(shù)據(jù)讀入到用戶態(tài) Buffer(CPU 拷貝)。
  • 接著用戶程序通過 Socket 發(fā)送數(shù)據(jù)時(shí)將用戶態(tài) Buffer 數(shù)據(jù)拷貝到內(nèi)核態(tài) Buffer(CPU 拷貝)。
  • 最后通過 DMA 拷貝將數(shù)據(jù)拷貝到 NIC Buffer。

Linux 2.4+ 內(nèi)核通過 Sendfile 系統(tǒng)調(diào)用,提供了零拷貝。數(shù)據(jù)通過 DMA 拷貝到內(nèi)核態(tài) Buffer 后,直接通過 DMA 拷貝到 NIC Buffer,無需 CPU 拷貝。這也是零拷貝這一說法的來源。

除了減少數(shù)據(jù)拷貝外,因?yàn)檎麄€(gè)讀文件,網(wǎng)絡(luò)發(fā)送由一個(gè) Sendfile 調(diào)用完成,整個(gè)過程只有兩次上下文切換,因此大大提高了性能。

 

Kafka 在這里采用的方案是通過 NIO 的 transferTo/transferFrom 調(diào)用操作系統(tǒng)的 Sendfile 實(shí)現(xiàn)零拷貝。

總共發(fā)生 2 次內(nèi)核數(shù)據(jù)拷貝、2 次上下文切換和一次系統(tǒng)調(diào)用,消除了 CPU 數(shù)據(jù)拷貝。

批處理

在很多情況下,系統(tǒng)的瓶頸不是 CPU 或磁盤,而是網(wǎng)絡(luò)IO。

因此,除了操作系統(tǒng)提供的低級批處理之外,Kafka 的客戶端和 Broker 還會在通過網(wǎng)絡(luò)發(fā)送數(shù)據(jù)之前,在一個(gè)批處理中累積多條記錄 (包括讀和寫)。

記錄的批處理分?jǐn)偭司W(wǎng)絡(luò)往返的開銷,使用了更大的數(shù)據(jù)包從而提高了帶寬利用率。

數(shù)據(jù)壓縮

Producer 可將數(shù)據(jù)壓縮后發(fā)送給 Broker,從而減少網(wǎng)絡(luò)傳輸代價(jià),目前支持的壓縮算法有:Snappy、Gzip、LZ4。數(shù)據(jù)壓縮一般都是和批處理配套使用來作為優(yōu)化手段的。

下次面試官問我 Kafka 為什么快,我就這么說:

  • Partition 并行處理。
  • 順序?qū)懘疟P,充分利用磁盤特性。
  • 利用了現(xiàn)代操作系統(tǒng)分頁存儲 Page Cache 來利用內(nèi)存提高 I/O 效率。
  • 采用了零拷貝技術(shù):Producer 生產(chǎn)的數(shù)據(jù)持久化到 Broker,采用 mmap 文件映射,實(shí)現(xiàn)順序的快速寫入;Customer 從 Broker 讀取數(shù)據(jù),采用 Sendfile,將磁盤文件讀到 OS 內(nèi)核緩沖區(qū)后,轉(zhuǎn)到 NIO buffer進(jìn)行網(wǎng)絡(luò)發(fā)送,減少 CPU 消耗。

參考資料:

  • 美團(tuán)——磁盤 I/O 那些事

https://tech.meituan.com/2017/05/19/about-desk-io.html

  • Kafka零拷貝

https://zhuanlan.zhihu.com/p/78335525

  • Linux - Zero-copy(零拷貝)

https://cllc.fun/2020/03/18/linux-zero-copy/

作者:不假

編輯:陶家龍

出處:轉(zhuǎn)載自公眾號 JavaKeeper(ID:JavaKeeper)

 

責(zé)任編輯:武曉燕 來源: JavaKeeper
相關(guān)推薦

2024-02-26 21:15:20

Kafka緩存參數(shù)

2020-03-30 15:05:46

Kafka消息數(shù)據(jù)

2018-10-28 15:40:23

Python編程語言

2023-11-02 10:22:29

gRPC后端通信

2021-10-13 09:00:19

排序數(shù)據(jù)集開發(fā)

2024-11-26 08:52:34

SQL優(yōu)化Kafka

2020-02-27 21:03:30

調(diào)度器架構(gòu)效率

2022-06-13 21:52:02

CDN網(wǎng)絡(luò)節(jié)點(diǎn)

2013-03-04 10:10:36

WebKit瀏覽器

2018-08-16 08:03:21

Python語言解釋器

2019-08-30 14:58:47

JavaScript程序員編程語言

2020-02-27 15:44:41

Nginx服務(wù)器反向代理

2022-06-02 08:03:19

PyCharmPython代碼

2020-10-13 17:54:18

開發(fā)Kafka數(shù)據(jù)

2024-09-14 09:41:17

2024-07-30 09:01:12

2017-01-23 13:08:46

大數(shù)據(jù)客戶畫像技術(shù)

2020-11-10 22:53:54

oracle數(shù)據(jù)庫

2020-09-27 08:12:09

Nginx反向代理負(fù)載均衡

2024-01-10 17:04:13

通信模塊通信技術(shù)通信模組
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號