爲什麼我不推薦Kafka Streams和KSQL?

在近日召開的 Kafka 峯會上,發佈了一系列值得關注的重要公告。有些改動值得嘗試,有些需要慎重考慮,才能轉化爲真正適合自己的實踐方法。本文作者認爲:不推薦使用 KSQL 和 Kafka Streams,因爲缺少檢查點機制以及存在隨機排序等問題。 本文,我將首先簡要陳述自己的觀點,隨後深入探討我得出這一觀點的原因。

我的觀點是:不建議用戶使用 Kafka Streams,因爲其缺少檢查點機制,也不具備隨機排序等功能,而 KSQL 以 Kafka Streams 爲基礎,因此其同樣繼承了後者所固有的不少問題。

Kafka 並不是數據庫,而是一套非常出色的消息傳遞系統。確實,直到現在也有很多人認定 Kafka 就是一套數據庫,由於篇幅所限,我在本文中沒法具體討論這些問題。我也承認,除非真正學習並瞭解過 Kafka,否則大多數開發者都很難理解這兩者之間的差異。

我發現,這樣的對話與爭論並沒能真正把觀點與論據區分開來。在這裏我希望做好區分,跟大家好好聊聊這個話題。

KSQL 和 Kafka Streams 存在的問題

檢查點機制

我認爲這個問題是客觀存在的,無可辯駁,Kafka Sterams 確實存在檢查點機制問題。檢查點可以說是操作分佈式系統的基礎。那麼,到底什麼是檢查點呢?

Kafka 是一套分佈式日誌記錄系統。在消息處理方面,Kafka 同時支持有狀態與無狀態兩類。在無狀態處理方面,用戶只會接收一條消息,然後進行實際處理,非常簡單。但一旦涉及有狀態處理,情況就立刻變得不同。現在,開發者面對的第一個難題就是存儲狀態,只有這樣才能在遇到錯誤時配合對應狀態完成系統恢復。

對於 Kafka Streams,恢復工作看似非常簡單,因爲擁有重構狀態所需要的全部消息。理論上,甚至能夠通過一些方法將保存在 Kafka 中的消息控制在每鍵約一條的水平。

但這就沒問題了嗎?當然不是。因爲每鍵一條消息,狀態量仍然相當誇張。如果大家擁有上千億個鍵,那就需要在狀態主題中保存超過 1 千億條消息,畢竟所有狀態變更都被放置在了對應的狀態變更主題內。隨着鍵數量的進一步增加,狀態的體積也會隨之膨脹。

這種運營思路總結起來就是,一旦某個節點無法正常運行,則必須從主題中重播所有消息並將其插入數據庫內。只有執行完成整個流程,處理才能恢復至原有狀態並繼續進行。

在極端情況或者發生人爲錯誤的前提下,一切運行 Kafka Streams 作業的設備都有可能崩潰或者宕機,這意味着所有節點都必須重播所有狀態變更消息,而後才能繼續正常處理新的消息。

這種大規模重播可能會帶來長達數小時的停機時間。不少 Kafka Streams 的潛在用戶表示,他們估算出的停機時間至少達到 4 個小時。好的,就算 4 個小時,完成恢復流程之後,接下來還有這一時段內新增的大量消息。追上這部分進度,系統纔算是真正回到運行正軌之上。

有鑑於此,數據庫與處理框架往往採用檢查點機制(在 Flink 中,這一機制被稱爲快照)。所謂檢查點,是將當前整體態定入至持久存儲(S3/HDFS)中。因此,一旦發生大規模故障,恢復程序將直接讀取前一個檢查點,重播該檢查點之後的所有消息(通常在 1000 秒以內),以便快速恢復後續處理能力。總體而言,檢查點支持下的恢復流程一般僅耗時幾秒鐘到幾分鐘不等。

可以看到,在檢查點的幫助下,系統的停機時間將由 Kafka Streams 的數小時顯著縮短至幾秒和幾分鐘水平。對於實時系統,停機時間必須儘可能短,我們也必須盡最大努力確保分佈式系統能夠儘快從故障中恢復過來。

隨機排序

隨機排序是分佈式處理流程的重要組成部分,其本質是將數據與同一個鍵整合起來的實現方法。如果需要對數據進行分析,則很可能會接觸到隨機排序。

事實上,Kafka Streams 的隨機排序與 Flink 或者 Spark Streaming 中的隨機排序存在巨大差異。下面來看看 JavaDoc 中關於其工作原理的描述:

如果某個鍵變更運算符在實際使用之前發生了變化(例如 selectKey(KeyValueMapper)、map(KeyValueMapper), flatMap(KeyValueMapper) 或者 transform(TransformerSupplier, String…)),且此後沒有發生數據重新分發(例如通過 through(String)),那麼在 Kafka 當中創建一個內部重新分區主題。該主題將被命名爲“${applicationId}-XXX-repartition”的形式,其中,“applicationId”由用戶在 StreamsConfig 中通過 APPLICATION_ID_CONFIG 參數進行指定,“XXX”爲內部生成的名稱,而“-repartition”則爲固定後綴。開發者可以通過 KafkaStreams.toString() 檢索所有已生成的內部主題名稱。

這意味着只要變更鍵(一般用於分析),Kafka Streams 就會新建一個主題來實現隨機排序。這種隨機排序實現方法,證實了我在與開發者溝通時做出的幾個基本假設:

我曾與多位前 Kafka Streams 開發者進行過交流,他們並不清楚這種新的主題機制。他們直接在集羣上執行實時分析,但這會快速增加代理上的負載與數據總量,並最終導致系統崩潰。但從使用者的角度來看,他們只是在正常執行數據處理。

如果開發者對性能並不關注,那麼這種方法似乎也能接受。但是,其他一些處理框架(例如 Apache Flink)顯然更加理想,它們提供更完善的內置隨機排序功能,而且也能與 Kafka 配合使用。這些系統,無疑能夠帶來更順暢的使用體驗。

結論 由於缺少兩大關鍵功能,Kafka Streams 實用性會大打折扣。我們不可能接受在實時生產系統上經歷長達數小時的停機,無法接受隨機排序功能導致集羣崩潰。而且除非在每一項 KSQL 查詢之前都進行解釋,否則我們也弄不明白可能出現哪些隨機排序操作。

怎麼做?

不要過分糾結沒有實際價值的架構問題

在本次召開的 Kafka 峯會上,其中不少演講糾結於那些根本沒有實際使用的架構問題。例如,他們談到數據庫是負責執行數據處理的環境,確實某些小型數據架構以及不少數據倉庫方案都在使用數據庫進行數據處理。但我從沒見過有哪些大數據架構會採用這樣的處理方式,畢竟數據庫的可擴展性一直是個大問題。長久以來,我們一直使用具有可擴展能力的處理引擎解決這方面需求,這也成爲大數據領域的一種客觀標準。

他們還將 KSQL 硬性拔高,表示其能夠完成一部分目前由大數據生態系統項目處理的任務。在他們看來,目前生態系統項目過多已經成爲新的問題。大數據生態系統中包含太多技術方案,每一項技術負責解決或處理一種特定用例。組織當然可以剔除掉部分技術方案,但這會大大減慢處理速度,甚至影響處理用例的能力。話雖沒錯,但就算是配合這次公佈的幾項新功能,KSQL 也仍不足以真正滿足組織的處理需求。

這不禁讓我好奇,爲什麼要積極鼓吹這麼多新的使用場景?在我看來,此次峯會中的不少發佈內容並不科學。很明顯,Kafka 確實不適合處理一些數據庫的任務。長期存儲的最佳選項,仍然是 S3 或者 HDFS。文件系統與 Kafka 無論在性能還是存儲成本上,都有着巨大差別。

我鼓勵各位架構師認真研究這種差別,目前只有兩種方法能夠通過時間戳或者提交 ID 的方式訪問 Kafka 中的歷史數據。一般來講,用例需要使用 where 子句進行隨機訪問,這一點我們看到 KSQL 開始進行嘗試處理。然而,針對隨機訪問讀取的數據庫優化絕非易事,不少大型科技企業都需要圍繞這個問題建立專門的大規模工程技術團隊。

Kafka 不是數據庫

現實情況是,數據庫要麼位於代理進程中,要麼處於具備穩定持久存儲層的應用程序內。在我看來,使用 KSQL 通過 where 子句獲取當前狀態的架構並沒有任何實際意義。其它成熟的架構已經能夠輕鬆獲取數據的當前狀態,例如數據庫或者帶有檢查點的其他處理程序。

在主題演講最後,Confluent(一家圍繞 Kafka 建立的創業公司)提到新功能的出現並不是要替代所有數據庫。我真心希望他們能再斟酌斟酌自己的發言。畢竟在列舉的衆多數據庫用例中,Confluent 都已經開始利用 KSQL 替換數據庫。這裏我要再次強調:創建數據庫絕非易事,而創建分佈式數據庫更是難上加難。

這篇文章的目的並不是打擊 Kafka。如果充分理解 Kafka 的特性與用法,它絕對是一套非常強大的發佈和訂閱系統。因此,最重要的是瞭解如何正確使用 Kafka,而不能單純被市場宣傳牽着鼻子走。請記住,供應商的利益訴求與你的並不一定始終一致。他們的關注重點在於提升收入以及產品使用率,但爲此推出的全新產品使用方式,未必符合開發者的最大利益。

因此,在決定採用實時處理機制時,請首先確保擁有清晰明確的業務案例,並認真比較批量處理與實時處理之間的優劣差異。這個業務案例可以來自當前場景,也可以着眼未來需求。只有確定其具備牢固的價值主張,我們纔有必要嘗試新的技術實現方法;如果沒有,盲目行動只會帶來更多問題。

最後,我建議大家認真瞭解 Kafka 架構的固有侷限。其中一些可能不太引人注目,也有一些要求我們對分佈式系統具有深刻的理解才能體會。請確保您所在組織的架構師們真正清楚這一切對業務以及用例的實際影響。否則,您所做的一切其實都只是在爲供應商做嫁衣,甚至可能因此毀掉自己苦心積累起的業務體系。

原文鏈接:

https://www.jesse-anderson.com/2019/10/why-i-recommend-my-clients-not-use-ksql-and-kafka-streams/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章