关于tuning Spark的内容总结

本文有关***tuning spark***的内容总结,主要包括以下内容

  • Data 序列化
  • Memory Tuning
  • 影响调优的其它因素
  • 总结

由于大多数spark运算都是基于内存进行的,因此集群中的任何资源(CPU、网络带宽和内存)都会成为制约和影响spark程序运行和因素和瓶颈。更多情况是,如果数据与内存相匹配,就是内存够存我们的数据,那么此时的瓶颈就是网络带宽。但是有时我们也需要考虑一些调优,例如将RDD以序列化的形式存储,这样可以减少内存使用。

第一部分:数据序列化(Data Serialization)
众所周知,序列化在分成式应用中扮演十分重要的角色。然而,将对象序列化慢,也会消耗大量的字节,这会大大地降低运行速度。所以,这是我们优化Spark应用程序首先应该想到的方面。Spark为了在方便使用和性能上达到平衡,它提供两种序列化库。
1.1 Java 序列化
默认情况下,Spark 序列化对象用的是Java的ObjectOutputStream framework, 我们不但可以使用任何我们创建的类实现java.io.Serializable,而且也可以通过继承 java.io.Externalizable来控制序列化的性能。java序列化十分灵活但是相当慢,并且会产生许多针对大量类的序列化方法?
1.2 Kryo 序列化
Spark也可以使用Kryo将对象序列化,而且更快。Kryo序列化比Java序列化快很多(通常是快10的数量级),但是不支持所有的序列化类型而且需要我们要程序中要序列化的类提前注册才能达到最优性能。

第二部分:内存调优(Memory Tuning)
2.0 Memory Management Overview
在Spark中的内存使用很大程度上包含execution和storage内存。执行内存指的是用于shuffles,joins,sorts和aggregations过程的运算内存;而存储内存(StorageMemory)指的是用于缓存和聚合集群中的数据。在Spark中,执行内存和存储内存共享一个统一内存(M).当没有执行内存被使用时,存储内存会获得全部可以获得的内存,相反亦然。执行内存会占掉全部统一内存在必要的情况下,而这种情况的发生只有发生在总的存储内存小于一定的threshold的时候。换一句话说,Threshold是unified region的一部分。存储内存是不会’抢夺’执行内存的,是因为其中的实现过程是十分复杂的。这种设计保证了以下几个比较理想的特性:
(1)第一、不使用缓存的应用程序会使用execution的所有空间,从而避免不必要的磁盘溢出;
(2)第二、使用缓存的应用能够重新serve和保证最小的存储内存当他们的数据块存储空间容易被占据的时候;
(3)第三、这种设计为各种workloads提供合理的out-of-the-box性能,而这样的过程不需要考虑用户的如何分配内存。
虽然,这其中涉及两个相关联的配置,特别地,我们可以不去而且没有必要调整它们因为默认值对于大多数情况是够用的。

`spark.memory.storageFraction` expresses the size of R as a fraction of M (default 0.5). R is the storage space within M where cached blocks immune to being evicted by execution.
The value of spark.memory.fraction should be set in order to fit this amount of heap space comfortably within the JVM’s old or “tenured” generation. See the discussion of advanced GC tuning below for details.```

***2.1 Determining Memory Consumption***
量化一个数据集的内存消耗的最佳方法是需要创建一个RDD,并将它存入缓存,然后在WebUI 的“Storage”页面上观察。我们会得到所创建的RDD所占的内存。`除此之外`,估算一个特定对象的内存消耗,我们可使用`SizeEstimator`的估算方法。它不但对不同的数据的分布(`优化内存使用`)十分有用,而且对于确定`广播变量`在每个executor heap中所占空间的数量也是有益的!!

***2.2 Tuning Data Structures***
减少内存消耗的第一个方法是避免使用基于指针的数据结构和封装对象。有以下方法可供参考:
(a) 设计数据结构优先考虑对象数组和基本数据类型,而不是标准的Java或者Scala集合类。
(b) 尽可能避免用大量的对象和指针嵌套数据结构,而应该考虑用数字型ID或者枚举对象代替字符串表示keys的数量类型。

***2.3 Serialized RDD Storage***

当我们的对象十分大而且高效存储时,一个非常简单减少内存使用的方法是将对象序列化后存储。这个过程可以使用RDD persistence API中的StorageLevels,例如:`MEMORY_ONLY_SER.`。Spark 将每个RDD分区作为字节数组来存储。唯一不足的是十分缓慢的访问时间,因为需要对每一个对象`反序列化`在频繁的运算中。因些强烈推荐用Kryo序列化如果我们需要以序列化的形式缓存数据。


未完待续.........



猜你喜欢

转载自blog.csdn.net/qq_24990561/article/details/85197051