閆燕飛:Kafka的高性能揭秘及優化

閆燕飛:Kafka的高性能揭秘及優化

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

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

大家下午好,我是來自騰訊雲基礎架構部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

此文已由作者授權騰訊雲+社區發布,原文鏈接:cloud.tencent.com/devel

weixin.qq.com/r/6TlxaU- (二維碼自動識別)


推薦閱讀:

分散式系統的那些事兒(四) - MQ時代的通信
Flink源碼解析之State的實現
MaxCompute理解數據、運算和用戶的大腦:基於代價的優化器
分散式輕量級批量任務框架設計思想
分散式架構的套路No.74

TAG:分散式系統 | 分散式計算 | Kafka |