增強在線可進化性
就我個人而言,這幾年來學(xué)到的最重要的一課蝎亚,就是要永遠保證一個流式數(shù)據(jù)平臺的在線可進化性(online-evolvable)。
之前我曾經(jīng)讀到 Amazon CTO Werner Vogels 寫過的一篇博客,里面就提到這一點,并且有一個精彩的比喻:搭建一個能夠在不斷產(chǎn)品升級過程中保證永遠在線的數(shù)據(jù)架構(gòu)哥谷,就像是駕駛著一架簡單的單螺旋槳飛機起飛,然后在飛行過程中麻献,不斷換新零件和添加新引擎们妥,直到最后升級成一架超大的空客飛機,這一切都必須在飛行中同步完成勉吻,并且坐在里面的乘客不能有任何感覺监婶,其難度可想而知。
而關(guān)于一個流數(shù)據(jù)平臺齿桃,對于在線可進化性這一點的需求尤甚:這里我也打一個比方惑惶,盡管沒有 Vogels 的那樣精彩——數(shù)據(jù)流就像是一個連接城市各個地區(qū)的高速公路,高速公路所連接的地方源譬,比如一家超市集惋、一家影院,或者一個居民小區(qū)踩娘,就如同一個企業(yè)里面大大小小的各種應(yīng)用產(chǎn)品或者數(shù)據(jù)倉庫刮刑,超市可以暫時歇業(yè),影院可以暫時關(guān)門翻修养渴,居民小區(qū)甚至也可以遷出人口夷平重建雷绢,就像是產(chǎn)品或者數(shù)據(jù)倉庫都可以短暫下線升級維護。然而高速公路卻很難徹底打斷重搭理卑,因為隨時都有人要上路翘紊。更多時候,它只能一邊繼續(xù)完成輸送車輛的任務(wù)藐唠,一邊增設(shè)車道或者加蓋匝道帆疟。就像是一個流數(shù)據(jù)平臺本身鹉究,因為不會有一個零流量的時刻,所以所有的維護和升級都需要保證同步在線完成踪宠,而且期間最好沒有任何用戶可感知到的性能弱化或者服務(wù)差別自赔。而在云環(huán)境下,后者顯得更為重要柳琢。對于 Kafka 而言绍妨,如果一個用戶沒有一個安全穩(wěn)定的升級路線的話,那么她就只能停留在最初的那個版本柬脸,再不會升級他去。
因此我們從很早以前開始注意保證在線升級的方便性,在這一次的 2.0.0 版本中倒堕,更多相關(guān)的屬性被加了進來灾测,比如 KIP-268、KIP-279涩馆、KIP-283 等等行施。
KIP-268:簡化 Kafka Streams 升級過程
Kafka Streams 利用 Consumer Rebalance 協(xié)議里面的元數(shù)據(jù)字符串編碼諸如任務(wù)分配、全局查詢魂那、版本升級相關(guān)的信息。然而稠项,當(dāng)編碼版本本身改變的時候涯雅,就需要進行離線升級。比如之前從 0.10.0 版本像更高級的版本升級的時候展运,用戶就需要將所有的 Streams 程序下線活逆,換上新的 Kafka 版本號,然后在全部重啟拗胜。
KIP-268 利用 version prob 可以使得舊版本的任務(wù)分配者告知其他高版本的成員暫時使用舊版本的 Rebalance 元數(shù)據(jù)編碼蔗候,這樣就可以讓用戶依然能夠通過 rolling bounce 在線升級 Kafka Streams 的版本。而當(dāng)所有參與的成員全部升級完畢之后埂软,最后一次 rebalance 會自動切換回新版本的元數(shù)據(jù)編碼锈遥。
KIP-279:修補多次 Kafka 分區(qū)主本遷移時的日志分歧問題
在升級 Kafka 版本或者做定期系統(tǒng)維護的時候,用戶往往需要進行連續(xù)的多次 Kafka 分區(qū)遷移勘畔。在這次發(fā)布中我們修補了一個在此過程中可能會出現(xiàn)的一個會導(dǎo)致日志分歧發(fā)生的邊緣情況所灸。具體方案就是將此前版本中已經(jīng)加入的主本 epoch 信息擴散到 OffsetForLeaderEpochResponse。如此所有主副本就可以清晰知道自己到底處于當(dāng)前分區(qū)備份的哪一個階段炫七,從而杜絕因為消息不對等而可能導(dǎo)致的日志分歧爬立。
KIP-283:降低信息格式向下轉(zhuǎn)換時的內(nèi)存消耗
在一個多客戶端組群的環(huán)境下,客戶端與服務(wù)器端的版本不匹配是常見現(xiàn)象万哪。早在 0.10.0 版本中侠驯,Kafka 已經(jīng)加入了允許不同版本客戶端與服務(wù)器交互的功能抡秆,即高版本的 Kafka 客戶端依然可以與低版本的服務(wù)器進行數(shù)據(jù)傳導(dǎo),反之亦然吟策。然而當(dāng)?shù)桶姹镜南M者客戶端和高版本的服務(wù)器進行交互時儒士,服務(wù)器有時需要將數(shù)據(jù)向下轉(zhuǎn)換(format down-conversion)成為低版本客戶端可以認知的格式后才能發(fā)回給消費者。向下轉(zhuǎn)換有兩個缺點:
丟失了 Kafka 數(shù)據(jù)零拷貝(zero-copy)的性能優(yōu)勢踊挠;
向下轉(zhuǎn)換需要額外的大量內(nèi)存乍桂,在極端情況下甚至?xí)?dǎo)致內(nèi)存溢出。
前者無法避免效床,但是后者依然可以改進:在即將發(fā)布的 2.0 版本中睹酌,我們使用了一種新的基于分塊(chunking)的向下轉(zhuǎn)換算法,使得需要同時占據(jù)的內(nèi)存需求大幅縮減剩檀。這使得高低版本的客戶端與服務(wù)器之間的交互變得更加有效憋沿。
更多的可監(jiān)控指標
對于企業(yè)級數(shù)據(jù)平臺來說,另一個很重要的要求就是提供各種實時的監(jiān)控能力沪猴。在 LinkedIn 的時候辐啄,同事間流傳著據(jù)傳是我們公司傳奇人物 David Henke 的一句話:what gets measured gets fixed,充分體現(xiàn)了監(jiān)測的重要性运嗜。
長期以來壶辜,Apache Kafka 社區(qū)不斷地完善各種區(qū)塊的各種指標,這每一個新添加的指標背后都有一個我們曾經(jīng)踩過的坑担租,一段在線調(diào)試和修 bug 的痛苦經(jīng)歷砸民。
舉一個具體的例子:Kafka 長期以來被詬病添加分區(qū)太慢,因此在 1.1.0 版本里面來自六個不同企業(yè)的貢獻者共同完成了重新設(shè)計 Kafka 控制器(Kafka Controller)這個規(guī)模巨大的 JIRA奋救。在這個長達九個月的項目里岭参,被談?wù)摵芏嗟囊稽c就是如何增添控制器操作的各種指標。在未來更多的新功能和新屬性尝艘,比如繼續(xù)增強 Kafka 的伸縮性演侯,包括多數(shù)據(jù)中心支持等等,如何能夠讓用戶繼續(xù)便捷地實時監(jiān)測這些新增功能的性能背亥,及時發(fā)現(xiàn)可疑問題秒际,并且?guī)椭s短需要的在線調(diào)試時間,都將是討論的重要一環(huán)隘梨,因為這也是任何一個企業(yè)級流數(shù)據(jù)平臺必須要注意到的程癌。
在 2.0.0 版本中,我們進一步加強了 Kafka 的可監(jiān)控性轴猎,包括添加了很多系統(tǒng)靜態(tài)屬性以及動態(tài)健康指標嵌莉,比如 KIP-223、KIP-237捻脖、KIP-272 等等锐峭。
KIP-223:加入消費者客戶端的領(lǐng)先指標
在此前中鼠, Kafka 消費者客戶端已經(jīng)加入了對每一個消費分區(qū)的延遲指標(lag metrics),定義為當(dāng)前消費者在分區(qū)上的位置與分區(qū)末端(log-end-offset)的距離沿癞。當(dāng)此指標變大時援雇,代表消費者逐漸跟不上發(fā)布的速度,需要擴容椎扬。我們發(fā)現(xiàn)惫搏,當(dāng)分區(qū) renteion 時間很短而導(dǎo)致消費者跌出可消費范圍時(out-of-range),此指標不能完全針對潛在的危險為用戶報警蚕涤。
因此在即將發(fā)布的 2.0 版本中筐赔,我們加入了另一個“領(lǐng)先”指標(lead metrics),定義為分區(qū)首端(log-start-offset)與消費者在分區(qū)上的位置距離揖铜,當(dāng)此指標趨近于零時茴丰,代表消費者有跌出可消費范圍因而丟失數(shù)據(jù)的危險。值得稱贊的是天吓,這個新特性是由國內(nèi)的社區(qū)貢獻者完成的贿肩。
KIP-237:加入更多 Kafka 控制器的健康指標
在完成了針對增強 Kafka 控制器性能的全面重設(shè)計之后,我們認為現(xiàn)在 Kafka 已經(jīng)可以支持千臺機器龄寞,百萬分區(qū)級別的集群汰规。在此之前,這樣規(guī)模集群的一個阻礙就是 Kafka 控制器本身處理各種 admin 請求物邑,諸如主本遷移控轿、話題擴容、增加副本等等時的時間消耗拂封。在完成了這個重設(shè)計之后,我們也相應(yīng)地加入了更多和新設(shè)計相關(guān)的健康指標鹦蠕,包括控制器內(nèi)部請求隊列的長度冒签,請求處理速率等等。
更全面的數(shù)據(jù)安全支持
最后钟病,也是最近一段時間被討論最多的萧恕,就是數(shù)據(jù)安全的重要性:在云計算大行其道的今天,多租戶方案已成為潮流肠阱。而許多數(shù)據(jù)保護條例的實施票唆,比如 GDPR,更是讓“保證數(shù)據(jù)不泄漏”成為一個標準流數(shù)據(jù)平臺的基本要求屹徘。這項要求包括從寫入走趋,到處理,到導(dǎo)出的一些系列措施噪伊,包括認證簿煌、訪問控制及授權(quán)氮唯、端到端加密等等。
舉個例子姨伟,如果一個 Kafka 集群可以被一個企業(yè)里面的多個部門所共享惩琉,如何控制哪些部門可以讀取或?qū)懭肽男┲黝}、哪些部門可以創(chuàng)建或刪除哪些主題夺荒、誰可以看見別人創(chuàng)建的主題瞒渠、以及與 Kafka 相關(guān)的其他服務(wù)和客戶端,比如應(yīng)該如何保護Zookeeper技扼、誰可以直接讀寫伍玖、哪些 Kafka Streams 或者 Kafka Connect 應(yīng)用程序可以發(fā)起哪些管理請求等,都需要提供足夠的控制手段淮摔。
在 2.0.0 版本里面私沮,我們對此提供了一系列的改進,比如更細粒度的更細粒度的前綴通配符訪問控制(KIP-290和橙、KIP-227)仔燕,支持 SASL/OAUTHBEARER(KIP-255),將委托令牌擴展到管理客戶端(KIP-249)魔招,等等晰搀。
KIP-290、KIP-227:細粒度前綴通配符訪問控制
在 2.0 以前办斑,很多 Kafka 自身的訪問控制(access control list)機制還是粗粒度的外恕。比如對“創(chuàng)建話題”這一訪問方式的控制,只有“全集群”這一種范圍乡翅。也就是說鳞疲,對于任何一個用戶來說,我們只能或者給予其在一個集群內(nèi)創(chuàng)建任何話題的權(quán)限——比如說蠕蚜,這個 Kafka 集群的運維或者可靠性工程團隊(Devops or SRE)尚洽,或者不給予任何話題的創(chuàng)建權(quán)限。但是在一個多租戶環(huán)境下靶累,我們很可能會出現(xiàn)需要更細粒度的控制機制腺毫。比如一個 Kafka Streams 客戶端,除了讀取給予的源話題之外挣柬,還需要實時創(chuàng)建一下內(nèi)部用于 data shuffling 和 change logging 的話題潮酒,但是給予其一個“全集群”的話題創(chuàng)建權(quán)限又太危險。
因而在 2.0 版本中邪蛔,我們進一步細粒度化了很多權(quán)限急黎,比如 KIP-290 就加入了前綴通配符(prefix wildcard)的范圍,而 KIP-227 就將這種范圍加入到了單個或多個話題創(chuàng)建的權(quán)限中。在這個機制下叁熔,用戶可以被賦予單獨一個話題基于其話題名的創(chuàng)建權(quán)限(literal topic)委乌,也可以被賦予多個話題基于其話題名前綴匹配的創(chuàng)建權(quán)限,比如可以創(chuàng)建所有名字開頭為“team1-”的話題荣回,等等遭贸。