架構
開源分布式流存儲服務
本質是在計算引擎與底層存儲間充當解耦層,旨在解決新一代大數據平台在數據存儲層上的挑戰
1、數據湖
Pravega 提供的 Stream 原語可以避免現有大數據架構中原始數據在多個開源存儲搜索產品中移動而產生的數據冗余現象,其在存儲層就完成了統一的數據湖(一處存儲,多處使用)
2、區別
區別於lambda架構和kappa架構,以 Apache Flink 作為計算引擎,通過統一的模型/API來統一批處理和流處理。以 Pavega 作為存儲引擎,為流式數據存儲提供統一的抽象,使得對歷史和實時數據有一致的訪問方式。兩者統一形成了從存儲到計算的閉環,能夠同時應對高吞吐的歷史數據和低延時的實時數據
區別於kafka,Kafka定位是消息隊列,Pravega定位是存儲,更關注數據的動態伸縮、安全、完整等存儲特性。對於流式數據處理來說,數據應該被視為連續和無限的,而Kafka作為基於本地文件系統的消息隊列,采用添加到日志文件末尾並使用offset跟蹤內容的方式模擬無限的數據流,這種方式必然受限於本地文件系統的文件描述符、磁盤容量上限,因此嚴格來說並非無限
3、流式存儲的特點
對於來自序列舊部分的歷史數據,需要提供高吞吐的讀性能,即 catch-up read
對於來自序列新部分的實時數據,需要提供低延遲的 append-only 尾寫 tailing write 以及尾讀 tailing read
4、系統架構
在控制層面,Controller 作為 Pravega 集群的主節點對數據層面的 Segment Store做管理,提供對流數據的創建,更新以及刪除等操作。同時它還承擔實時監測集群健康狀態,獲取流數據信息,收集監控指標等功能。通常集群中會有3份 Controller 來保證高可用。
在數據層面,Segment Store 提供讀寫 Stream 內數據的 API。在 Pravega 里面,數據是分層存儲的:
- Tier 1 存儲
Tier1 的存儲通常部署在 Pravega 集群內部,主要是提供對低延遲,短期的熱數據的存儲。在每個 Segment Store 結點都有 Cache 以加快數據讀取速率,Pravega 使用 Apache Bookeeper 來保證低延遲的日志存儲服務。
- Long-term 存儲
Long-term 的存儲通常部署在 Pravega 集群外部,主要是提供對流數據的長期存儲,即冷數據的存儲。不僅支持 HDFS,NFS,還會支持企業級的存儲如 Dell EMC的 ECS,Isilon 等產品
概念
- Stream:把寫入的數據組織成 Stream,Stream 是命名的、持久的、僅追加的、無限的字節序列
- Stream Segments:Stream 會划分為一個或多個 Segments,相當於 Stream 中數據的分片,它是一個 append-only 的數據塊,而 Pravega 也是基於 Segment 基礎上實現自動的彈性伸縮。Segment 的數量也會根據數據的流量進行自動的連續更新
- Event:client API 允許用戶以 Event 為基本單位寫入和讀取數據,Event 具體是Stream 內部字節流的集合。如 IOT 傳感器的一次溫度記錄寫入 Pravega 就可以理解成為一個 Event
- Routing Key:每一個 Event 都會有一個 Routing Key,它是用戶自定義的一個字符串,用來對相似的 Event 進行分組。擁有相同 Routing Key 的 Event 都會被寫入相同的 Stream Segment 中。Pravega 通過 Routing Key 來提供讀寫語義
- Reader Group:用於實現讀取數據的負載均衡。可以通過動態增加或減少 Reader Group 中 Reader的數量來改變讀取數據的並發度
關鍵特性
1、讀寫分離
讀寫分離有助於優化讀寫性能:只從 Tier1 的 Cache 和 Tier2 Long-term 存儲去讀,只從 Tier1 中的 Bookkeeper 去寫。
(1)寫
在 Tier1 存儲部分,寫入數據的時候通過 Bookkeeper 保證了數據已經在所有的 Segment Store 中落盤,保證了數據寫入成功。
Tier1 的 Bookkeeper 在集群不出現故障的情況下永遠不進行讀取操作,只進行寫入操作
(2)讀
在客戶端向 Pravega 發起讀數據的請求的時候,Pravega 會決定這個數據究竟是從Tier1 的 Cache 進行低延時的 tail-read,還是去 Long-term 的長期存儲數據(對象存儲/NFS)去進行一個高吞吐量的 catch-up read(如果數據不在 Cache,需要按需load 到 Cache 中)。讀操作是對客戶端透明的
2、彈性伸縮
(1)存儲層
Stream 中的 Segment 數量會隨着 IO 負載而進行彈性的自動伸縮。如圖所示,
t0時刻,數據流寫入Pravega,根據鍵會路由到S0、S1,如果寫入速率不變則Segment數量不會發生變化;
t1時刻,S1寫入速率增大,S1進入sealed狀態,划分為S2、S3,根據鍵重定向到這兩個Segment,即scale-up操作;
t3時刻,S2、S5寫入速率減小,兩者都進入sealed狀態,合並成S6,即scale-down操作。
(2)應用層
以 Kubernetes Operator 來對集群各組件進行有狀態的應用部署,這可以使得應用的彈性伸縮更為靈活方便。
Pravega 最近也在和 Ververica 進行深度合作,致力於在 Pravega 端實現 Kubernetes Pod 級別的彈性伸縮同時在 Flink 端通過 rescaling Flink 的 Task 數量來實現彈性伸縮
3、事務性寫入
在提交事務之前,數據會根據路由鍵寫入到不同的 Transaction Segment 中,這時候 Segment 對於 Reader 來說是不可見的。只有在事務提交之后,Transaction Segment 才會各自追加到 Stream Segment 的末尾,這時候 Segment 對於 Reader 才是可見的,這是Pravega與Flink結合支持exactly-once的關鍵
引入 Pravega 前后的解決方案比較
實現了數據湖的理念,降低存儲、計算成本,減小運維壓力,提高代碼開發效率
