【導讀:數據是二十一世紀的石油,蘊含巨大價值,這是·情報通·大數據技術系列第[77]篇文章,歡迎閱讀和收藏】
1 基本概念
與傳統的 IO 相比, Spark IO 有很大區別。傳統的數據存在單個計算機中,數據量少,而 Spark 的數據存儲在集群中,數據量巨大。另外, Spark 需要考慮本地主機的 IO 開銷,還需要顧慮到不同主機之間的傳輸開銷。針對這些情況, Spark 就要制定一些機制,來解決數據量巨大開銷的問題。
2 術語解釋
3 Spark IO 機制介紹
3.1 IO 序列化
序列化是將對象轉換為字節流,本質上可以理解為將鏈表存儲的非連續空間的數據存儲轉化為連續空間存儲的數組中。這樣就可以將數據進行流式傳輸或者塊管理。
序列化主要有以下兩個目的:
l 進程間通信:不同節點之間進行數據傳輸;
l 數據持久化存儲到磁盤:本地節點將對象寫入磁盤;
無論是內存或者磁盤中的 RDD 含有的對象存儲,還是節點間的傳輸數據,都需要執行序列化的過程。序列化與反序列化的速度、序列化後的數據大小等都影響數據傳輸的速度,以致影響集群的計算效率。
Spark 通過集中方式實現進程通信,包括 Actor 的消息模式、 Java NIO 和 Netty 的 OIO 。
3.2 IO 壓縮
當大片連續區域進行數據存儲並且存儲區域中數據重複性高的狀況下,數據適合進行壓縮。數組或者對象序列化後的數據塊可以考慮壓縮。所以序列化後的數據可以壓縮,使數據緊縮,減少空間開銷。
壓縮採用了兩種算法: Snappy 和 LZF ,底層分別採用了兩個第三方庫實現,同時可以自定義其它壓縮對 Spark 進行擴展。
Snappy 提供了更高的壓縮速度, LZF 提供了更高的壓縮比。
val conf=sc.getConf
conf.getBoolean( “ spark.broadcast.compress ” ,true)
conf.set( “ spark.broadcast.compress ” ,true)
Sc 是 SparkContext 對象, conf 是 SparkConf 對象。
在分佈式中,序列化和壓縮是兩個重要的手段。
Spark 通過序列化將鏈式分佈的數據轉化為連續分佈的數據,這樣就能夠進行分佈式的進程間數據的通信,或者在內存進行數據壓縮等操作,提升 Spark 的應用性能。通過壓縮,能夠減少數據的內存佔用,以及 IO 和網絡數據傳輸開銷。
3.3 IO 塊管理
RDD 在邏輯上是按照 Partition 分塊的,可以將 RDD 看成是一個分區作為數據項的分佈式數組。物理上存儲的 RDD 是以 Block 為單位的,一個 Partition 對應一個 Block ,用 Partition 的 ID 通過元數據的映射到物理上的 Block ,而這個物理上的 Block 可以存儲在內存,也可以存儲在某個節點的 Spark 的硬盤臨時目錄。
Spark 的 I/O 管理整體分為兩個層次:
1) 、通信層: I/O 模塊也是採用 Master-Slave 結構來實現通信層的架構, Master 和 Slave 之間傳輸控制信息、狀態信息。
2) 、存儲層: Spark 的塊數據需要存儲在內存或者硬盤,有可能還需要傳輸到遠端機器,這些有存儲層完成。
可以通過以下幾個維度來理解整個存儲系統:
1 )、管理和接口:
當其他模塊要與 storage 模塊進行交互時, storage 模塊提供了統一的操作類 BlockManager ,外部類與 storage 模塊打交道都需要調用 BlockManager 相應接口來實現。
2 )、通信層:
BlockManagerMasterActor :在主節點創建,從節點通過這個 Actor 的引用向主節點傳遞消息和狀態。
BlockManagerSlaveActor :在從節點創建,主機點通過這個 Actor 的引用向從節點傳遞命令,控制從節點的塊讀取。
BlockManagerMaster :對 Actor 通信進行管理。
3 )、數據讀寫層:
DiskStore :提供 Block 在磁盤上以文件形式讀寫的功能;
MemoryStore :提供 Block 在內存中的 Block 讀寫功能;
ConnectionManager :提供本地機器和遠端節點進行網絡傳輸 Block 的功能;
BlockManagerWorker :對遠端數據的異步傳輸進行管理。
主節點和從節點之間通過 Actor 傳遞消息來傳遞命令和狀態。
Master 節點負責總體控制, Slave 節點接受命令、彙報狀態。( Actor 和 ref 是 AKKA 中兩個不同的 Actor 引用)。
BlockManager 在內部封裝 BlockManagerMaster ,並通過 BlockManagerMaster 進行通信。 Spark 在各節點創建各自的 BlockManager ,通過 BlockManager 對 storage 模塊進行操作。 Block 對象在 SparkEnv 創建, SparkEnv 相當於線程的上下文變量,在 SparkEnv 也會創建很多的管理組件。
3.4 數據讀寫
數據寫入主要分以下步驟:
1 )、 RDD 調用 compute() 方法進行制定分區的寫入。
2 )、 CacheManager 中調用 BlockManager 判斷數據是否已經寫入,如果未寫入則寫入。
3 )、 BlockManager 中數據與其他節點同步。
4 )、 BlockManager 根據存儲級別寫入制定的存儲層。
5 )、 BlockManager 向主節點彙報存儲狀態。
數據讀取:
在 RDD 類中,通過 compute 方法調用 iterator 讀寫某個分區( Partition ),作為數據讀取的入口。分區是邏輯概念,在物理上是一個 Block 。
在本地同步讀取數據塊,首先看能否在內存讀取數據塊,如果不能讀取,則看能否從 Tacjyon 讀取數據塊,如果仍不能讀取,則看能否從本地磁盤讀取數據。如果仍不存在,再看看網絡中其它節點是否有數據。
內存 Block 塊管理是通過鏈表來實現的,在 DiskStore 中,一個 Block 對應一個文件。
閱讀更多 情報通 的文章