閆燕飛:Kafka的高效能揭祕及優化

騰訊雲加社群發表於2018-05-03

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~

本文首發在雲+社群,未經許可,不得轉載。

大家下午好,我是來自騰訊雲基礎架構部ckafka團隊的高階工程師閆燕飛。今天在這裡首先為大家先分享一下開源Kafka在高效能上面的一些關鍵點,然後我會分享一下我們騰訊雲ckafka對社群Kafka所做的一些優化點,最後我會介紹一下我對Kafka社群未來的展望。

Kafka高效能揭祕

在這裡首先我會介紹一下整個Kafka的架構,讓大家對Kafka有一個較為巨集觀的瞭解,緊接著我會在更加詳細的介紹一下Kafka的儲存方式以及具體訊息儲存格式。當然為了方便大家對kafka的高效能有個直觀的理解,最後我也會給出其效能資料。

總體架構

我們可以看到Kafka整個叢集裡面僅僅包含了Broker,zookeeper兩個元件。

Broker是整個Kafka叢集的核心引擎,負責訊息的儲存轉發,並對外提供服務。我們可以看到,Kafka叢集可以非常簡單的通過增刪Broker,實現整個叢集的擴縮容。Kafka對外提供服務的基本單位是Topic,那麼實現Topic級別的平行擴充套件能力,也就實現了應用級的平行擴充套件能力。為了實現應用級的平行擴充套件能力,Kafka採用了對Topic進行分割槽的做法,通過對Topic進行分割槽讓不同的分割槽落在不同的Broker上,從而利用到更多Broker的能力,最終實現了應用級的水平擴充套件。

Zookeeper則在整個叢集中則主要負責儲存一些配置資訊、Broker資訊、Topic資訊等等後設資料,並且承擔了一部分協調選主的功能,可以將其理解為Kafka叢集的配置管理中心。講到這裡,大家會覺得在Kafka叢集中,可以簡單的通過Broker動態的增刪實現叢集擴縮容,但在整個叢集中卻僅僅存在一個Zookeeper,那麼Zookeeper會不會成為整個叢集的瓶頸點,從而制約了整個叢集的平行擴充套件能力?的確,在Kafka一些較老版本,Kafka的生產者及消費者都需要與Zookeeper進行通訊互動,進行後設資料拉取、消費分組協調、以及消費分組offset提交與儲存等等。這樣造成的一個問題,就是所有的客戶端都要直接與ZooKeeper進行通訊互動,對其造成了非常大的壓力,影響了系統的穩定性,最終影響整Kafka叢集的平行擴充套件能力。但從0.9(含)版本之後,Kafka團隊對整個Kafka進行了優化中,通過增加了一些協議,並且增加了協調模組。當前Kafka已經做到了客戶端的生產及消費不需要與Zookeeper進行任何通訊互動,故Zookeeper當前僅僅充當了配置管理中心,壓力非常的小,不會成為叢集的瓶頸點進而制約叢集的水平擴充套件能力。

大家也可以看到生產者及消費者是直接與Broker進行互動實現生產消費功能,Kafka在設計上並未採用傳統系統中通過增加一層代理實現系統的平行擴充套件能力。Kafka在設計中通過內部路由協議,實現了生產者與消費者可以直接與Broker進行路由協商,從而實現了客戶端直接與Broker進行生產消費,而不需要藉助第三方代理。無代理的方式不僅會減少整個資料鏈路的長度,降低延遲,也可以提高整個系統的穩定性,而且也會節省大量的成本。

總結下Kafka的總體架構體現瞭如下幾個主要的優勢。其一,Kafka叢集可以通過增刪Broker實叢集級的水平擴充套件。其二,通過對Topic進行分割槽,實現了應用級別的無限平行擴充套件能。其三,通過優良通訊協議,實現了生產系統直接與後端的Broker進行通訊,節省了代理,不僅減少了資料鏈路長度降低了延遲,而且極大的降低了成本。

至此,我想大家對Kafka已經有一個較為巨集觀瞭解。我們知道系統總體架構,決定了整個系統的能力上限。但系統中關鍵元件的效能,則是決定了相同能力下叢集中伺服器數量。伺服器數量的增加,不僅僅會增加成本,而且會帶來更多的運維壓力及影響系統的穩定性。所以下面我將會介紹下Kafka核心引擎Broker的系統架構。

Broker架構

我們可以看Broker是一個典型的Reactor模型,其主要包含一個網路執行緒池,負責處理網路請求進行網路的收發以及打包解包,然後把請求通過請求佇列推送給核心處理模組,由其負責真正的業務邏輯處理(Kafka會把所有訊息落地儲存,故主要是些檔案I/0操作)。我們可以看到kafka採用多執行緒方式,可以充分利用現代系統的多核優勢。其次,其採用佇列方式實現了網路處理模組及核心處理模組的非同步解耦,實現了網路處理和檔案I/O並行處理,極大的提高了整個系統的效率。

講到這裡,大家對Kafka架構已經有一個巨集觀的理解。上面我們也提到,Kafka會把所有的訊息都落地儲存。那麼為什麼Kafka並未像傳統的訊息佇列那樣非常懼怕磁碟,勁量快取而不觸碰磁碟?Kafka為什麼選擇了將所有訊息都落地儲存?下面我將通過講解其儲存組織方式及儲存格式,為大家進行一一揭祕。

儲存的組織方式

這個就是當前Kafka的儲存組織方式,我們可以看到Topic,其實只是邏輯概念,並不對應任何物理實體,為了實現Topic的水平擴充套件,Kafka會對其進行分割槽。Partition則以目錄形式進行展現,同時Partition中具體的資料還未進行分片儲存。這樣在生產時,就能快速的找到最新的分配直接追加到檔案末尾,可以看到Kafka在生產中充分利用了磁碟的順序寫,極大的提高了生產的吞吐能力。同時進行分片儲存,還有一個好處就是我們可以非常方便的通過刪除老的分片實現過期訊息的刪除。同時為了方便消費,Kafka在分片的命名上也採用了一定的技巧,分片的命名採用了其包含的第一條訊息的offset進行格式化這樣,在消費資料時,可以非常方便的通過二分查詢定位到訊息所在的檔案分片。同時為了實現分片內快速定位,Kafka也會對每個資料分片建立兩個稀疏索引檔案,通過索引檔案,採用二分查詢可以非常快速的定位了指定訊息在資料分片中的位置,進而進行消費。通過講解我們可以看到Kafka的整個生產消費其實都是順序讀寫,充分利用了磁碟順序讀寫能力。其次,Kafka的消費,採用了二級二分查詢,其查詢效能僅僅依賴一個分片的索引大小,不會受整個系統資料量的影響。

Kafka處理的最基本單位是訊息,那麼Kafka的訊息具體是什麼格式?落地儲存的訊息又具體是什麼格式?不用說這些都將極大的影響系統的效能,所以下面我也將會詳細的介紹下Kafka的訊息格式。

訊息格式

為方便大家理解,這裡我就以C程式碼的形式進行訊息格式展示。Kafka訊息其實是採用的簡單的二進位制編碼,網路位元組序儲存,故可以非常高效的進行編解碼操作。同時,我們可以看到整個Kafka訊息頭部非常的緊湊,僅僅只有30個位元組左右,而且還包含了crc校驗碼用於對訊息進行相關的校驗。同時在Kafka中最為精妙的是,該訊息的格式在生產系統端、網路傳輸中、Broker端,包括最終的檔案儲存中,都保持了訊息格式的一致性。所以使得訊息在整個系統的傳輸中,不需要有任何轉碼,效率奇高。當然為了提高整個系統的吞吐,Kafka這邊實現了訊息的批量生產消費。批量訊息在Kafka中表現形式為,以二進位制形式在記憶體中一個個排列起來。同時為了提高系統網路及磁碟的利用率,Kafka還是實現了訊息壓縮,右邊這個流程圖則詳細的說明了訊息壓縮的流程。可以看到,首先我們把整個批量訊息以一個整體進行壓縮,生成一個新的二進位制串。然後,把該值打包到一個新的訊息的value欄位中。可以看到Kafka非常巧妙的通過訊息巢狀方式實現了訊息的批量壓縮,提高了整體壓縮效率。同時該方式也保證了訊息的格式的一致性。保持訊息一致性就有以下好處:其一,我們在整個訊息流轉中僅僅需要生產者進行一次壓縮後,將該壓縮訊息傳送到Broker端後,Broker端僅需要一次解壓操作,用以進行訊息校驗,並進行訊息offset設定,後就能直接把訊息直接儲存在檔案中,不需要有Broker進行一次非常消耗效能的壓縮操作。所以說即使採用的訊息壓縮,對於Broker端的消耗也非常低。同時由於保持了壓縮訊息格式的一致性,當有消費請求時,Broker不用進行任何解壓及壓縮操作,可以直接將訊息以壓縮的方式傳送給消費者,由消費者負責解壓,這樣的話Broker在整個消費中也就不需要任何的解壓及壓縮的操作,可以極大的提高Broker端的效能。可以看到Kafka通過這種方式,非常簡單的實現了端到端的資料壓縮,把計算資源消耗分攤到生產系統和消費系統中。

Kafka高效能

由於時間原因,講到這裡Kafka高效能的關鍵點也基本都涵蓋了,當然Kafka團隊為了其高效能還是有很多巧妙的設計,這裡由於時間原因就不在一一贅述,當然這頁PPT中則詳細的列舉了其高效能的關鍵點,大家下面有興趣可以自己對著這些關鍵點自己仔細琢磨。

講了這麼多Kafka高效能的關鍵點,但到底其有著什麼樣的效能?為使大家對整個Kafka的效能有一個較為直觀的認識,下面我也將給大家提出相關的效能測試資料。當然任何效能測試如果沒有前置的測試條件則都是在空說,所以在給出資料前,先給一下測試的配置條件.一、測試場景是一個Broker單topic,多個partition。二、機器硬體配置是32核 64G記憶體,萬兆網路卡,同時掛載12塊2T SATA盤,並且對SATA盤做了軟RAID10。三、Broker版本上我們選擇是0.10.2.0。Broker配置方面,我們選擇的是每10萬條訊息或兩秒進行一次刷盤。四、我們使用社群Kafka的原生壓測工具,並同時開啟140客戶進行壓測,用於模擬一定的併發。當然我後面所有壓測資料都是基於這個統一的配置,後面介紹時我就不再相信敘述測試條件了。

通過下面的表格,我們可以看到Kafka在小包的情況下輕鬆達到百萬級別的qps,而且即使在1K的大包情況下也達到了幾十萬級別的qps,可以說整個Kafka效能還是非常強悍的。但同時我們也發現Kafka Broker在測試中,的CPU使用率,尤其是磁碟I/O使用率並不高,說明社群Kafka還是有一定的優化空間。所以下面我就介紹一下我們CKafka對社群Kafka的一些優化點。

Kafka效能優化

在這個章節裡面,首先我會帶領大家進一步的深入瞭解一下整個 Broker端的架構,通過進一步瞭解他的架構,找出它可能的瓶頸點,然後在針對瓶頸點進行優化優化。緊接著我將會挑出幾個具體的優化點進行詳細的介紹。

當前架構剖析

在這裡為了方便大家理解,我們用一次真實的請求,經過的路徑,來說明Broker各個模組是怎麼互動的。首先,當一個生產啟動,他需要去和Broker進行連線,Broker端會有一個Accept執行緒模組進行連線監聽用於建立新的連線,在連線建立後Accept會將網路連線輪詢轉發給給網路接收傳送處理執行緒池中的一個執行緒處理,至此連線接入已經完成。下面將進入資料請求,這時候生產者傳送的生產請求資料,將直接由網路收發處理執行緒進行處理,每當網路執行緒收到一個完整的包,並進完成解包操作後,就會將請求推送到請求佇列,由後端核心處理執行緒進行真正的邏輯處理。後端核心I/O處理執行緒會競爭的從請求佇列中拉取到生產請求任務後,首先,其會對相應的訊息進行解析,建立相應的訊息物件,然後訊息物件進行一些合法性校驗,並設定相應的offset,當完成這些後會將訊息寫入檔案。當然寫入完成後會檢測未刷盤的訊息個數是否達到刷盤要求,如果達到刷盤要求,該執行緒還會主動進行刷盤操作,最後把這個處理結果通過每個網路處理執行緒的應答佇列,返回給對應的網路處理執行緒,最後由網路執行緒進行打包並把結果返回給生產端,至此一個生產流程就以完成。

在這個流程中,我們可以發現:一、在整個Kafka的架構中,僅僅只有一個請求佇列,而且該佇列還未進行任何無鎖化優化,這樣會導致網路處理執行緒池以及核心I/O處理執行緒產生激烈的鎖競爭,從而有可能影響整個系統的併發性,進而影響到系統的效能。所以這個是我們應該想到一個優化點。其二,我們剛才講到Kafka選擇直接在核心處執行緒中直接進行磁碟刷盤,這樣會導致堵塞整個核心流程,進而影響整個系統的效能。這也是我們今天發現的需要優化的第二個一個優化點。其三,就是我們發現在生產訊息中會生成大量的訊息物件,用於進行訊息的合法性的校驗。產生大量的訊息物件,會對jvm的GC產生較大的影響,可能會成為系統效能的瓶頸點。當然我們ckafka對社群kafka還做了很多其它方面的優化,這裡有由於時間關係,主要集中這三點進行介紹。

鎖優化

我們第一版的鎖優化,通過架構圖可以看到,其實是非常簡單的。我們直接把broker端僅有的一個請求佇列,替換成一個無鎖請求佇列,當然我們也對所有的應答佇列進行了無鎖佇列的替換優化。經過這一輪優化,我們具體到達成一個什麼效果?這個就是當前無鎖佇列的優化結果。通過對比我們可以發現,經過無鎖佇列優化後,相對於社群版本Kafka,整個效能基本上保持了一致。但按照我們之前的分析,按理說應該會有較大的效能提升才對,但為啥沒有達到預期效果?

為一探究竟,我們又對 Broker進行了更為詳細的統計分析。通過統計分析後,我們統計了請求次數,通過下面的統計圖表,我們發現不管是社群Kafka,還是我們優化的版本,即使在百萬qps的訊息情況下,生產請求個數都非常的少,都是在10w級別以下。講到這裡我們明白了,正是由於開源Kafka這邊採用了批量傳送的方式,合併了大量的生產請求,使的整個Broker端的請求次數急劇的減少,請求量的減少就使得網路處理執行緒及核心處理執行緒間的鎖爭用減少,在當前請求量級的情況下鎖爭用不太會成為真個系統的瓶頸點,所以我們的無鎖佇列沒有達到理想的效果也是正常的。講到這裡,可以說我們第一個優化其實是不太成功的,但是優化道路總是漫長曲折的,一次不成功也正常也不會嚇到我們,我們ckafka會持續不但的在優化道路上前行。

檔案刷盤優化

下面我們進行第二個優化點的介紹,非同步刷盤優化。在非同步刷盤優化方面,我們ckafka專門增加了一組刷盤執行緒,專門用於磁碟刷盤,這樣當核心執行緒發現需要有刷盤需要時,直接生成一個刷盤任務,並將刷盤任務通過無鎖佇列推送給刷盤執行緒,由其進行刷盤即可。這樣的話我們就可以實現在刷盤時不堵塞核心處理執行緒處理,會極大的提高一個系統的效能。當然經過這一輪的話後我們到底有沒有效果?具體我們看一下下面的效能對比資料。

經過非同步刷盤優化後,我們可以看到,優化後的吞吐在小包情況下,較社群版本有4到5倍的效能提升,同時即使是在大包情況下也有一倍左右的效能提升(隨著包的增大及partition的增多優化後的提升會成下降趨勢)。同時我們可以發現在我們非同步刷盤優化的測試過程中,整個系統的I/O使用率已經非常搞了,基本都在90%以上了,可以說現在整個系統的瓶頸點應該就是磁碟I/O了,同時超過90%的I/O使用率,說明我們已經榨乾了系統磁碟的效能,也表示我們後續的吞吐量優化空間已經不大了。那麼這樣是不是說我們整個Kafka就沒有任何的優化空間了?其實對於系統的優化則不僅僅是包含了吞吐量的提升,我們還可以從相同吞吐量下資源使用率方面進行相關的優化,所以ckafka對社群Kafka的優化並未止步於當前,所以我們進一步進行了下一個GC方面的優化。我們期望通過該優化不僅能有吞吐方面的提升,更重要的是期望在類似的場景下,可以更好的減少資源的使用率,進一步縮減成本。

GC優化

在GC優化方面,主要是社群Kafka在對生產訊息進行校驗時會針對每條訊息生成一個訊息物件,導致產生大量的訊息物件,ckafka通過優化,採用直接在ByteBuffer二進位制資料上進行訊息校驗,這樣在整個訊息校驗中就不會生成任何訊息物件,減少大量的訊息物件的生成,則會降低對jvm GC的壓力,進而提高系統的效能。通過對比優化前後的效能資料,我們可以看到它起到一定效果的。我們可以看到優化後整個GC的耗時佔比的已經低於2.5%,可以說GC已經不會成為系統的瓶頸點了。我們看一下社群開源Kakfa這邊的GC耗時,在較多的partition較小的訊息下,直接可以達到10%的消耗。通過我們的GC優化後,可以看到整個GC耗時方面的話,有1.5%到7%的效能的提高。同樣我們可以看到,在吞吐量差不多的情況下,我們整個系CPU消耗較交社群版的CPU有關5%到10%的降低,所以可以肯定的說GC優化有效的降低了系統CPU資源的消耗,起到一定的效果。最後我們發現整個GC優化前後系統中I/O基本上已經達到頂點,已經成為系統的瓶頸點,所以GC優化就和前面預測的一致並未有吞吐量大幅的提升,主要集中在降低系統資源的消耗,對於前端客戶端來說則是一定幅度上降低系統的延遲。

至此由於時間原因,Kafka的效能優化的介紹已經完畢。但為了更加方便大家直觀的理解,這一頁PPT則貼出了最終的優化對比效果。我們來看看最終優化後的效果,可以看出我們最終完整版優化,在小包情況下有4到5倍的效能提升,即使在1K的大包情況下,也有一倍左右的效能提升(當然隨著partition的增加及訊息大小的增加,優化效果呈一定的下降趨勢)。同時我們可以發現整個系統的I/O已經是成為系統的瓶頸點。也為我們後面系統硬體選擇方面提供一個參考,可能我們後面會通過掛載更多的磁碟,進一步提高系統的吞吐壓榨系統的效能,進一步平衡CPU及磁碟的配比消耗,當然通過選擇更合適的硬體做到CPU、磁碟、網路之間合適的配比實現資源利用的更大化。

下面我講一下我們在CKafka運營中所發現一些問題,以及我們針對這些問題的優化點,同時我們期望社群Kafka能夠採納我們ckafka在運營中發現並優化的一些關鍵點建議,讓kafka能夠更好的適應生產條件。

其一,當前社群Kafka還無法採用pipe方式進行消費,這樣就導致出現以下幾個問題:一、消費者的效能非常依賴於與Broker端的網路延遲,當消費者與Broker存在跨城區的時候,由於網路延遲的增大,會導致整個消費效能非常低下,這樣就最終限制了Kafka的使用場景,使其不能很好的作用於跨城區資料同步,限制了其使用的場景。二,Kafka在副本複製的時複用了消費邏輯,同樣走的也是消費者邏輯,這樣也同樣導致其無法使用pipe方式,最後導致了副本同步效能低下而且非常依賴於延遲,最終導致了整個Kafka叢集不太可能進行一些跨區域的部署,限制了Kafka部署的靈活性,而且同時在壓力較大的情況下,容易出現副本拉取的速度跟不上生產的速度導致ISR抖動影響系統效能。針對這個問題,其實在第二點,我們這邊已經做了優化,使得副本拉取已經可以進行pipe方式,後面即使需要做一些跨城區部署,其整個副本同步效能是能夠達到要求的。但是在這裡第一個問題我們這裡無法解決,因為我們這邊生為了相容性社群版本Kafka,是讓客戶直接採用的是開源的SDK,導致了我們這裡還沒法沒辦法優化。在這裡我希望社群Kafka,可以採納相關的建議,實現消費者pipe方式,使得整個消費效能不在依賴於網路延遲,使得使用者的使用上沒有地域空間的一些限制。

其二,就是當前社群Kafka對消費為了效能方面的考慮,他在設計中是不支援低版本的消費者直接去消費高版本生產增產的訊息,而當前Kafka發展到現在已經有三個訊息版本,這樣就導致了業務的在使用Kafka時,包括生產者及消費者的升級降級都是非常不友好的。當然這裡我們在進行雲化的時候,我們已經實現了對訊息格式轉換,已經實現了不同版本訊息混合儲存在同一個檔案中,已經實現了任意版本的生產以及任意版本的消費。這裡我們希望社群Kafka能否試試放開相關的支援,因為畢竟在生產系統中,業務使用時相容性是最重要的考量標準之一。而且即使是我們現在的實現存在訊息高低版本的轉碼,其實CPU現在還是有富餘的,也不是系統的瓶頸點,所以說我希望社群這邊能夠採納

講到這裡,其實我的分享也基本上完了。然後這是我的個人微信,大家如果有什麼問題可以加我的微信。當然,現在我們的CKafka團隊也在大量的招人,大家有意向的話也可以聯絡我們。

Q/A

Q:這裡需要請教你一個問題,就是我看剛才看到一部刷盤優化的時候,發現CPU也是隨著效能的提升上升了很多倍,這裡是不是主要是因為優化過程中你又做了一次拷貝?

A:沒有,其實社群Kafka在記憶體拷貝方面還是有一些優化的。唉,稍等一下,社群Kafka在整個訊息流轉中,比如生產訊息時,他從網路層開始會生成一個ByteBuffer用於儲存訊息包,而後這個ByteBuffer會在整個系統中不斷的扭轉,它是不會有新的拷貝的,除非有一些訊息需要有不同方式的儲存時,需要有轉碼的要求,他才會生成一個新的訊息進行一次記憶體拷貝否則不會有多次記憶體拷貝。而我們這裡在做非同步刷盤優化時,其實是不會有任何多於的記憶體拷貝的,我們的CPU使用有數倍的提高,主要還是在與吞吐的提高,可以看到我們系統在小包情況下有4 ~ 5倍的效能提升,這樣提升,會導致更多的網路操作,更多的打包解包,更多的系統I/O當然最終就會導致更多的cpu,當然就會需要更多的CPU消耗。這麼多消耗的疊加當然照成CPU使用率數倍的提高也是很正常的。

Q:我有個問題想問一下你剛才之前PPT也有說就是說在系統量很大的情況下,副本的拉取速率無法跟上生產的速率,對這個的話我們測試或者是說線上其實也會碰到副本拉取跟不上生產速度,而且會影響導致其它節點也跟不上,照成一種雪崩效應。然後我想問一下你這邊的解決辦法,你剛才說有解決辦法,我想問一下你們這邊是採用哪種解決辦法?

A: 社群Kafka副本拉取不上最主要的原因,是因為採用了消費方式,但消費方式又不支援pipe方式消費。其實Kafka的副本拉取是同步方式,傳送一個副本拉取請求後等到應答後再次傳送一次同步拉取請求,無法使用pipe流水線方式,這樣的同步方式Broker的網路延遲會成為整個副本同步的關鍵點,並且在壓力大的情況下整個Kakfa的broker端出來延遲會達到秒及,這樣會導致整個副本拉取效能不足,不足的真正原因就是拉取請求次數不夠,如果我們採用pipe方式增大拉取請求次數,自然也就增大了副本同步的效能。

Q:你們還有沒有就是說更具體一點的解決方式?

主要是我們這邊的話,副本的同步採用了一個新的協議,使的副本拉取請求可以採用pipe方式增大請求次數進而提高副本同步速度。其實,社群Kafka副本拉取跟不上的真正原因是應為請求都是同步的,延遲正大導致請求量減少,請求量的減少最終導致副本效能下降導致無法跟上,所以我們所要做的就是加大副本同步請求個數,就可以從根本上解決問題,我們這裡採用的就是pipe方式,用於增大請求次數解決副本無法跟上的問題。這其實是最核心的,也是最簡單一個解決方案了。

Q: 請問一下就是說我剛才看到有一個非同步落盤的優化,問一下就是說你這裡公佈的資料都是沒有時延資訊的,我不知道就是說這個有話會不會導致業務時延增加。

A: 因為測試中客戶端比較多,統計上加上時延就會導致更加的雜亂,故這裡統計資料並未有展示出來,其實我們測試統計中採用非同步刷盤後這個時延效果其實更好。因為採用非同步刷盤後在整個請求中不會堵塞任何核心流程,只用把刷盤任務推送到佇列,就可以直接返回給前端客戶端了。但是如果你不使用非同步刷盤直接在核心流程中進行刷盤的話,會堵塞核心流程的,而且每次刷盤耗時其實是非常大的,經常會到達400毫秒左右的延遲,所以延遲會更大。採用非同步刷盤後,經過我們測試,即使在七八百MB的最高吞吐下,我們這邊整個延遲是保持得非常好,整個測試的平均延遲是在15毫秒到30毫秒之間。然而在社群Kafka環境下,其延遲其實是在200毫秒左右。

Q: 我就問,如果非同步落盤的時候,它到期還沒刷到盤,這個不需要等到刷盤完成後才返回給客戶嗎?會不會導致未刷盤時訊息丟失?

A: 這個其實和Kafka的應用場景有關了,當前社群Kafka也不是每條訊息都刷盤,其實刷盤也是通過配置一個訊息間隔數或間隔時間進行的,這樣其實社群Kafka這邊在系統掉電的情況下,是還真的沒法保證這個訊息不丟失。Kafka應用場景一般也不是在用在完全不需要訊息丟失的場景,而是主要用於一些日誌採集等實時性要求比較高,吞吐要求比較高的場景,Kafka這裡為了吞吐這邊其實還是選擇了犧牲一定的訊息的可靠性的。當然針對我們這個非同步刷盤,當前的第一步優化比較簡單,我們直接把任務推送到刷盤人群佇列,就返回給客戶端成功,的確會導致一部分訊息在系統掉電下導致丟失。當前為了切合Kafka的應用場景,採用了優先吞吐的方式,當然,我們後面還會根據需要看看,是否需要實現真正刷盤後在返回給使用者成功。其實實現這個也比較簡單,我們選擇掛起生產請求,直到刷盤執行緒真正刷盤後,在返回給客戶成功即可。但這樣的話你剛才也說了可能會導致的延遲增大,因為你必須要等它真正的刷盤完成,這個可能需要你自己根據應用形態採用而不同的方式,實現一個高吞吐及高可靠的一個取捨了。

Q:你好,問個問題就是兩個問題,第一個問題是關於數落盤的,因為剛才也提到說Kafka裡面的資料不一定是可靠的,然後想問一下騰訊在這邊對資料可靠性是有做了什麼優化和方案這樣。

A:一方面,從硬體方面,其實我們這裡所有的儲存磁碟,都採用了RAID10的方式,這樣即使有少量的磁碟的損壞,對我們來說的話是不會有資料丟失的風險的。另一方面,ckafka和社群kafka一樣都可以通過多副本的方式,加上一定合理的配置,可以保證在機器損壞時,資料不丟失。再次,在實現上我們ckafka也做到了定時定量進行主動刷盤可以降低機器由於意外掉電導致的資料丟失。所以相對應社群kafka ckafka從硬體及軟體上都有更高的資料可靠性保證。

Q:然後第二個問題,剛才說到說跨城區的副本同步就有個問題,現在騰訊這邊的部署是跨城區部署的嗎?

A:當前ckafka的部署採用的是同城區,同zone部署的,但是我們ckafka是可以實現跨城區部署的,當前沒提供這種部署方式,最主要的原因是當前使用社群Kafka sdk的消費者效能強依賴於與Broker之間網路延遲。如果我們進行跨地域部署的話,那麼客戶端的消費效能是得不到保障的,因為不通地域之間的網路延遲往往都在幾十毫秒,甚至上百毫秒,這樣使得整個消費效能下降非常嚴重無法滿足業務的需求。當然如果社群Kafka SDK能夠採用我們上面的建議實現消費者pipe方式消費,那麼進行跨地域部署將不會有任何問題。

Q:OK帶來另外一個問題,就是我覺的如果真的出現意外情況,比如像天津大爆炸案,導致整個騰訊的天津機房都炸掉了,你們這裡的話有沒有考慮過這種遷移計劃?

A:其實我們ckafka是在各個地域都部署的有相關的叢集,使用者可以通過在不同地域購買不同的例項,一方面實現就近接入,另一方面實現異地容災,保證程式的可用性。當然使用者也可以通過,我們提供的Kafka的一些同步工具,進行資料在不同地域間同步,用於實現地域級別的容災。

Q:對於業務來說,如果他使用同步工具那麼會不會對業務照成更大的成本?業務是否需要改造相關的程式用以實現跨城區訪問?

A:對業務使用方來說,可以直接使用一些開源的工具及方法,使用者是不需要有任何的更改就能實現跨地域訪問,社群Kafka的生態及工具還是比較完善的大家可以多去社群上逛逛總能找到適合自己的工具。

問答
Kafka的基於關鍵/值對的訊息傳遞的目的是什麼?
相關閱讀
饒軍:Apache Kafka的過去,現在,和未來
楊原:騰訊雲Kafka自動化運營實踐
陳新宇:CKafka在人臉識別PASS中的應用


更多相關資料,請戳:

kafka-高效能揭祕及優化.pdf


此文已由作者授權騰訊雲+社群釋出,原文連結:https://cloud.tencent.com/developer/article/1114834?fromSource=waitui


相關文章