关于Spark实际操作的一些实用干货(持续更新中.....)
1.有关local模式
曾经在国外网站上看到一篇帖子,觉着很受用,拿来分享。
说Spark的local模式,就是指在本机上运行的本机模式,所以,有关于你设置的executor.memory以及driver.memory的,并不会影响Spark本身内存设置问题。经本人测试之后发现,local模式下设置这两个参数完全没有作用。
2.spark.memory.fraction与spark.storage.memoryFraction
内存占比,用于对Spark性能进行调优,官方文档上就有介绍:
-
spark.memory.fraction
expresses the size ofM
as a fraction of the (JVM heap space - 300MB) (default 0.6). The rest of the space (25%) is reserved for user data structures, internal metadata in Spark, and safeguarding against OOM errors in the case of sparse and unusually large records. -
spark.memory.storageFraction
expresses the size ofR
as a fraction ofM
(default 0.5).R
is the storage space withinM
where cached blocks immune to being evicted by execution.
spark.memory.fraction(暂称之为M)表示:片段M的大小是(JVM堆空间- 300MB)(默认为0.6)的一部分。其余的空间(25%)保留给用户数据结构、Spark中的内部元数据以及在稀疏和异常大的情况下防止OOM错误。
spark.storage.memoryFraction(暂称之为M.R):表示R的大小为M的一部分(默认为0.5)。R是M中的存储空间,其中缓存的块不会被执行逐出
这也就是为什么明明设置内存大小为比如20G(-Xmx即最大允许堆内存决定了内存大小),而Spark会报出一下信息:
18/06/14 16:01:42 INFO MemoryStore: MemoryStore started with capacity 10.5 GB
3.-Xms -Xmx及-XX:PermSize -XX:MaxPermSize参数设置
首先,参数建议设置为:
-Xms 物理内存的1/64
-Xmx 物理内存的1/4
-XX:PermSize 物理内存的1/64
-XX:MaxPermSize 物理内存的1/4
其次是Java的GC(Garbage Collection),所设置初始堆内存大小-Xms,当内存使用达到这个值的时候,GC才开始回收垃圾,意味着如果将-Xms与-Xmx设置大小相同的话,只有当内存耗尽时才会进行GC回收。
4.RDD通过collect转数组
RDD类型的数据可以通过collect方法转化为数组,但由于collect方法属于对RDD操作中的Action操作,根据RDD的惰性机制可知,多一次Action操作就会多一次shuffle,而一次shuffle操作的结果一次调度stage的结果,然而一次stage又包含许多个Task,最终会导致程序运行耗时增加。
另外,RDD通过collect,将原有分布在各个executor进程的数据全部汇集到一个driver节点上,这个操作的实质是把分布式的环境拉出来做单机处理了,所以后续对collect而来的数据来说,已经脱离了Spark的分布式环境。
再者,将所有数据聚集到一个driver节点,容易产生内存溢出是可想而知的。
5.RDD与JavaRDD
本人曾在Java环境下用RDD做map等操作,结果发现Java环境下使用map与Scala环境下使用map并不很一样。比如:
data.map(it => {it +=1})),而Java中做同样的map则需要data.map(Function<T, U> f, ClassTag<U> evidence$3);
本以为是Scala中scala.reflect.ClassTag类相关部分自己设置出了问题,找了半天Scala官方api也没搞明白问题出在哪,后来尝试用JavaRDD进行同样的操作,问题解决。
具体方法就是导入org.apache.spark.api.java.JavaRDD,并调用toJavaRDD方法data.toJavaRDD();然后进行map等操作即可。