天天看點

《Spark大資料分析:核心概念、技術及實踐》一3.7 緩存

 本節書摘來自華章出版社《spark大資料分析:核心概念、技術及實踐》一書中的第3章,第3.7節,作者[美] 穆罕默德·古勒(mohammed guller),更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

3.7 緩存

除了将資料駐留在記憶體中以外,緩存在rdd中也扮演了另外一個重要的角色。就像之前所說的,建立rdd有兩種方式,從存儲系統中讀取資料或者應用其他現存rdd的轉換操作。預設情況下,當一個rdd的操作方法被調用時,spark會根據它的父rdd來建立這個rdd,這有可能導緻父rdd的建立。如此往複,這個過程一直持續到spark找到根rdd,而後spark通過從過存儲系統讀取資料的方式建立根rdd。操作方法被調用一次,上面說的過程就會執行一遍。每次調用操作方法,spark都會周遊這個調用者rdd的血統樹,執行所有的轉換操作來建立它。

考慮下面的例子。

《Spark大資料分析:核心概念、技術及實踐》一3.7 緩存

盡管上面的代碼隻調用了一次textfile方法,但是日志檔案會被從硬碟中讀取兩次。這是因為調用了兩次操作方法count。在調用errorlogs.count時,日志檔案第一次被讀取,調用warninglogs.count時,日志檔案被再次讀取。這隻是個簡單的例子,現實世界中的應用會有更多的各種轉換和操作。

如果一個rdd緩存了,spark會執行到目前為止的所有轉換操作并為這個rdd建立一個檢查點。具體來說,這隻會在第一次在一個緩存的rdd上調用某操作的時候發生。類似于轉換方法,緩存方法也是惰性的。

如果一個應用緩存了rdd,spark并不是立即執行計算并把它存儲在記憶體中。spark隻有在第一次在緩存的rdd上調用某操作的時候才會将rdd物化在記憶體中。而且這第一次操作并不會從中受益,後續的操作才會從緩存中受益。因為它們不需要再執行從存儲系統中讀取資料開始的一系列操作。它們通常都運作得快多了。還有,那些隻使用一次資料的應用使用緩存也不會有任何好處。隻有那些需要對同樣資料做多次疊代的應用才能從緩存中受益。

如果一個應用把rdd緩存在記憶體中,spark實際上是把它存儲在每個worker節點上執行者的記憶體中了。每個執行者把它所計算的rdd分區緩存在記憶體中。

3.7.1 rdd的緩存方法

rdd類提供了兩種緩存方法:cache和persist。

cache

cache方法把rdd存儲在叢集中執行者的記憶體中。它實際上是将rdd物化在記憶體中。

下面的例子展示了怎麼利用緩存優化上面的例子。

《Spark大資料分析:核心概念、技術及實踐》一3.7 緩存

persist

persist是一個通用版的cache方法。它把rdd存儲在記憶體中或者硬碟上或者二者皆有。它的輸入參數是存儲等級,這是一個可選參數。如果調用persist方法而沒有提供參數,那麼它的行為類似于cache方法。

《Spark大資料分析:核心概念、技術及實踐》一3.7 緩存

persist方法支援下列常見的存儲選項。

memory_only:當一個應用把 memory_only作為參數調用persist方法時,spark會将rdd分區采用反序列化java對象的方式存儲在worker節點的記憶體中。如果一個rdd分區無法完全載入worker節點的記憶體中,那麼它将在需要時才計算。

《Spark大資料分析:核心概念、技術及實踐》一3.7 緩存

disk_only:如果把disk_only作為參數調用persist方法,spark會物化rdd分區,把它們存儲在每一個worker節點的本地檔案系統中。這個參數可以用于緩存中間的rdd,這樣接下來的一系列操作就沒必要從根rdd開始計算了。

memory_and_disk:這種情況下,spark會盡可能地把rdd分區存儲在記憶體中,如果有剩餘,就把剩餘的分區存儲在硬碟上。

memory_only_ser:這種情況下,spark會采用序列化java對象的方式将rdd分區存儲在記憶體中。一個序列化的java對象會消耗更少的記憶體,但是讀取是cpu密集型的操作。這個參數是在記憶體消耗和cpu使用之間做的一個妥協。

memory_and_disk_ser:spark會盡可能地以序列化java對象的方式将rdd分區存儲在記憶體中。如果有剩餘,則剩餘的分區會存儲在硬碟上。

3.7.2 rdd緩存是可容錯的

在分布式環境中可容錯性是相當重要的。之前我們就已經知道了當節點出故障的時候spark是怎麼自動把計算作業轉移到其他節點的。spark的rdd機制同樣也是可容錯的。

即使一個緩存rdd的節點出故障了,spark應用也不會崩潰。spark會在另外節點上自動重新建立、緩存出故障的節點中存儲的分區。spark利用rdd的血統資訊來重新計算丢失的緩存分區。

3.7.3 緩存記憶體管理

spark采用lru算法來自動管理緩存占用的記憶體。隻有在必要時,spark才會從緩存占用的記憶體中移除老的rdd分區。而且,rdd還提供了名為unpersist的方法。應用可以調用這個方法來從緩存占用的記憶體中手動移除rdd分區。