資料架構的演進與儲存技術的革新密不可分。過去企業受限於關聯式資料庫的固定結構與擴展成本,資料分析彈性受限。分散式檔案系統,特別是Hadoop的普及,帶來了「先儲存,後分析」(Schema-on-Read)的典範轉移,資料湖應運而生。然而,真正將此概念推向成熟的關鍵是物件儲存。它徹底分離儲存與計算資源,降低維運複雜度與成本,並憑藉其擴展性與API驅動特性,成為雲端資料平台基石。本章將剖析此技術脈絡,從HDFS的侷限談起,說明物件儲存如何成為資料湖與湖倉一體的標準儲存層,並塑造現代資料工程的實踐。
第五章:物件儲存與資料湖
物件儲存與資料湖
結構化資料。湖倉一體是資料倉儲和資料湖功能的結合。玄貓將學習如何使用物件儲存,它是資料湖和湖倉一體的基礎技術和儲存。
在本章中,玄貓將涵蓋以下主題:
- 理解分散式檔案系統
- 深入探討湖倉一體
- 理解串流資料
- 使用串流來源
理解分散式檔案系統
GFS論文向科技界闡述了如何在大規模(當時而言)上成功儲存和存取資料。當時,數百TB的資料分散在數千台商用伺服器上。它們不僅可以儲存和存取大量的資料,還提供了儲存非傳統類型資料的能力。
然而,網際網路的興起帶來了影片檔案、圖片、音訊、電子郵件和HTML。傳統資料倉儲沒有能力儲存和使用這些類型的資料,因此新的分散式檔案系統是一個完美的解決方案。這個解決方案很快在業界透過Apache Hadoop於2005年普及,成為第一個廣泛採用的分散式檔案系統,稱為Hadoop分散式檔案系統(HDFS),以及處理框架(MapReduce)。這種以商用價格實現的儲存和計算的全新可擴展性,促成了資料湖的興起。
現在,讓玄貓深入探討資料湖,探索它們的工作原理以及為什麼它們對資料工程師如此重要。
資料湖
分散式儲存和計算允許公司儲存和分析大量各種資料,例如圖片、非結構化文本、音訊檔案等。這與資料庫系統以及網際網路時代之前有限的可擴展性相比,是一個完全的典範轉移。除了這種巨大的架構轉變之外,定價模型使得各種規模的公司都能夠開始使用。Hadoop是開源的,可以安裝在商用硬體上,並具有隨需擴展的理念。隨著資料集的增長,底層叢集的計算能力可以隨之擴展。將這種廉價、可擴展的基礎設施與提供進階分析能力相結合,被稱為資料湖。
有了資料湖,團隊可以引入任何類型的資料,並且可以隨意引入任意數量的資料。無需指定Schema,因此資料建模的決策已成為過去。這帶來的一個巨大好處是,在捕獲資料來源之前無需仔細審查。業務部門無需為永久儲存原始資料提供強有力的理由,因為儲存成本低廉,並且開發人員的參與可以降到最低。這使得資料可以在確定其特定用途之前就被捕獲。這樣做的能力確保了所有資料都被捕獲並最大程度地減少了資料丟失。
然而,每一次巨大的技術變革都會伴隨著其自身的成長煩惱。業務部門被允許隨意儲存他們選擇的任何東西,而無需太多審查。這很容易導致全職人員專門負責基礎設施維護和解決方案的擴展。Hadoop系統還遭受了單點故障和瓶頸的困擾,稱為NameNode。它充當叢集中所有其他節點之間的協調器,負責知道所有區塊的儲存位置、這些區塊的冗餘複製、工作節點之間的容錯性以及協調所有資訊請求。Amazon看到了這些缺點中的市場機會,並推出了其在Amazon Web Services (AWS)上的第一個普遍可用的服務,稱為簡易儲存服務(Simple Storage Service,簡稱S3)。
物件儲存
物件儲存透過提供極高的資料持久性(通常達到十一個九的可靠性)和極低的成本(每GB僅需約0.023美元)徹底改變了儲存產業。這種突破性的儲存範式,使得大規模、經濟高效地儲存海量資料成為可能,為資料湖和湖倉一體的發展奠定了堅實的基礎。
此圖示:傳統資料倉儲與資料湖演進
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
rectangle "傳統資料倉儲 (Pre-Internet)" as DW {
component "關聯式資料庫" as RDB
component "固定Schema" as Schema
component "有限可擴展性" as LimitedScale
RDB --> Schema
RDB --> LimitedScale
}
cloud "網際網路時代興起" as Internet {
component "影片/圖片/音訊" as Multimedia
component "非結構化文本" as UnstructuredText
component "海量資料" as BigData
Multimedia -- BigData
UnstructuredText -- BigData
}
rectangle "Google檔案系統 (GFS)" as GFS {
component "分散式儲存" as DistributedStorage
component "商用硬體" as CommodityHardware
DistributedStorage --> CommodityHardware
}
rectangle "Hadoop生態系統" as Hadoop {
component "HDFS (分散式檔案系統)" as HDFS
component "MapReduce (處理框架)" as MapReduce
HDFS --> MapReduce
}
rectangle "資料湖 (Data Lake)" as DataLake {
component "原始資料儲存 (Any Data)" as RawData
component "Schema-on-Read" as SchemaOnRead
component "廉價且可擴展" as CheapScale
RawData --> SchemaOnRead
RawData --> CheapScale
}
rectangle "湖倉一體 (Lakehouse)" as Lakehouse {
component "資料湖優勢" as DLAdvantage
component "資料倉儲管理" as DWManagement
DLAdvantage <--> DWManagement
}
cloud "物件儲存 (Object Storage)" as ObjectStorage {
component "S3 (AWS)" as S3
component "高持久性 (11個9)" as HighDurability
component "低成本" as LowCost
S3 --> HighDurability
S3 --> LowCost
}
DW --> Internet : 無法應對
Internet --> GFS : 催生解決方案
GFS --> Hadoop : 啟發開源實現
Hadoop --> DataLake : 奠定基礎
DataLake --> Lakehouse : 進一步演進
ObjectStorage --> DataLake : 成為核心儲存
ObjectStorage --> Lakehouse : 成為核心儲存
DW -[hidden]-> DataLake : 典範轉移
DataLake -[hidden]-> ObjectStorage : 核心儲存技術
@enduml看圖說話:
此圖示闡述了從傳統資料倉儲到資料湖和湖倉一體的演進過程,以及物件儲存在其中的關鍵作用。傳統資料倉儲(如關聯式資料庫)在網際網路時代面臨海量、多樣化資料的挑戰時顯得力不從心。Google的GFS為分散式儲存提供了藍圖,隨後Hadoop生態系統(HDFS和MapReduce)將其開源化,催生了資料湖的概念。資料湖以其儲存任意原始資料、Schema-on-Read和廉價可擴展的特性,解決了傳統倉儲的痛點。然而,資料湖也帶來了管理和治理的挑戰,這促成了湖倉一體的出現,它結合了資料湖的靈活性和資料倉儲的結構化管理能力。在此演進過程中,物件儲存(如AWS S3)以其極高的資料持久性和極低的成本,成為資料湖和湖倉一體不可或缺的底層儲存技術,為大規模資料處理提供了堅實的基礎。
第五章:物件儲存與資料湖
理解分散式檔案系統
對這些資料的存取具有可擴展性,部分原因是從傳統檔案系統中存在的階層式命名空間轉變為鍵值查找。以檔案櫃的組織為例。這個檔案櫃可以組織成資料夾、子資料夾和巢狀子資料夾。另一方面,物件儲存會將這個檔案櫃組織成一個扁平結構,其中每個檔案都在自己的資料夾中,並標有完整的路徑。
階層式命名空間允許快速點查找,而物件儲存則允許在規模上實現更高的吞吐量。傳統上,為了擴展系統上的儲存,還需要擴展計算。向Hadoop叢集添加儲存的最簡單方法是向其添加更多節點。這是物件儲存改變動態的另一個領域。
S3可以透過REST API在最低層次上存取,這在兩個方面有所幫助:
- 它允許程式設計師將儲存和計算視為兩個完全不同的實體和成本模型。對更多儲存的需求不再需要叢集中的更多節點。
- REST API消除了NameNode的瓶頸。
Amazon有責任處理S3在2006年推出時作為資料來源所要求的吞吐量需求,這使得S3幾乎立即聲名鵲起。近十年後,其他雲端供應商發布了自己的物件儲存,以與Amazon競爭。Microsoft Azure經歷了幾次迭代,最終提出了一個有趣的解決方案,稱為Azure Data Lake Storage Gen2 (ADLS Gen2)。其目標是將階層式儲存與物件儲存的功能結合起來,以提供大資料吞吐量能力和低成本,同時保留階層式儲存的優勢。這解決了S3引入物件儲存的一個令人頭痛的問題,即原子性中繼資料互動。這意味著重新命名檔案或刪除檔案會立即被系統感知。儘管S3在吞吐量方面通常優於ADLS Gen2(例如,S3每秒可處理高達5,500個GET請求,而Azure在儲存帳戶層級限制吞吐量為每秒20,000個GET請求),但S3已成為物件儲存實現的黃金標準,許多小型供應商也實現了自己的物件儲存,並提供S3相容的API。這些供應商包括MinIO、Wasabi和Dell的企業物件儲存。
雖然有許多S3相容的API,但為了簡潔起見,本書將簡要介紹使用AWS Java SDK (S3 SDK)與Scala進行底層S3互動。然後,本書的大部分內容將透過Apache Spark API和Scala抽象這種底層互動。對於S3 SDK,所需的一切只是一個S3儲存桶和物件的鍵。有了這兩條資訊,Scala就可以添加一個帶有一些文本的物件,如下所示:
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3ClientBuilder
val BUCKET_NAME = "scala-data-engineering"
val OBJECT_PATH = "my/first/object.csv"
val s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build()
s3Client.putObject(BUCKET_NAME, OBJECT_PATH, "id,name\n1,john")
從上述程式碼中,玄貓可以看到首先建立了一個用於與S3互動的客戶端,並帶有預設憑證。憑證可以是儲存在本地AWS設定檔中的使用者存取金鑰。另一個選項是使用Amazon Elastic Compute Cloud (EC2)和實例設定檔以實現更整合的安全性。透過S3客戶端和變數,玄貓可以使用以下語法讀取最近寫入的物件:
import com.amazonaws.services.s3.model.GetObjectRequest
import scala.io.Source
val s3Object = s3Client.getObject(new GetObjectRequest(BUCKET_NAME, OBJECT_PATH))
val myData = Source.fromInputStream(s3Object.getObjectContent()).getLines()
for (line <- myData) {
print(line)
}
最後,如果需要,可以使用以下語法刪除物件:
s3Client.deleteObject(BUCKET_NAME, OBJECT_PATH)
此圖示:物件儲存的優勢與演進
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "傳統檔案系統" as TraditionalFS {
component "階層式命名空間" as HierarchicalNamespace
component "儲存與計算耦合" as CoupledSC
HierarchicalNamespace --> CoupledSC : 限制擴展性
}
package "物件儲存" as ObjectStorage {
component "扁平式命名空間" as FlatNamespace
component "鍵值查找" as KeyValueLookup
component "儲存與計算分離" as DecoupledSC
component "REST API 存取" as RESTAPI
component "高持久性 (11個9)" as HighDurability
component "低成本" as LowCost
FlatNamespace --> KeyValueLookup
KeyValueLookup --> DecoupledSC
RESTAPI --> DecoupledSC
DecoupledSC --> HighDurability
DecoupledSC --> LowCost
}
package "AWS S3" as S3 {
component "黃金標準" as GoldStandard
component "高吞吐量" as HighThroughput
GoldStandard --> HighThroughput
}
package "Azure Data Lake Storage Gen2 (ADLS Gen2)" as ADLSGen2 {
component "階層式儲存 + 物件儲存" as HybridStorage
component "原子性中繼資料互動" as AtomicMetadata
HybridStorage --> AtomicMetadata
}
package "S3 相容儲存" as S3Compatible {
component "MinIO" as MinIO
component "Wasabi" as Wasabi
component "Dell EOS" as DellEOS
}
TraditionalFS --> ObjectStorage : 解決痛點
ObjectStorage --> S3 : 領先者
ObjectStorage --> ADLSGen2 : 競爭者
ObjectStorage --> S3Compatible : 生態擴展
S3 .up.> "S3 SDK / Spark API" as SDKAPI : 程式化互動
ADLSGen2 .up.> "Spark API" as SparkAPIADLS : 程式化互動
@enduml看圖說話:
此圖示展示了物件儲存相對於傳統檔案系統的根本性轉變及其在雲端時代的演進。傳統檔案系統以階層式命名空間組織資料,並將儲存與計算緊密耦合,導致擴展性受限。物件儲存則採用扁平式命名空間和鍵值查找,實現了儲存與計算的徹底分離,並透過REST API提供存取。這種架構帶來了高持久性和低成本的顯著優勢。AWS S3作為物件儲存的黃金標準,以其卓越的吞吐量引領市場。而ADLS Gen2則嘗試結合階層式儲存和物件儲存的優點,解決了S3在原子性中繼資料互動方面的挑戰。此外,圖中也呈現了許多S3相容儲存供應商,豐富了物件儲存的生態系統。最終,這些物件儲存服務都透過SDK或Spark API等方式,為開發者提供了程式化互動的能力,極大地簡化了大規模資料的處理和管理。
第五章結論
縱觀現代資料架構的演進脈絡,物件儲存的崛起並非單純的技術更迭,而是一場徹底改變企業數據資產價值觀的典範轉移。
從Hadoop將儲存與運算耦合的緊密架構,到物件儲存將兩者徹底分離,此一轉變的核心價值在於釋放了組織的策略彈性。企業能以極低成本保存所有原始資料,保留未來分析的無限可能,擺脫了傳統架構前期高昂投入的束縛。然而,這也帶來新的權衡,例如在AWS S3的極致吞吐量與ADLS Gen2的原子性操作之間,管理者需依據業務即時性與一致性需求,做出精準的技術選型判斷。
展望未來,市場焦點已從單純追求儲存的擴展性,轉向如何在其上建立兼具彈性與治理能力的「湖倉一體」架構。S3 API逐漸成為業界標準,更預示著一個開放、多元的數據儲存生態正在成形。
玄貓認為,掌握物件儲存的設計哲學與其生態演進,已是高階管理者制定前瞻性數據策略、鞏固企業數位時代競爭力的關鍵修養。