當前的大數據處理系統無論是何種架構都面臨一個共同的問題,即:“計算是原生的流計算,而存儲卻不是原生的流存儲” 。Pravega 團隊重新思考了這一基本的數據處理和存儲規則,爲這一場景重新設計了一種新的存儲類型,即原生的流存儲,命名爲”Pravega”,取梵語中“Good Speed”之意。本文是“分佈式流存儲 Pravega 系列文章”第二篇,第一篇文章回顧《爲什麼你需要開源分佈式流存儲 Pravega?》。
流行大數據存儲存在的三大問題
如圖1是目前大數據處理平臺最常見的Lambda架構,它的優勢在於滿足了實時處理與批處理需求,但是,正如前一篇文章《實時流處理統一批處理的最後一塊拼圖:Pravega》的觀點,從存儲的角度看其缺點也很明顯,可以總結爲如下三點:
- 實時處理、批處理不統一,不同的處理路徑採用了不同的存儲組件,增加了系統的複雜度,導致了開發人員的額外學習成本和工作量。
- 數據存儲多組件化、多份化,如下圖,同樣的數據會被存儲在Elastic Search 、S3對象存儲系統、Kafka等多種異構的系統中,而且考慮到數據的可靠性,數據還都是多份冗餘的,這就極大的增加了用戶的存儲成本。而往往對於企業用戶來說,0.1%的存儲冗餘都意味着損失。
- 系統裏存儲的組件太多太複雜,也增加了使用的運維成本。並且大部分現有的開源項目還處於“強運維”的產品階段,對於企業用戶來說又是很大的開銷。
爲了解決如上提出的三個問題:降低開發成本、減少存儲成本與減少運維成本,在這篇文章中,我們將從Pravega的架構角度出發,挖掘流存儲的具體需求,並且通過架構的設計解決這三個問題。
第四種存儲類型:流存儲
從存儲的視角來說,存儲架構的設計需要首先明確存儲的特點。每種類型的數據都有其原生的屬性和常用訪問模式,對應有最佳的適用場景以及最合適的存儲系統。
在物聯網、金融等實時應用場景中,所需要存儲的數據一般被稱之爲“流數據”,流數據一般被定義爲:
流數據是一組順序、大量、快速、連續到達的數據序列,一般情況下,數據流可被視爲一個隨時間延續而無限增長的動態數據集合。
上圖所示,我們將流數據定義爲第四種數據類型。從左到右分佈着四種最常見的的存儲類型,依次從傳統批數據轉變成流數據。傳統數據庫這類基於事務的程序適合採用塊存儲系統。文件共享場景下需要在用戶間共享文件進行讀寫操作,因此適合採用分佈式文件(NAS)存儲系統。而需要無限擴展並支持REST接口讀寫的非結構化的的圖像/音視頻文件則非常適合採用對象存儲系統。
流數據存儲針對流數據的應用場景需要滿足以下需求:
-
低延時:在高併發條件下 <10ms的讀寫延時。
-
僅處理一次:即使客戶端、服務器或網絡出現故障,也確保每個事件都被處理且只被處理一次。
-
順序保證:可以提供嚴格有序的數據訪問模式
-
檢查點:確保每個讀客戶端/上層應用能保存和恢復原來的使用狀態
從訪問模式角度看,Pravega需要統一傳統批數據和流數據,因此不僅需要實時到達數據的低延時(low latency)讀和寫,還要滿足對於歷史數據的高吞吐(high throughput)的讀。
技術在某種程度上一定是來自此前已有技術的新的組合。 --《技術的本質》,布萊恩·阿瑟
Pravega也並不是憑空發明出來的,它是以前的成熟技術與新技術的組合。Pravega團隊擁有着基於日誌存儲的設計經驗,也擁有Apache ZooKeeper/BookKeeper的項目歷史,加之大量實時系統同樣也採用日誌存儲的方式來完成實時應用的消息隊列,想要滿足這三種數據訪問模式,自然想到了使用僅附加(Append only)的日誌作爲存儲原語。
如圖3所示:在Pravega裏,日誌是作爲共享存儲原語而存在的,數據以事件(event)的形式以僅附加的方式寫入日誌當中。
所有寫入操作以及大部分讀取操作都發生在日誌的尾部(tail read/write)。寫操作將事件附加到日誌中,而大量讀客戶端希望以到達日誌的速度讀取數據。這兩種數據訪問機制主要是需要低延遲。
對於歷史數據的處理,讀客戶端不從日誌的尾部讀取,而是從日誌中的任意位置開始讀。這些讀取稱爲追趕讀(catch-up read)。我們可以採用和尾部數據一樣的高性能存儲(例如SSD)來存儲歷史數據,但這會非常昂貴並迫使用戶通過刪除歷史數據來節省成本。這就需要Pravega架構提供一種機制,允許客戶在日誌的歷史部分使用經濟高效,高度可擴展的高吞吐量存儲,這樣他們就能夠保留所有的歷史數據,來完成對一個完整數據集的讀取。
Pravega邏輯架構
爲了實現上述的三種訪問模式的性能需求,Pravega採用瞭如上圖所示的分層存儲架構。事件可以存儲在低延遲/高IOPS的存儲(第一層存儲)和更高吞吐量的存儲(第二層存儲)中。通過這種方式,冷熱數據分離有效降低了數據存儲成本。上層使用Apache ZooKeeper作爲分佈式協調器,並提供統一的Stream抽象。
第一層存儲用於快速持久地將數據寫入stream,並確保從stream的尾讀儘可能快。第一層存儲基於開源Apache BookKeeper項目。BookKeeper是一種底層的日誌服務,具有高擴展、強容錯、低延遲等特性。許多Apache開源項目,例如Apache Pulsar,Apache DistributedLog都是基於這一項目實現。BookKeeper對於複製、持久性、一致性、可用性、低延時的承諾也正是Pravega所需要的第一層存儲的需求。爲達到高性能的讀寫延遲需求,我們建議第一層存儲通常在更快的SSD或甚至非易失性存儲(non-volatile RAM)上實現。
第二層存儲考慮到經濟效益,選用高度可擴展,高吞吐量的雲存儲,目前Pravega支持HDFS,NFS和S3協議的二級存儲,用戶可以選用支持這些協議的大規模存儲進行擴展。Pravega提供了兩種數據降層(retention)的模式,一種基於數據在stream中保留的時間,另一種基於數據在stream中存儲的容量大小。Pravega會異步將事件從第一層遷移到第二層,而讀寫客戶端將不會感知到數據存儲層級的變化,依然使用同樣的Stream抽象操作數據的讀寫。
正是基於這樣的分層模型,文章開頭提到的三大問題被一次性解決。
- 對於開發者而言,只需要關心Stream抽象的讀寫客戶端的操作。實時處理和批處理不再區分對數據訪問方式。
- 數據僅在第一層存儲有三份拷貝,在第二層存儲則可以通過商業分佈式/雲存儲自身擁有的高可用、分佈式數據恢復機制(如Erasure Coding)進一步降低存儲係數,達到比公有云存儲更便宜的總擁有成本(TCO)。
- 所有的存儲組件歸結爲統一的Pravega,組件僅包括Apache ZooKeeper,Apache BookKeeper以及可託管的第二層存儲,運維複雜程度大大降低。Pravega還提供了額外的“零運維”自動彈性伸縮特性,進一步減輕了數據高峯期的運維壓力。
Pravega的基本概念
本章節將簡要介紹一些Pravega的基本概念。
Stream:Pravega存儲的抽象,類似於Kafka的topic,是一種可持久化、可伸縮、僅附加、字節大小無限制的序列,具有高性能和強一致性的特性。在同一個scope內stream具有命名唯一性,stream由一個或多個segment組成。用戶可以在創建stream時配置降層策略(RetentionPolicy
)和伸縮策略(ScalingPolicy
)。
Scope:scope是stream的命名空間,將stream進行分類和隔離。在多租戶場景下,每一個租戶擁有一個scope。例如,具體應用、商業部門等可以劃分scope。
Segment:Pravega最底層的存儲單元,對應BookKeeper中的ledger。stream由segment組成,segment是stream的分片,類似但不侷限於Kafka的partition。事件(event)存儲在segment裏。一個stream的segment的數量可以根據到達數據量和伸縮策略改變,同時也是該stream讀取時的最大並行度。
事件(event):Pravega IO操作的最小單位,類似於Kafka的message。事件是stream中的可以表示爲一組字節的任何事物。例如:來自溫度傳感器的讀數,網站點擊和日誌數據等。
Stream,segment和事件的關係如下圖所示。
路由鍵(Routing key):事件所擁有的屬性,路由鍵會通過一致性散列算法(consistent hashing)將事件讀寫到對應的segment,因此相同的路由鍵會將事件路由到相同的segment,由相同的讀客戶端讀取。路由鍵是Pravega許多讀寫語義特性的基礎。
寫客戶端(Writer):寫客戶端是一個可以創建事件並將事件寫入一個或多個stream中的應用,所有的事件數據都通過附加到stream的尾部來寫入。
讀客戶端(Reader):讀客戶端是一個可以從一個或多個stream中讀取事件的應用。Pravega會以負載均衡方式分配stream中的segment給指定的Reader。讀客戶端可以從stream中的任何一點讀取,比如頭部、尾部、中間任何一點。
讀者組(Reader Group):讀者組由讀客戶端組成,讀者組本質上是爲了實現同一個組內讀客戶端的並行化以及不同組的stream讀取扇出,類似於Kafka的Consumer Group。同一個讀者組內的讀客戶端可以一起並行讀取給定的一組segment內的事件。讀者組由name
字符串唯一標識。
Pravega產品定位和與kafka的對比
前面我們已經提到過Pravega是從存儲的視角來看待流數據,而Kafka本身的定位是消息系統而不是存儲系統,它是從消息的視角來看待流數據。消息系統與存儲系統的定位是不同的,簡單來說,消息系統是消息的傳輸系統,關注的是數據傳輸與生產消費的過程。Pravega的定位就是企業級的分佈式流存儲產品,除了滿足流的屬性之外,還需要滿足數據存儲的持久化、安全、可靠性、一致性、隔離等屬性,關注數據的生產、傳輸、存放、訪問等整個數據的生命週期。作爲企業級的產品,一些額外的特性也有支持,例如:數據安全、多租戶、自動擴縮容、狀態同步器、事務支持等,部分特性將在後續文章詳述。
這裏我們把Pravega與Kafka做了對比,大體在功能上的差異如下表所示。功能上的差異也只是說明各個產品針對的業務場景不同,看待數據的視角不同,並不是說明這個產品不好,另外每個產品自身也在演進,因此本對比僅供參考。
名稱 | Kafka 2.1.0 | Pravega 0.4 |
---|---|---|
自動擴容縮容 | 部分支持 | 支持 |
完全不丟數據 | 不支持 | 支持 |
多協議可入 | 支持 | 支持 |
無限個流 | 不支持 | 支持 |
事務 | 支持 | 支持 |
恰好一次 | 支持 | 支持 |
順序保證 | 支持 | 支持 |
兼容Kafka API | 支持 | 支持 |
與主流處理平臺集成 | 支持 | 部分支持 |
多種二層存儲支持(HDFS,S3,etc) | 不支持 | 支持 |
安全與加密 | 支持 | 支持 |
無限多租戶 | 不支持 | 部分支持 |
服務質量保證 | 部分支持 | 部分支持 |
流計算應用集成 | 支持 | 支持 |
數據治理 | 不支持 | 支持 |
總結
本文從商業痛點出發,分析了分佈式流存儲Pravega的需求,重點介紹了Pravega的關鍵架構以及關鍵特性,另外還與Kafka做了簡要對比。有關Pravega的更多詳細信息,請參閱官方網站以及關注我們的後續文章。
Pravega系列文章計劃
Pravega根據Apache 2.0許可證開源,我們歡迎對流式存儲感興趣的大咖們加入Pravega社區,與Pravega共同成長。下一篇文章將會從Pravega的應用實例出發,闡述如何使用Pravega。本篇文章爲Pravega系列第二篇,後面的文章標題如下(標題根據需求可能會有更新):
- 實時流處理(Streaming)統一批處理(Batch)的最後一塊拼圖:Pravega
- Pravega設計原理與基本架構介紹
- Pravega應用實例
- Pravega動態彈性伸縮特性
- Pravega的僅一次語義及事務支持
- 分佈式一致性解決方案:狀態同步器
- 與Apache Flink集成使用
作者簡介
-
滕昱:就職於 DellEMC 非結構化數據存儲部門 (Unstructured Data Storage) 團隊並擔任軟件開發總監。2007 年加入 DellEMC 以後一直專注於分佈式存儲領域。參加並領導了中國研發團隊參與兩代 DellEMC 對象存儲產品的研發工作並取得商業上成功。從 2017 年開始,兼任 Streaming 存儲和實時計算系統的設計開發與領導工作。
-
吳長平,現就職於DellEMC,10年+ 存儲、分佈式、雲計算開發以及架構設計經驗,現從事流存儲和實時計算系統的設計與開發工作;
-
周煜敏,復旦大學計算機專業研究生,從本科起就參與 DellEMC 分佈式對象存儲的實習工作。現參與 Flink 相關領域研發工作。