Spark與緩存
預期成果
1.1 當前問題
當前以圖搜圖應用存在的問題:
- 當前使用spark RDD方案無法達到數據實時加載(每10分鐘加載一次,雖然可配,但太短可能會有問題)
- Spark RDD內存會被分為兩部分,一部分用來緩存數據一部分用來計算,Spark默認配置只有差不多50%的內存用於緩存(也就是說executor配了100G,只有50多G可以被用來做緩存),雖然比例可以進行配置,但增加緩存內存比例後,是否會影響計算性能有待測試。
- 當前數據全緩存到spark jvm內存中,GC時間較長會導致影響計算性能
- 當前加載的RDD只有自身context才能使用,無法做到應用間共享
- 當driver端服務宕掉後,緩存的數據也會丟失
- 期望能將增量數據加載時間縮小到足夠小達到準實時,或者直接能夠達到實時
- 職責分明,緩存有分布式緩存做,Spark只負責計算
- 緩存數據不占用Spark jvm內存,減少GC對計算的影響
- 加載到內存的數據可以被其他應用使用
- Driver端服務宕掉後,緩存數據不會丟失,其他driver段仍可使用
- 采用新方案對比原方案,性能損耗盡可能小,最好達到無損耗
1.2 預期成果
2 技術選型
根據上述問題和預期成果,期望選擇一款與Spark結合較好的分布式內存緩存計算,從而將緩存工作從spark中抽離出來,讓spark專註於計算。
2.1.1 Apache Ignite
Apache Ignite內存數據組織是高性能的、集成化的以及分布式的內存平臺,他可以實時地在大數據集中執行事務和計算,和傳統的基於磁盤或者閃存的技術相比,性能有數量級的提升。
選擇預研該技術最大的原因為,Ignite實現了一個可共享的Spark RDD,可實現增量數據實時在比對中體現。
2.1.2 Alluxio(原Tachyon)
Alluxio在1.0版本後由原來的Tcahyon更名。Alluxio與Spark結合較好,Spark1.5後增加的緩存方式:OFF_HEAP(堆外緩存)當前只支持tachyon。
不過Alluxio和Spark RDD一樣都不可變,緩存文件一旦寫入就不能修改,且在完成寫入之前緩存數據是無法讀取的,這樣就服務達到增量數據的實時性,但可以實現盡可能縮短增量加載時間來達到準實時性。
3 階段性結論
性能測試采用上述兩種技術三個版本(apache-ignite-fabric-1.5.0.final、alluxio-1.0.1、tachyon-0.7.1-hadoop2.6-build)八種方案:
- 直接采用Spark RDD緩存,且緩存數據不做序列化
- 直接采用Spark RDD緩存,緩存數據使用java序列化方式
- 直接采用Spark RDD緩存,緩存數據使用kryo序列化方式
- 采用Spark RDD OFF_HEAP模式(即緩存數據到tachyon),緩存數據使用java序列化方式
- 采用Spark RDD OFF_HEAP模式(即緩存數據到tachyon),緩存數據使用kryo序列化方式
- 使用tachyon緩存數據(調用saveAsObjectFile,直接將數據序列化成文件寫到tachyon中),saveAsObjectFile使用java序列化方式
- 使用Alluxio緩存數據(調用saveAsObjectFile,直接將數據序列化成文件寫到Alluxio中),saveAsObjectFile使用java序列化方式
- 使用ignite緩存數據,使用IgniteRDD進行統計
下面為三臺256G內存集群,58727000條數據,Spark分配36核,測試結果如下:
緩存方式 |
內存配置 |
是否序列化 |
序列化實現 |
檢索耗時(s) |
內存空間(GB) |
Spark RDD |
executor:150GB*3 |
否 |
|
11.527 |
112.8 |
Spark RDD |
executor:150GB*3 |
是 |
java |
20.09 |
56.4 |
Spark RDD |
executor:150GB*3 |
是 |
kryo |
16.275 |
51.8 |
Spark RDD + tachyon |
executor:20GB*3 tachyon:100GB*3 |
是 |
java |
21.771 |
51.56 |
Spark RDD + tachyon |
executor:20GB*3 tachyon:100GB*3 |
是 |
kryo |
17.772 |
51.83 |
tachyon |
executor:20GB*3 tachyon:100GB*3 |
是 |
java |
32.719 |
53.03 |
Alluxio |
executor:20GB*3 alluxio:100GB*3 |
是 |
java |
26.988 |
53.03 |
ignite |
executor:20GB*3 ignite:10GB*3(數據保存在堆外,不使用jvm內存) |
是 |
java |
333.228 |
|
由上表分析如下:
- 檢索耗時最短為方案一,直接緩存到spark jvm中且不做序列化,但該方案占用內存也較多(目前是其他方案的兩倍),不過當前以圖搜圖框架中數據結構采用map,所以較占內存
- 方案一、二、三對比,采用序列化會有性能損耗,kryo序列化耗時是java序列化的1/2,與之前測試基本一致,采用kryo序列化112GB數據耗時4-5秒
- 對比方案二、方案四以及方案三、方案五,從tachyon拉數據到spark進行計算耗時為1秒左右,但由於存儲到tachyon必須序列化,所以得加上序列化的耗時,最少的性能損耗也差不多5-6秒
- 直接調用saveAsObjectFile保存數據到tachyon或者Alluxio,性能損耗較大,分別為22秒和14秒,初步估計性能損耗由於:(1)saveAsObjectFile采用java序列化方式,性能損耗將近9秒;(2)saveAsObjectFile內部實現使用的是hadoop api,tachyon能夠兼容這些api,但可能有部分性能損耗;(3)spark可能對tachyon存儲做過一定優化
- 由表格可以看出ignite結合spark性能很差,估計原因可能為:(1)可能修改某些配置後可以優化性能,但iginte資料非常少,特別是跟spark結合這塊,基本沒有什麽資料;(2)ignite本身不單單包含存儲功能,還有檢索、計算等功能,所以它與spark本身也存在競爭關系
結論如下:
- ignite如需優化性能需要深入源碼,且沒有對比數據,具體最後能到什麽程度無法預估,且當前基本沒有什麽已知公司使用該技術與Spark結合
Alluxio(Tachyon)性能優化需要看Spark緩存代碼,但是該方法最終能夠達到的性能指標基本能夠預估(較現有方案有5-6秒的損耗,但內存消耗可能會有所減少)
Spark與緩存