![]()
Kafka 社區對共享存儲的興趣由來已久:如果所有數據都放在 S3 這樣的共享存儲上,Broker 就不需要本地磁盤,副本復制可以省掉,跨 AZ 流量費也隨之消失。但對象存儲的延遲一直讓這個想法停留在「理論上很美」的階段。AWS 最近發布的 S3 Files 改變了這個前提——它給 S3 加上了 NFS 文件系統接口,小文件讀取延遲做到了亞毫秒級。于是一個老問題以新的面貌回來了:Kafka 能不能直接跑在 S3 Files 上?
我們在 AutoMQ 從 2023 年起就在解決這個問題——不是把 Kafka 搬到共享文件系統上,而是從存儲引擎層重新設計,讓 Kafka 真正運行在共享存儲架構上。我們是這個領域最早探索用共享文件系統作為存儲后端的團隊,也是目前唯一做到生產級低延遲的 Diskless Kafka 實現。所以當 S3 Files 出現時,我們自然要評估它的可能性——以及它的邊界在哪里。
S3 Files 是什么?
要回答「Kafka 能不能跑在 S3 Files 上」,先得理解 S3 Files 到底做了什么。它本質上是 AWS 在 S3 之上加了一層基于 EFS(Elastic File System)的文件系統訪問面——你可以通過 NFS 協議把 S3 存儲桶掛載到 EC2 實例上,像操作本地文件一樣讀寫,而 S3 始終是數據的 Source of Truth。
![]()
圖片這層訪問面的核心設計圍繞一個 128 KB 的閾值。小于 128 KB 的文件在首次訪問時會被導入 EFS 高性能層,讀取延遲可以做到亞毫秒到個位數毫秒;128 KB 及以上的文件則繞過 EFS,通過本地代理直接從 S3 流式讀取。寫入方向上,所有數據都先落到 EFS 層,再由后臺異步批量同步回 S3。換句話說,S3 Files 的優化重點是小文件的低延遲讀取,而不是讓所有數據都常駐在高性能層。
定價模型進一步印證了這個定位。寫入按流量計費 $0.06/GB,最小計費 I/O 為 6 KiB,沒有預置容量選項。數據同步到 S3 后不會立刻從 EFS 淘汰,默認駐留 30 天,期間你同時支付 EFS 高性能層存儲費($0.30/GB- 月)和 S3 存儲費用。對于讀多寫少的場景,這個定價是合理的。但對于持續高吞吐寫入的工作負載,寫入成本和 EFS 駐留費用會快速累積。
共享存儲對 Kafka 的吸引力
理解了 S3 Files 的能力邊界,再來看為什么大家想把 Kafka 構建在上面。傳統 Apache Kafka 是為專用服務器加本地磁盤設計的,這套架構搬到云上會產生三個不斷疊加的成本問題。
最直接的是副本復制帶來的跨 AZ 流量費。Kafka 通過 ISR(In-Sync Replicas)機制保證持久性,每條消息會被復制到兩到三個 Broker。在多 AZ 部署中,這種復制產生大量跨 AZ 網絡流量——AWS 對跨 AZ 數據傳輸雙向收費,合計 $0.02/GB。一個寫入吞吐 500 MB/s、副本因子為 3 的集群,兩個 Follower 分布在不同 AZ,每秒產生約 1 GB 的跨 AZ 復制流量,僅這一項就超過 $50,000/ 月。
![]()
圖片副本復制還帶來了第二個問題:存算耦合。每個 Broker 在本地磁盤上管理自己的數據副本,擴展存儲就意味著加機器——即使你只需要更多磁盤空間。而且必須按峰值負載加上故障冗余來預留容量,大部分時間都在為閑置資源付費。
存算耦合又進一步放大了運維復雜度。分區重分配需要在 Broker 之間物理搬遷數據,大 Topic 可能耗時數小時。Broker 故障觸發漫長的恢復流程。縮容比擴容更難,因為你得先把數據搬走。
如果所有數據都在 S3 這樣的共享存儲上,這三個問題可以一次性解決:S3 自帶 11 個 9 的持久性,不需要副本復制;Broker 變成無狀態計算節點,秒級擴縮容;跨 AZ 流量降到接近零。S3 Files 有 NFS 接口、有亞毫秒延遲,看起來正好是連接 Kafka 和共享存儲之間的橋梁。但真正嘗試搭建這座橋梁時,會遇到幾個根本性的問題。
挑戰:直接把 Kafka
跑在 S3 Files 上會怎樣?
![]()
持久性缺口
最符合直覺的做法是把副本因子設為 1——既然 S3 Files 提供了共享的持久化存儲,一份數據就夠了。問題出在 Kafka 的寫入機制上。
Kafka 是一個異步 I/O 系統。Producer 發送消息并收到 ack 時,數據還在操作系統的 Page Cache 里,并不一定已經刷到底層存儲。這是 Kafka 高吞吐的設計基礎——它假設即使 Broker 在刷盤前崩潰,數據仍然安全地存在于 Follower 副本上。但在 replica=1 的 S3 Files 上,這張安全網消失了。Broker 崩潰意味著 Page Cache 中尚未持久化的數據直接丟失,S3 Files 的 11 個 9 持久性幫不上忙——數據根本還沒到達存儲層。
要堵住這個缺口,需要改變 Kafka 的寫入路徑:確保每條被確認的消息在返回 ack 之前就已經持久化。這不是調配置能解決的,這是存儲引擎層面的重新設計。
可用性耦合
持久性問題可以通過改造寫入路徑來解決,但 Kafka 的高可用機制帶來了另一個更深層的挑戰。
Kafka 的 HA 和多副本設計緊密耦合:Broker 故障時,Controller 將 Follower 副本提升為新 Leader。這個機制的前提是存在 Follower——而 replica=1 意味著沒有 Follower 可以提升。你需要一套完全不同的故障轉移邏輯:讓新 Broker 直接從共享存儲讀取數據來接管分區,而不依賴本地副本。Kafka 現有的 HA 設計天然阻止了它利用 S3 Files 內置的可用性保障。
這同樣需要架構層面的重新設計——不只是寫入路徑,還有整個故障恢復和分區所有權的管理方式。
延遲現實
即使解決了持久性和可用性問題,延遲仍然是一道坎。S3 Files 宣傳的亞毫秒延遲針對的是 EFS 高性能層上的小文件讀取,而 Kafka 的核心工作負載是高吞吐的持續順序寫入——這兩者的 I/O 模式完全不同。
社區已經有人在 S3 Files 上跑過 Kafka benchmark,數據很說明問題:
![]()
圖片數據來源:https://www.linkedin.com/pulse/apache-kafka-meets-s3-files-jason-taylor-kxiae/
中位數和 P95 看起來還行——P95 只有 5-13ms,和原生 Kafka 差距不大。但從 P95 到 P99 出現了斷崖式跳躍:5ms 直接飆到 704ms,延遲放大了 140 倍。這意味著每一百次請求就有一次要等超過一秒。對于實時流處理場景——風控、實時大屏、事件驅動微服務——這種不可預測的尾延遲是不可接受的。S3 Files 并沒有徹底解決共享存儲的低延遲問題,相比本地磁盤上的 Kafka 仍然有明顯的延遲犧牲。
成本結構
![]()
延遲之外,S3 Files 的定價模型對 Kafka 也不友好。S3 Files 采用按流量計費——寫入 $0.06/GB,小文件讀取 $0.03/GB,沒有預置容量選項。這和 S3 的按 API 請求次數計費是完全不同的模型。Kafka 的工作負載特征是寫入和讀取都需要走高性能層:Producer 寫入的數據落到 EFS 高性能層,Consumer 做 Tailing Read(消費最新數據)也從高性能層讀取。兩端都按流量計費,成本隨吞吐量線性增長。寫入端還有雙重流量費——數據先寫入 EFS($0.06/GB),再由后臺同步回 S3($0.03/GB),Kafka 的所有數據都需要同步回 S3,這筆同步費逃不掉。更隱蔽的是 EFS 高性能層的存儲駐留費:$0.30/GB- 月,是 S3 Standard 存儲費的 13 倍,數據默認駐留 30 天才淘汰。
算一筆具體的賬。一個 100 MB/s 持續寫入的集群,假設消費端吞吐和寫入相當(1x fan-out,即一個 Consumer Group),每天寫入和讀取各約 8,400 GB(100 MB/s × 86,400 秒):
![]()
圖片這還是 1x fan-out 的保守估算。如果有多個 Consumer Group(在 Kafka 場景中很常見),Tailing Read 的流量費會成倍增長。2x fan-out 下月成本就超過 $113,000,3x 超過 $120,000。而且這還沒算 S3 本身的存儲費。S3 Files 的定價模型是為「讀多寫少、活躍工作集小」的場景設計的——Kafka 恰好相反:持續高吞吐寫入,所有數據都是「活躍」的,讀取端也是持續高吞吐。
這些挑戰加在一起意味著什么?
持久性缺口要求重新設計寫入路徑。可用性耦合要求重新設計故障轉移機制。延遲問題要求在對象存儲之前加一層高性能寫入緩沖。成本問題要求對小寫入進行攢批優化。把這四項加在一起,你實際上需要的是一個全新的 Kafka 存儲引擎——而這正是 AutoMQ 從 2023 年就在構建的東西。
AutoMQ 已經被驗證的
Shared Storage 架構
AutoMQ 的架構分為兩層。S3 是主存儲層,所有數據最終都持久化在 S3 上——這是和 Tiered Storage 的根本區別。Tiered Storage 仍然把熱數據放在本地磁盤上,S3 只存冷數據;而 AutoMQ 讓 S3 成為唯一的 Single Source of Truth,Broker 上沒有任何持久化狀態。
關于兩者的詳細對比,可以參考這篇文章:https://docs.automq.com/automq/what-is-automq/difference-with-tiered-storage
但直接把每條消息都寫到 S3 有兩個問題:S3 的寫入延遲太高,而且 S3 API 調用是按次計費的——每條消息一次 PUT 請求,API 成本會隨消息數線性爆炸。這就是 WAL(Write-Ahead Log)層存在的意義。
WAL 是一塊固定大小的高性能存儲空間,充當 S3 前面的寫入緩沖。所有 Produce 請求先寫入 WAL,使用 Direct IO 繞過 page cache,在返回 ack 之前就保證數據持久化——這直接堵住了上面說的持久性缺口。然后 WAL 中的數據被異步壓縮、攢批,再批量上傳到 S3。這個攢批過程至關重要:不是每條消息一次 S3 PUT,而是每批數千條消息一次 PUT,S3 API 成本從隨消息數增長變成了隨吞吐量增長,降低了一到兩個數量級。
![]()
WAL 帶來的另一個關鍵好處是讓用戶可以在延遲和成本之間做 trade-off。WAL 層是可插拔的,不同的云存儲后端對應不同的延遲和成本特征:EBS/Regional EBS WAL 提供亞毫秒延遲,NFS WAL(AWS 上基于 FSx for NetApp ONTAP)提供平均 6ms、P99 約 13ms 的寫入延遲。Producer 的體驗和原生 Kafka 沒有區別。
而且 WAL 的成本很低。它只需要一小塊固定大小的存儲空間——不是存全量數據,只是一個循環寫入的緩沖區。對于大部分云存儲的定價模型來說,這非常友好:每月幾美元到幾十美元的 WAL 支出,就能換來低延遲持久化、S3 API 成本優化、以及真正的無狀態 Broker。
因為所有持久化狀態都在 WAL 和 S3 中,Broker 是真正無狀態的。一個 Broker 故障時,另一個 Broker 在秒級內接管分區映射,不需要數據遷移,Zero RPO——這解決了可用性耦合的問題。
最終效果是 Kafka on S3 Files 所承諾的一切——零跨 AZ 流量、無副本復制、彈性無狀態 Broker——但沒有持久性缺口、秒級尾延遲和高昂的流量成本。
S3 Files 作為 WAL
技術上可行,經濟上還不成熟
既然 AutoMQ 的 WAL 層是可插拔的,S3 Files 能不能作為又一個 WAL 后端?從架構上看,答案是肯定的。S3 Files 提供 NFS 接口,底層基于 EFS 構建——而 AutoMQ 的 NFS WAL 已經支持 EFS 和 FSx for NetApp ONTAP 作為實現,技術路徑是通的。
但當前的定價模型讓這個方案的經濟賬算不過來。Kafka 不是一個輕量級的應用層服務,它是數據密集型的基礎設施——AutoMQ 的一些生產客戶集群吞吐超過 1 GiB/s,7×24 小時不間斷寫入。在這個量級下,S3 Files 的純按量計費模型會產生驚人的費用。
以一個相對溫和的工作負載為例——寫入吞吐 100 MB/s、平均消息大小 4 KiB:
![]()
圖片100 MB/s 已經是一個保守的數字了。如果換成 1 GiB/s 的生產集群,S3 Files 的月成本會突破百萬美元——流量費和 EFS 存儲駐留費都隨吞吐量線性增長。核心問題在于 S3 Files 的定價模型是為「讀多寫少、活躍工作集小」的場景設計的,而 Kafka 恰好相反:持續高吞吐寫入,所有數據都是「活躍」的。S3 Files 作為 WAL 的開銷遠高于直接使用 EFS,而延遲上并沒有優勢。
不過云存儲的定價在持續演進。如果 AWS 為 S3 Files 引入預置吞吐模型或降低最小計費 I/O,這筆賬可能很快就會變。AutoMQ 的架構已經為那一天做好了準備。
一套架構,適配所有云存儲
S3 Files 的故事其實揭示了一個更大的趨勢:云存儲在加速分化。AWS 在過去兩年推出了 S3 Express One Zone(個位數毫秒延遲的 S3)、S3 Files(NFS over S3)、以及對 EFS 和 FSx for NetApp ONTAP 的持續改進。GCP 和 Azure 也在各自的存儲服務上走著類似的路線。每種存儲服務針對不同的訪問模式、成本模型和持久性保障做了優化。
![]()
圖片AutoMQ 的可插拔 WAL 架構意味著我們不需要押注某一個贏家——每一次云存儲創新都會成為 WAL 后端菜單上的一個新選項:
![]()
圖片用戶不需要被鎖定在某一種存儲方案上,而是可以根據自己的延遲要求和成本預算自由選擇——并且隨著需求變化或云定價演進隨時切換。在 AWS 上,NFS WAL 已經支持 EFS 和 FSx for NetApp ONTAP 兩種實現;在 Azure 和 GCP 上,Regional EBS WAL 利用各自的多 AZ 塊存儲提供亞毫秒延遲。讓這一切成為可能的 WAL 抽象層,從第一天起就是這么設計的。
回到最初的問題
Kafka 構建在 S3 Files 上,是個好主意嗎?如果說的是把原生 Kafka 直接掛載上去——不是。Kafka 的異步 I/O、基于副本的 HA、對本地存儲的假設,這些設計決策會讓你回到原點:還是要管副本、管故障轉移、管容量規劃。共享存儲就在那里,但 Kafka 的架構用不上。
但 Kafka 向 Shared Storage 架構演進的方向是確定的——經濟賬和運維收益太有說服力了。AutoMQ 基于 WAL 的 Shared Storage 架構已經交付了這個承諾,而且每當云存儲向前邁進一步,可插拔的 WAL 層就把這次創新變成用戶的一個新選項。一套架構,適配所有云存儲。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.