基于Alluxio系统的Spark DataFrame高效存储管理技术
介紹
越來越多的公司和組織開始將Alluxio和Spark一起部署從而簡化數(shù)據(jù)管理,提升數(shù)據(jù)訪問性能。Qunar最近將Alluxio部署在他們的生產(chǎn)環(huán)境中,從而將Spark streaming作業(yè)的平均性能提升了15倍,峰值甚至達(dá)到300倍左右。在未使用Alluxio之前,他們發(fā)現(xiàn)生產(chǎn)環(huán)境中的一些Spark作業(yè)會(huì)變慢甚至無法完成。而在采用Alluxio后這些作業(yè)可以很快地完成。在這篇文章中,我們將介紹如何使用Alluxio幫助Spark變得更高效,具體地,我們將展示如何使用Alluxio高效存儲(chǔ)Spark DataFrame。
Alluxio和Spark緩存
用戶使用Alluxio存儲(chǔ)Spark DataFrame非常簡單:通過Spark DataFrame write API將DataFrame作為一個(gè)文件寫入Alluxio。通常的做法是使用df.write.parquet()將DataFrame寫成parquet文件。在DataFrame對應(yīng)的parquet文件被寫入Alluxio后,在Spark中可以使用sqlContext.read.parquet()讀取。為了分析理解使用Alluxio存儲(chǔ)DataFrame和使用Spark內(nèi)置緩存存儲(chǔ)DataFrame在性能上差異,我們進(jìn)行了如下的一些實(shí)驗(yàn)。
實(shí)驗(yàn)相關(guān)設(shè)置如下:
硬件配置:單個(gè)worker安裝在一個(gè)節(jié)點(diǎn)上,節(jié)點(diǎn)配置:61 GB內(nèi)存 + 8核CPU;
軟件版本:Spark 2.0.0和Alluxio1.2.0,參數(shù)均為缺省配置;
運(yùn)行方式:以standalone模式運(yùn)行Spark和Alluxio。
在本次實(shí)驗(yàn)中,我們使用Spark內(nèi)置的不同緩存級別存儲(chǔ)DataFrame對比測試使用Alluxio存儲(chǔ)DataFrame,然后收集分析性能測試結(jié)果。同時(shí)通過改變DataFrame的大小來展示存儲(chǔ)的DataFrame的規(guī)模對性能的影響。
存儲(chǔ)DataFrame
Spark DataFrame可以使用persist() API存儲(chǔ)到Spark緩存中。persist()可以緩存DataFrame數(shù)據(jù)到不同的存儲(chǔ)媒介。
本次實(shí)驗(yàn)使用了以下Spark緩存存儲(chǔ)級別(StorageLevel):
MEMORY_ONLY:在Spark JVM內(nèi)存中存儲(chǔ)DataFrame對象
MEMORY_ONLY_SER:在Spark JVM內(nèi)存中存儲(chǔ)序列化后的DataFrame對象
DISK_ONLY: 將DataFrame數(shù)據(jù)存儲(chǔ)在本地磁盤
下面是一個(gè)如何使用persist() API緩存DataFrame的例子:
df.persist(MEMORY_ONLY)將DataFrame保存在內(nèi)存中的另一種方法是將DataFrame作為一個(gè)文件寫入Alluxio。Spark支持將DataFrame寫成多種不同的文件格式,在本次實(shí)驗(yàn)中,我們將DataFrame寫成parquet文件。
下面是一個(gè)將DataFrame寫入Alluxio的例子:
查詢存儲(chǔ)在Alluxio上的DataFrame
DataFrame被保存后(無論存儲(chǔ)在Spark內(nèi)存還是Alluxio中),應(yīng)用可以讀取DataFrame以進(jìn)行后續(xù)的計(jì)算任務(wù)。本次實(shí)驗(yàn)中,我們創(chuàng)建了一個(gè)包含2列的DataFrame(這2列的數(shù)據(jù)類型均為浮點(diǎn)型),計(jì)算任務(wù)則是分別計(jì)算這2列數(shù)據(jù)之和。
當(dāng)DataFrame存儲(chǔ)在Alluxio時(shí),Spark讀取DataFrame就像從Alluxio中讀取文件一樣簡單。下面是一個(gè)從Alluxio中讀取DataFrame的例子:
df = sqlContext.read.parquet(alluxioFile) df.agg(sum("s1"), sum("s2")).show()我們分別從Alluxio中 parquet文件以及各種Spark存儲(chǔ)級別緩存中讀取DataFrame,并進(jìn)行上述的聚合計(jì)算操作。下圖顯示了不同存儲(chǔ)方案中的聚合操作的完成時(shí)間。
從上圖可以看出,從Alluxio中讀取DataFrame進(jìn)行聚合操作具有比較穩(wěn)定的執(zhí)行性能。對于從Spark緩存中讀取DataFrame,在DataFrame規(guī)模較小時(shí)執(zhí)行性能具有一定優(yōu)勢,但是隨著DataFrame規(guī)模的增長,性能急劇下降。在本文的實(shí)驗(yàn)環(huán)境中,對于各種Spark內(nèi)置的存儲(chǔ)級別, DataFrame規(guī)模達(dá)到20 GB以后,聚合操作的性能下降比較明顯。
另一方面,相比使用Spark內(nèi)置緩存,使用Alluxio存儲(chǔ)DataFrame并進(jìn)行聚合操作,其性能在小規(guī)模數(shù)據(jù)上略有劣勢。然而,隨著DataFrame數(shù)據(jù)規(guī)模的增長,從Alluxio中讀取DataFrame性能更好,因?yàn)閺腁lluxio中讀取DataFrame的耗時(shí)幾乎始終隨著數(shù)據(jù)規(guī)模線性增長。由于使用Alluxio存儲(chǔ)DataFrame的讀寫性能具有較好的線性可擴(kuò)展性,上層應(yīng)用可以穩(wěn)定地以內(nèi)存速度處理更大規(guī)模的數(shù)據(jù)。
使用Alluxio共享存儲(chǔ)的DataFrame
使用Alluxio存儲(chǔ)DataFrame的另一大優(yōu)勢是可以在不同Spark應(yīng)用或作業(yè)之間共享存儲(chǔ)在Alluxio中的數(shù)據(jù)。當(dāng)一個(gè)DataFrame文件被寫入Alluxio后,它可以被不同的作業(yè)、SparkContext、甚至不同的計(jì)算框架共享。因此,如果一個(gè)存儲(chǔ)在Alluxio中的DataFrame被多個(gè)應(yīng)用頻繁地訪問,那么所有的應(yīng)用均可以從Alluxio內(nèi)存中直接讀取數(shù)據(jù),并不需要重新計(jì)算或者從另外的底層外部數(shù)據(jù)源中讀取數(shù)據(jù)。
為了驗(yàn)證采用Alluxio共享內(nèi)存的優(yōu)勢,我們在如上述的同樣的實(shí)驗(yàn)環(huán)境中進(jìn)行相同規(guī)模的DataFrame聚合操作。當(dāng)使用50 GB規(guī)模的DataFrame時(shí),我們在單個(gè)Spark應(yīng)用中進(jìn)行聚合操作,并且記錄該聚合操作的耗時(shí)。沒有使用Alluxio時(shí),Spark應(yīng)用需要每次都從數(shù)據(jù)源讀取數(shù)據(jù)(在本次實(shí)驗(yàn)中是一個(gè)本地SSD)。在使用Alluxio時(shí),數(shù)據(jù)可以直接從Alluxio內(nèi)存中讀取。下圖顯示了2次聚合操作的完成時(shí)間性能對比。使用Alluxio的情況下,聚合操作快了約2.5倍。
在上圖的實(shí)驗(yàn)中,數(shù)據(jù)源是本地SSD。如果DataFrame來自訪問起來更慢或不穩(wěn)定的數(shù)據(jù)源,Alluxio的優(yōu)勢就更加明顯了。舉例而言,下圖是DataFrame數(shù)據(jù)源由本地SSD替換為某公有云存儲(chǔ)的實(shí)驗(yàn)結(jié)果。
這張圖顯示是執(zhí)行7次聚合操作的平均完成時(shí)間。圖中的紅色的誤差范圍(error bar)代表完成時(shí)間的最大和最小范圍。這些結(jié)果清晰地顯示出Alluxio可以顯著提升操作的平均性能。這是因?yàn)槭褂肁lluxio緩存DataFrame時(shí),Spark可以直接從Alluxio內(nèi)存中讀取DataFrame,而不是從遠(yuǎn)程的公有云存儲(chǔ)中。平均而言,Alluxio可以加速上述DataFrame的聚集操作性能超過10倍。
另一方面,由于數(shù)據(jù)源是公有云系統(tǒng),Spark必須跨網(wǎng)絡(luò)遠(yuǎn)程讀取數(shù)據(jù)。錯(cuò)綜復(fù)雜的網(wǎng)絡(luò)狀況會(huì)導(dǎo)致讀取性能難以預(yù)測。這種性能的不穩(wěn)定性從上圖中的誤差范圍(error bar)可以很明顯地看出。在不使用Alluxio的情況下,Spark作業(yè)的完成時(shí)間變化范圍超過1100秒。當(dāng)使用Alluxio之后,完成時(shí)間的變化范圍只有10秒。在本實(shí)驗(yàn)中,Alluxio能夠?qū)?shù)據(jù)讀取造成的不穩(wěn)定性降低超過100倍。
由于共有云存儲(chǔ)系統(tǒng)的網(wǎng)絡(luò)訪問性能不可預(yù)測性,最慢的Spark作業(yè)執(zhí)行時(shí)間超過1700秒, 比平均慢2倍。然而,當(dāng)使用Alluxio時(shí),最慢的Spark作業(yè)執(zhí)行時(shí)間大約比平均時(shí)間只慢6秒。因此,如果以最慢的Spark作業(yè)執(zhí)行時(shí)間來評估,Alluxio可以加速DataFrame聚合操作超過17倍。
結(jié)論
Alluxio可以在多個(gè)方面幫助Spark變得更高效。這篇文章介紹了如何使用Alluxio存儲(chǔ)Spark DataFrame,并且實(shí)驗(yàn)驗(yàn)證了采用Alluxio帶來的優(yōu)勢:
Alluxio可以直接在內(nèi)存中保存大規(guī)模的數(shù)據(jù)來加速Spark應(yīng)用;
Alluxio能夠在多個(gè)Spark應(yīng)用之間快速共享存儲(chǔ)在內(nèi)存中的數(shù)據(jù);
Alluxio可以提供穩(wěn)定和可預(yù)測的數(shù)據(jù)訪問性能。
?
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的基于Alluxio系统的Spark DataFrame高效存储管理技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10个你应该了解的Git命令(以及Git
- 下一篇: 在闲鱼,我们如何用Dart做高效后端开发