首頁 > 科技

Kafka 效能調優實戰:同等資源配置效能提升 20 幾倍的祕訣

2021-06-30 03:03:27

作者 | 丁威 責編 | 歐陽姝黎

拋出問題


筆者最近在折騰資料異構體系,在實現MySQL增量資料同步到MQ(Kafka、RocketMQ),本文的故事就從這裡開始。

眾所周知,為了提高寫入端的併發效能,通常會採用多執行緒併發機制,提高寫入端的效能,接下來基於MySQL增量同步到Kafka為例,闡述一下第一版的架構方案。

真實的資料同步架構設計複雜性遠比上面複雜,上圖旨在闡述Kafka的使用特點:

為了提高效能,通常會引入多執行緒,故組內同事直接採用多執行緒,通過創建多個執行緒,每一個執行緒單獨創建一個KafkaProducer物件,然後binlog解析器後,按照分區鍵進行負載均衡。

但發現,效能非常低下,為什麼呢?該如何處理呢?


多執行緒在Kafka這裡為啥不好使了


當發現效能比較慢,然後又按照 Kafka效能優化指南進行調優,對linger.ms,batch.size等參數進行調優,但發現毫無用處,這是為啥呢?


Kafka的高吞吐率設計的核心要點之一是批處理,即kafka在訊息傳送端引入了一個雙端佇列,應用程式通過KafkaProducer的send方法時,會將訊息先放入到雙端佇列,然後kafka使用一個非同步執行緒從佇列中成批發送訊息。

為了確保sender執行緒能一次傳送較多資料,kafka在客戶端引入了一個參數linger.ms,預設為200ms,即小心進入到快取區後不會立即被send執行緒傳送,而是等待一定時間,這樣能提高send執行緒的傳送效率,提高吞吐率。

再回到上述到場景,將視角切換到單個執行緒,在單個執行緒內,應用方呼叫KafkaProducer後,訊息會在快取區中等待200ms,但由於是資料同步場景,訊息傳送使用的是同步傳送,這樣就會導致不管send執行緒等多久,永遠只會有一條訊息被髮送,每條訊息傳送還要無緣無故的增加200ms的延遲,tps怎能上去?

第一個優化點:還是基於多執行緒傳送,當多執行緒共同持有一個KafkaProducer物件,這樣在同一時間會有更多資料到達KafkaProducer的快取區,Sender執行緒就可以實現一次傳送多條訊息,實現批量傳送到效果,從而提升Kafka的吞吐率,實現高TPS,其效果如下圖所示:


關鍵點:對於單個執行緒,由於要保證訊息都順序性,使用的是同步傳送模式。


「大殺器」非同步傳送也能保證順序


眾所周知,在資料異構的架構體系中,通常需要將分庫分表的mysql資料庫中的資料同步到es,從而實現跨庫join等複雜查詢功能。

資料同步為了確保資料的最終一致性,通常必須保證順序。但其維度可以為表級別、資料行級別,通常只需要保證同一行資料的不同事件(新增、更新、刪除)等事件必須順序執行,所以在上述的架構中採用的是同步傳送。

有沒有可能使用非同步傳送,但同時滿足順序語義呢?

答案當然是可以的,其設計思路為:將訊息分批處理,該批次內部訊息併發執行,各個批次順序執行。示意圖如下:

將訊息分成批次,批次1必須要先與批次2執行,但在執行一個批次的時候,如果這個批次中的訊息的key(例如id)不相同,那這批訊息內部其實是無需保證其順序的,就可以將這批訊息非同步傳送,使每條訊息併發傳送,大大提高其併發度,TPS將得到進一步提升。

溫馨提示:如果一個批次中的訊息存在相同的key,需要將這些訊息進行分割,確保一個併發批次沒有重複key。

同步轉非同步,如果目標端是RocketMQ,其優化效果會更加顯著。

好了,本文就介紹到這裡了,一鍵三連(關注、點贊、留言)是對我最大的鼓勵。

掌握一到兩門java主流中介軟體,是敲開BAT等大廠必備的技能,送給大家一個Java中介軟體學習路線,助力大家實現職場的蛻變。

Java進階之梯,成長路線與學習資料,助力突破中介軟體領域

最後分享筆者一個硬核的RocketMQ電子書,您將獲得千億級訊息流轉的運維經驗。


IT145.com E-mail:sddin#qq.com