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

軟件 大數據 SQL 卡夫卡 解道Jdon 解道Jdon 2017-09-19

本文是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個數據庫更有趣。我認為這種類型的流媒體平臺對於數據在現代企業中的移動和處理以及現代實時應用程序的構建方式至關重要。所以我們把其作為重點放在第一位。

相關推薦

推薦中...