Kafka真正定位並不是訊息系統

banq發表於2017-09-18
本文是Kafka創始人的一篇部落格,認為Kafka可以用於像資料庫那樣持久儲存,這與人們通常對訊息系統的印象不同,其實Kafka真正定位是一個日誌系統,訊息佇列只是其一個應用模式,如同會氣功的人玩劈磚一樣,騰訊將Kafka改為真正訊息系統用於微信也可見Kafka的內功深厚,其在大資料分析領域配合Kafka Stream將是Storm/Spark以後的流式計算新貴。

原文大意如下:


人們經常詢問Apache Kafka的一個問題是:是否可以將其用於長期儲存。其實Kafka本身就是一個儲存記錄的日誌系統。

問題是您是否真的可以將這種日誌看成檔案系統一樣呢?將其用作資料的真實儲存庫。

顯然這是可能的,如果您將預設的保留(retention )設定為“永遠(forever)”或啟用主題的日誌壓縮功能,那麼資料將一直保留在Kafka中。但我認為人們問這個問題真正意思是,這是否會奏效?是完全瘋狂嗎?

簡單的答案是,這不是瘋狂的,人們一直這樣做,而卡夫卡實際上是為這種型別的使用而設計的。但首先,你需要了解為什麼要這樣做?這裡有一些實際用例:

1.您可能正在使用事件溯源(Event Sourcing)構建應用程式,並需要一個儲存變動的日誌。理論上你可以使用任何系統來儲存這種變動修改日誌,但是Kafka直接解決了不可變的日誌和“物化檢視”中的很多問題。見:紐約時報將其作為所有的文章資料儲存核心

2.您可能在應用程式的每個例項中都有一個記憶體快取,由Kafka提供更新。一個非常簡單的構建方法是將Kafka主題進行日誌壓縮,並且只要重新開始匯入資料到快取中時,應用程式只要從零偏移的開始位置重新開始重新整理就行了。

3.透過卡夫卡實現流處理進行資料流計算時,當流處理程式碼的邏輯發生變化時,您經常要重新計算結果。一個非常簡單的方法是將程式的偏移量重置為零,以使用新的程式碼重新計算結果。有時候,這個有趣的名字叫做“Kappa架構”。

4.Kafka通常用於捕獲和分發資料庫的更新流(這通常稱為Change Data Capture更改資料捕獲,簡稱CDC)。正常情況下已經在執行的應用程式通常只需要資料的最新改動,但是新的應用程式則需要從頭開始使用整塊資料。然而,執行大型生產資料庫的完全轉換儲存通常是非常精細和耗時的操作。在主題上啟用日誌壓縮可以透過重置為零來簡化這種資料的重新載入操作。

那麼這樣做是瘋狂的嗎?答案是否定的,在Kafka中儲存資料並不奇怪,因為它就是為了這樣做而設計的。Kafka中的資料被持久化到磁碟,校驗和複製以進行容錯。累積更多的儲存資料並不會減慢。有Kafka叢集在生產中執行超過一百億位元組儲存資料的案例。

那麼為什麼在Kafka中儲存資料這件事會讓人們非常關心,因為這顯然是像儲存系統應該做的事情?

我認為,人們關注卡夫卡通常是因為它被描述為訊息佇列系統。使用訊息佇列的前兩個規則是:“您不可以在訊息佇列中儲存訊息”。這在傳統訊息傳遞系統中是有以下原因:

1. 因為讀訊息時會刪除它
2. 因為訊息系統的資料量不足,資料累積起來會出現超出記憶體的情況。
3. 因為訊息傳遞系統通常缺乏強大的複製功能(因此,如果訊息系統程式當機,您的資料也可能會消失)。

這些傳統訊息系統的設計實際上是有很大的缺陷。畢竟,如果你考慮到,任何非同步訊息傳播基本底層都會儲存訊息,即使它們只是在幾秒鐘之內就被消費。我的服務傳送一個訊息到佇列中後就可以繼續做其他業務,但我想要一些保證機制確保其他服務能最終會收到和處理該訊息,因此必須在某處儲存它,直到其他服務消費後刪除它。所以如果你的訊息系統不能很好地儲存訊息,那麼它也不是“佇列”訊息系統。您可能會認為這並不重要,因為您不打算長時間儲存訊息。但是無論訊息系統中的訊息如何簡短,如果訊息系統處於連續的高負載狀態,總是會儲存一些未被訊息的訊息。所以當這個系統失敗出錯時,如果它沒有提供容錯儲存的能力,那就會丟失資料。因此,做訊息系統的功能就需要擁有儲存能力,這一點似乎很明顯,但是當人們評估訊息傳遞系統時,經常會錯過。

因此,儲存是訊息系統使用中非常重要的判斷標準。但實際上,卡夫卡並不真正是傳統意義上的訊息佇列,在實現中,它看起來不像RabbitMQ或其他類似的技術。在架構上相比傳統的訊息佇列,它更接近於分散式檔案系統或資料庫。卡夫卡與傳統資訊系統有三個主要區別:

1. 正如我們所描述的那樣,Kafka是一個永久性儲存日誌系統,可以重頭讀取資料並無限期儲存資料。

2.卡夫卡是作為現代分散式系統構建的:它可以叢集方式執行,可以彈性擴充套件或伸縮,並在內部複製資料,以實現容錯和高可用性。

3.Kafka可以進行實時流處理,而不僅僅是一次處理單個訊息。這允許在更高階別的抽象中處理資料流。

我們認為這些差異足以證明,將卡夫卡視為訊息佇列非常不準確,而應將其分類為流式平臺。

訊息系統、儲存系統和Kafka之間的關係如下。

訊息系統都是傳播未來訊息,當您正在等待新訊息到達時,您等待的是在未來某個時刻將到來的訊息。

儲存系統(如檔案系統或資料庫)都是關於儲存過去的寫入資料的:當您查詢或從中讀取資料時,您將根據過去所做的更新獲取結果。

流處理的本質是能夠將這兩個二者結合起來,可以處理過去,並在未來有新訊息時可繼續處理。這就是為什麼卡夫卡的核心抽象是一個連續的時間上有序的日誌。

這個抽象的關鍵在於,它是一種結構化的“檔案”,當您到達檔案最後一個位元組時並不會結束,而是在邏輯上至少是永遠。因此,寫入日誌的程式不需要區分已經發生的資料和將來會發生的資料,這一切都表現為一種連續的流。

儲存過去和將未來傳播到單一統一協議和API之後的這種組合正是Kafka在流處理方面發揮作用的關鍵點。

這個儲存的日誌非常類似於分散式檔案系統中的檔案,因為它跨機器複製,持久化到磁碟,並支援高吞吐量的線性讀寫,但它也像一個訊息系統,它允許許多許多高吞吐量併發寫入,並且對訊息的釋出時間進行了非常精確的定義,以允許對許多消費者進行進行低成本的、低延遲的變動傳播。在這個意義上,它是兩個世界中最好的。

在實施中,這個複製的日誌非常適合用作儲存,這不是意外設計的功能。事實上,卡夫卡本身就是儲存,所以你不用迴避!內部卡夫卡儲存並跟蹤消費者使用相應主題中的位置偏移量,Kafka的Streams API使用壓縮主題作為應用程式處理狀態的日誌。這兩種用例都需要永久儲存所寫入的資料。

儲存系統在正確性、正常執行時間和資料完整性方面真正承擔了巨大的負擔。我參與了在LinkedIn建立和執行幾代分散式資料庫,當一個系統被視為資料的規範來源時,軟體正確性和操作實踐的標準大大增加。我們為Kafka的正確性付出了很大的努力 - 除了成千上萬的正常單元測試之外,我們每天都會執行數百次機器時間的分發性折磨測試,但是老實說總是會做更多的事情。但是,除了測試之外,如果您正在為這種用例執行Kafka,那麼您需要確保知道如何良好執行,並且需要知道系統的限制。這是Confluent可以幫助的:我們提供支援和工具,用於自己管理和監控Kafka,或託管服務。

當我和其他人談論這個問題時,他們有時候會問,如果這意味著卡夫卡可以成為一種通用的資料庫,那麼就會廢除所有其他的儲存空間(顯然我和很多卡夫卡粉絲交談)。答案可能不是,有兩個原因:

首先,資料庫主要是關於查詢,我不認為Kafka真的會嘗試直接針對日誌新增任何型別的隨機訪問查詢。相反,它正在做的是將可複製的資料的日誌儲存到任意數量真正的資料庫、快取、流處理器、搜尋引擎、圖形儲存和資料湖中(更不用說定製應用程式或SaaS產品)。這些系統中的每一個都有自己的利弊,我認為在一個單一的系統中,你可以比所有這些系統都更好。這些儲存通常需要與其自己的儲存佈局非常緊密(例如,分析資料庫具有非常複雜的柱狀索引技術,搜尋索引保持反向索引,快取在記憶體中,LSM有利於寫入,btrees優於讀取等) 。

如果卡夫卡不會成為查詢的通用格式,那它是什麼呢?我認為將你的資料中心視為一個巨大的資料庫,在該資料庫中,Kafka是確認資料庫提交SQL操作的日誌,各種儲存系統是派生的索引或各種檢視。

這是真的,像Kafka這樣的日誌可以看成是建立資料庫的原始資料,但是查詢仍然由根據恰當訪問模式而構建的索引提供。

其中最好的例子之一是Kafka Streams API中的互動式查詢功能。Kafka Streams應用程式只是另一個Kafka消費者,但他們可以保持狀態的持續計算,這是一種流。這種狀態可以直接查詢或者輸出到外部系統中。不包括直接查詢Kafka,而是使流程處理應用程式能夠在Kafka中保留資料的派生的、可查詢的物化檢視,並對其執行低延遲查詢。

Kafka叢集用來儲存日誌,流處理API用來儲存物化檢視並對其進行查詢。您可以將其視為應用程式和資料庫之間分界線的一種重構。當我們新增KSQL時,這變得更有趣,它是一個用於卡夫卡的流式SQL引擎。使用KSQL,您不再需要編寫任何程式碼,但可以使用SQL語句來連續地轉換和計算Kafka中的物化檢視(並且很快就對這些檢視進行查詢)。

但是也許Kafka不新增查詢API的另一個原因是它有一個更令人興奮的使命。卡夫卡的目標是使資料流和流處理成為主流開發範例,並使這種型別的流媒體平臺成為現代數字業務的中樞神經系統。

我認為這實際上比建立第1001個資料庫更有趣。我認為這種型別的流媒體平臺對於資料在現代企業中的移動和處理以及現代實時應用程式的構建方式至關重要。所以我們把其作為重點放在第一位。

相關文章