今天聊聊kafka版本號的問題,這個問題實在是太重要了,我覺得甚至是日后能否用好kafka的關鍵。上一節我們介紹了kafka的幾種發行版,其實不論是哪種kafka,本質上都內嵌了最核心的Apache kafka,也就是社區版kafka,那今天我們就說說Apache kafka版本號的問題。在開始之前,先強調一下,后面出現的所有"版本"這個詞都表示kafka具體的版本號,而非上一節中介紹kafka種類,這一點要切記。
那么現在可能會有這樣的疑問,我為什么要關心版本號的問題呢?直接使用最新版本不就好了嗎?當然了,這的確是一種有效的版本選擇的策略,但我想強調的是這種策略並非在任何場景下都適用。如果你不了解各個版本之間的差異和功能變化,你怎么能准確地評判某kafka版本是不是滿足你的業務需求呢?因此在深入學習kafka之前,花些時間搞明白版本演進,實際上是非常划算的一件事。
kafka版本命名
當前Apache kafka已經迭代到2.2版本,社區正在為2.3.0發版日期進行投票,相信2.3.0也會馬上發布。但是稍微有些令人吃驚的是,很多人對於kafka的版本命名理解存在歧義。比如我們在官網下載kafka時,會看到這樣的版本。
於是有些人或許就會納悶,難道kafka的版本號不是2.11或者2.12嗎?其實不然,前面的版本號是編譯kafka源代碼的Scala編譯器版本。kafka服務器端的代碼完全由Scala語言編寫,Scala同時支持面向對象編程和函數式編程,用Scala寫的源代碼編譯之后也是普通".class"文件,因此我們說Scala是JVM系的語言,它的很多設計思想都是為人稱道的。
事實上目前java新推出的很多功能都是在不斷地向Scala靠近,比如lambda表達式、函數式接口、val變量等等。一個有意思的事情是,kafka新版客戶端代碼完全由java語言編寫,於是有人展開了java vs Scala的討論,並從語言特性的角度嘗試分析kafka社區為什么放棄Scala轉而使用java重寫客戶端代碼。其實事情遠沒有那么復雜,僅僅是因為社區來了一批java程序員而已,而以前老的Scala程序員隱退罷了。可能有點跑題了,但是不管怎么樣,我依然建議你有空學一學python語言。
回到剛才的版本號討論,現在你應該知道了對於kafka-2.11-2.1.1的提法,真正的kafka版本號是2.1.1,那么這個2.1.1又表示什么呢?前面的2表示大版本號,即major version;中間的1表示小版本號或者次版本號,即minor version;最后的1表示修訂版本號,也就是patch號。kafka社區在發布1.0.0版本后特意寫過一篇文章,宣布kafka版本命名規則正式從4位演進到3位,比如0.11.0.0版本就是4位版本號。
kafka版本演進
於kafka目前總共演進了7個大版本,分別是0.7、0.8、0.9、0.10、0.11、1.0和2.0,其中的小版本和patch版本很多。哪些版本引入了哪些重大的功能改進?建議你最好做到如數家珍,因為這樣不僅令你在和別人交談時顯得很酷,而且如果你要向架構師轉型或者已然是架構師,那么這些都是能夠幫助你進行技術選型、架構評估的重要依據。
我們先從0.7版本說起,實際上也沒有什么可說的,這是最早開源時的上古版本了。這個版本只提供了最基礎的消息隊列功能,甚至連副本機制都沒有,我實在想不出來有什么理由你要使用這個版本,因此如果有人要向你推薦這個版本,果斷走開好了。
kafka從0.7時代演進到0.8之后正式引入了副本機制,至此kafka成為了一個真正意義上完備的分布式、高可靠消息隊列解決方案。有了副本備份機制,kafka就能夠比較好地做到消息無丟失。那時候生產和消費消息使用的還是老版本客戶端的api,所謂老版本是指當你使用它們的api開發生產者和消費者應用時,你需要指定zookeeper的地址而非broker的地址。
如果你現在尚不能理解這兩者的區別也沒有關系,我會在后續繼續介紹它們。老版本的客戶端有很多的問題,特別是生產者api,它默認使用同步方式發送消息,可以想到其吞吐量一定不會太高。雖然它也支持異步的方式,但實際場景中消息有可能丟失,因此0.8.2.0版本社區引入了新版本producer api,即需要指定broker地址的producer。
據我所知,國內依然有少部分用戶在使用0.8.1.1、0.8.2版本。我的建議是盡量使用比較新的版本,如果你不能升級大版本,我也建議你至少要升級到0.8.2.2這個版本,因為該版本中老版本消費者的api是比較穩定的。另外即使升級到了0.8.2.2,也不要使用新版本producer api,此時它的bug還非常的多。
時間來到了2015年11月,社區正式發布了0.9.0.0版本,在我看來這是一個重量級的大版本更迭,0.9大版本增加了基礎的安全認證/權限功能,同時使用java重寫了新版本消費者的api,另外還引入了kafka connect組件用於實現高性能的數據抽取。如果這么眼花繚亂的功能你一時無暇顧及,那么我希望你記住這個版本另一個好處,那就是新版本的producer api在這個版本中算比較穩定了。如果你使用0.9作為線上環境不妨切換到新版本producer,這是此版本一個不太為人所知的優勢。但和0.8.2引入新api問題類似,不要使用新版本的consumer api,因為bug超級多,絕對用到你崩潰。即使你反饋問題到社區,社區也不管的,它會無腦的推薦你升級到新版本再試試,因此千萬別用0.9新版本的consumer api。對於國內一些使用比較老的CDH的創業公司,鑒於其內嵌的就是0.9版本,所以要格外注意這些問題。
0.10.0.0是里程碑式的大版本,因為該版本引入了kafka streams。從這個版本起,kafka正式升級成為分布式流處理平台,雖然此時的kafka streams還不能上線部署使用。0.10大版本包含兩個包含兩個小版本:0.10.1和0.10.2,它們的主要功能變更都是在kafka streams組件上。如果把kafka作為消息引擎,實際上該版本並沒有太多的功能提升。不過在我的印象中,自從0.10.2.2版本起,新版本consumer api算是比較穩定了。如果你依然在使用0.10大版本,那么我強烈建議你至少升級到0.10.2.2然后再使用新版本的consumer api。還有個事情不得不提,0.10.2.2修復了一個可能導致producer性能降低的bug。基於性能的緣故你也應該升級到0.10.2.2。
在2017年6月,社區發布了0.11.0.0版本,引入了兩個重量級的功能變更:一個是提供冪等性producer api;另一個是對kafka消息格式做了重構。
前一個好像更加吸引眼球一些,畢竟producer實現冪等性以及支持事務都是kafka實現流處理結果正確性的基石。沒有它們,kafka streams在做流處理時無法像批處理那樣保證結果的正確性。當然同樣是由於剛推出,此時的事務api有一些bug,不算十分穩定。另外事務api主要是為kafka streams應用服務的,實際使用場景中用戶利用事務api自行編寫程序的成功案例並不多見
第二個改進是消息格式的變化。雖然它對用戶是透明的,但是它帶來的深遠影響將一直持續。因為格式變更引起消息格式轉換而導致的性能問題在生產環境中屢見不鮮,所以一定要謹慎對待0.11這個版本的變化。不得不說的是,在這個版本中,各個大功能組件都變得相當穩定了,國內該版本的用戶也很多,應該算是目前最主流的版本之一了。也正是因為這個緣故,社區為0.11大版本特意退出了3個patch版本,足見它的受歡迎程度。我的建議是,如果你對1.0版本是否適用於線上環境依然感到困惑,那么至少將你的環境升級到0.11.0.3,因為這個版本的消息引擎功能已經非常完善了。
最后合並說一下1.0和2.0版本吧,因為在我看來這兩個大版本主要還是kafka streams的各種改進,在消息引擎方面並未引入太多的重大功能特性。kafka streams的確在這兩個版本有着非常大的變化,也必須承認kafka streams目前依然還在積極地發展着。如果你是kafka streams的用戶,只要選擇2.0.0版本吧。
去年8月國外出了一本書叫做kafka streams in action,中文譯名:kafka streams實戰,它是基於kafka streams1.0版本撰寫的,但是用2.0版本去運行書中的很多例子,居然很多都已經無法編譯了,足見兩個版本的差別之大。不過如果你在意的依然是消息引擎,那么這兩個大版本都是可以用於生產環境的。
最后還有個建議,不論你使用的是哪個版本,都請盡量保持服務器端版本和客戶端版本一致,否則你將損失很多kafka為你提供的性能優化收益。