• spark学习(三)--内存管理和性能调优


    (一)内存管理

    内存管理指的是executor的内存管理。

    1. 内存分类--堆内存和堆外内存

    内存分类分为 堆内存和堆外内存。堆内存分为存储storage内存、execution运算内存、other内存。比例是622

    堆内存:Executor内存管理是建立在JVM内存管理之上的。JVM内存就是堆(on-heap)内存。SparkJVM内存做了更加详细的划分,以充分利用堆内存。

    堆外内存:spark还引入了堆外(off-heap)内存,直接在工作节点的系统内存中开辟空间。可以减少节省堆内存

    堆内存是受JVM统一管理。Gc释放内存。堆外内存是直接向节点的操作系统申请和释放。主动申请和主动释放。换句话说。堆外内存我们可以完全控制申请、使用和释放的节奏。

    堆内存是spark释放之后,等待JVMGC。所以,spark释放后,可能仍然没有释放。而spark认为已经释放了。所以,堆内存可能实际的内存大小小于预估的内存大小。

     

    存储内存storage缓存RDD和广播Broadcast所占用的内存

    执行内存execution存储执行shuffle中的中间数据

    Other内存用户定义的数据结构或spark内部的元数据

    2. 内存空间分配

    (1) 静态内存管理

    存储内存、执行内存和其它内存的大小在spark的运行过程中是固定的。6-2-2

     

    堆外内存的统计是准确的。无需预留空间。

     

    (2) 统一内存管理

    存储内存和执行内存公享同一块空间。可以动态的占用对方的空闲区域。

     

    3. 存储内存管理

    RDD 有血缘依赖,RDD的转换是惰性的,只有在Action操作的时候才会被触发。所以,如果一个RDD被多次使用,没有缓存的话,就需要多次根据血缘关系加载,重复计算。因此,就需要对多次重复计算的RDD,第一次运行cache或者persist方法,在缓存中持久化这个RDD

    CachePersist的区别:cache 是存储级别为MEMORY_ONELYPersist

    4. 执行内存管理
    5. 广播变量、累加器

    广播变量广播变量允许编程者在每个Executor上保留外部数据的只读变量,而不是给每个任务发送一个副本。广播变量是每个executor一份。一个executor的所有task共享一份只读变量。

    累加器:累加器是存在driver端,只允许被相关操作累加的变量。Spark提供多个节点对一个共享变量进行共享型的操作。

    (二)SPARK 性能调优

    1. 常规性能优化
    (1) 最优资源配置:

    根据环境的资源情况,尽可能多的使用资源。

    (2) RDD优化

    ① 不同分支,相同运算避免RDD的重复计算RDD不同分支的相同运算尽量在父RDD中一次计算。类似面向对象中,子类相同的方法应该向上转移到父类中去。

    ② 相同分支,多次运算。增加持久化:对多次计算的RDD添加缓存。持久化到内存。

    ③ RDD尽早做Filter:和优化sql类似,优先减少操作的数据集。

    (3) 并行度调节

    并行度指的是各个stageTask的数量。并行度的合理设置是需要和资源匹配的。Task应该是executorcore的倍数。一般推荐的是。Task的数量是core2-3倍。

    (4) 使用广播变量

        如果task需要使用外部变量,每个task都回备份一份数据。造成资源浪费。可以使用广播这些外部变量。每个executor保存一份。每个task使用自己所在executor的变量。

    2. 算子调优
    (1) mapPartitions

    MapmapPartitions 的区别:map函数会对每条数据进行遍历读取。MapPartitions 会一个分区数据一次取全部,然后在内存中处理。

    MapPartitions一次加载,容易造成OOM

    (2) foreachPartition

    ForeachPartition 一般用在数据写入数据库。使用foreachPartition可以经每次操作公用的操作放在foreachPartition中。比如:数据库连接,可以每个分区做一次连接。而不需要每条数据做一次连接。

    (3) filtercoalesce的配合使用

    假设原始数据分配均匀。通过filter之后(不同分区可能过滤掉的数据大小不一),数据量上有倾斜。可以通过coaleasce或者 repartition重新分区。

    (4) repartition解决SparkSQL低并行度问题

    Spark Sql 加载原始文件成RDD的分区数 是原始分区数。可能和当前spark的资源数不匹配。这是大概率事件。所以,需要通过reparttition函数对其重分区。让并行度和资源数匹配。

    (5) reduceByKey本地聚合

    ReduceByKey 会在map端会先对本地的数据进行combine操作,然后将数据写入给下个stage的每个task创建的文件中。增加数据的聚合程度,较少数据量,从而提高效率。

    3. shuffle调优
    (1) 调节map端缓冲区大小

    调节map端缓冲区大小。可以减少数据溢写的小文件个数。较少IO,从而调高效率。

    (2) 调整reduce端拉去缓冲区大小

    Reduce端缓冲区大小调整,可以影响到拉去数据的次数。较少网络传输的次数,从而提高效率。

    (3) 调整reduce拉取数据间隔等待时间

    适当调整reduce拉取数据间隔的等待时间

    4. 数据倾斜
    (1) Reduce join map join

    大小表Join。小表小于12M,对小表采用broadcast。将小表数据转成外部变量数据。通过广播变量到每个executor上。在map阶段就可以进行join。从而从根本上避免了shuffle

    (2) 对个别key对应数据量大的问题

    可以将rdd通过过滤分为两个子rdd。分别处理之后,再合并。场景:[工作中,通常keynull或者”” ,在repatitions 的时候,会将这些特殊的数据在重分区的时候,人为的造成了数据倾斜]

    5. 个人经验
    (1) 相同维度的计算,一次扫描,多次同时计算

    Rdd的计算过程中,全表扫描是很耗时间的。所以,尽量渐少扫描的过程。能在同一个统计维度中能计算的,尽量在一次计算中去统计。应用场景【在相同的聚合条件中:对不同的字段进行计算,产生不同的指标】

  • 相关阅读:
    java编码规范
    Unix操作系统内核结构报告
    vim常用命令组合
    JavaWeb学习笔记13--Servlet开发(二)
    JavaWeb学习笔记12--Servlet开发(一)
    JavaWeb学习笔记11--JSTL标签库
    JavaWeb学习笔记10--Cookie实现记住密码的功能
    JavaWeb学习笔记9--JSP属性范围
    JavaWeb学习笔记8--JSP内置对象详解
    JavaWeb学习笔记7--JSP脚本元素、指令元素、动作元素
  • 原文地址:https://www.cnblogs.com/maopneo/p/13948053.html
Copyright © 2020-2023  润新知