存儲級別簡介
Spark中RDD提供了多種存儲級別,除去使用內存,磁盤等,還有一種是OFF_HEAP,稱之為 使用JVM堆外內存
使用OFF_HEAP的優點:在內存有限時,可以減少頻繁GC及不必要的內存消耗(減少內存的使用),提升程序性能。
Spark內存管理根據版本划分為兩個階段:spark1.6[官網給出spark1.5之前(包含spark1.5)]之前階段、spark1.6之后階段。
1.6.0及以后版本,使用的統一內存管理器,由UnifiedMemoryManager實現。
- ü MemoryManger在spark1.6之前采用靜態內存管理
(StaticMemoryManager[https://github.com/apache/spark/blob/branch-2.4/core/src/main/scala/org/apache/spark/memory/StaticMemoryManager.scala]),
- ü Spark1.6之后默認為統一內存管理
(UnifiedMemoryManager[https://github.com/apache/spark/blob/branch-2.4/core/src/main/scala/org/apache/spark/memory/UnifiedMemoryManager.scala])統一內存管理模塊包括了堆內內存(On-heap Memory)和堆外內存(Off-heap Memory)兩大區域
從1.6.0版本開始,Spark內存管理模型發生了變化。舊的內存管理模型由StaticMemoryManager類實現,現在稱為“legacy(遺留)”。默認情況下,“Legacy”模式被禁用,這意味着在Spark 1.5.x和1.6.0上運行相同的代碼會導致不同的行為。
為了兼容,您可以使用spark.memory.useLegacyMode參數(目前spark2.4版本中也依然保留這個靜態內存管理模型)啟用“舊”內存模型:
spark.memory.useLegacyMode=true(默認為false)
該參數官網給出的解釋:
Whether to enable the legacy memory management mode used in Spark 1.5 and before. The legacy mode rigidly partitions the heap space into fixed-size regions, potentially leading to excessive spilling if the application was not tuned. The following deprecated memory fraction configurations are not read unless this is enabled:
spark.shuffle.memoryFraction
spark.storage.memoryFraction
spark.storage.unrollFraction
在Spark1.x以前,默認的off_heap使用的是Tachyon。但是Spark中默認操作Tachyon的TachyonBlockManager開發完成之后,代碼就不再更新。當Tachyon升級為Alluxio之后移除不使用的API,導致Spark默認off_heap不可用(spark1.6+)。
錯誤情況可參考:https://alluxio.atlassian.net/browse/ALLUXIO-1881
Spark2.0的OFF_HEAP
從spark2.0開始,移除默認的TachyonBlockManager以及ExternalBlockManager相關的API。
移除情況可參考:https://issues.apache.org/jira/browse/SPARK-12667。
但是在Spark2.x的版本中,OFF_HEAP這一存儲級別,依然存在:
那么,這里的OFF_HEAD 數據是如何存儲的呢?
在org.apache.spark.memory中,有一個MemoryMode,MemoryMode標記了是使用ON_HEAP還是OFF_HEAP。
在org.apache.spark.storage.memory.MemoryStore中,根據MemoryMode類型來調用不同的存儲。
在MemoryStore中putIteratorAsBytes方法,是用於存儲數據的方法。
其實真正管理(存儲)values的對象是valuesHolder,valueHolder是SerializedValuesHolder的類對象,我們看下SerializedValuesHolder是怎么定義的。
在該方法中,OFF_HEAP使用的是org.apache.spark.unsafe.Platform(https://github.com/apache/spark/blob/master/common/unsafe/src/main/java/org/apache/spark/unsafe/Platform.java)來做底層存儲的,Platform是利用java unsafe API實現的一個訪問off_heap的類,所以,spark2.x的OFF_HEAP就是利用java unsafe API實現的內存管理。
Spark2.x OFF_HEAP優勢:
- ü 優點:在內存有限時,可以減少頻繁GC及不必要的內存消耗(減少內存的使用,),提升程序性能。
- ü 缺點:沒有數據備份,也不能像alluxio那樣保證數據高可用,丟失數據則需要重新計算。
參考
《Spark2.x 內存管理之---OFF_HEAP https://blog.csdn.net/qq_21439395/article/details/80773121》
- 關於 java unsafe API 可參考:
《Java中Unsafe類詳解 https://www.cnblogs.com/mickole/articles/3757278.html 》
《JAVA並發編程學習筆記之Unsafe類 https://blog.csdn.net/aesop_wubo/article/details/7537278》