• Spark开发-内存模型


    Spark内容

      1.Spark的内存模型 2.Spark的执行过程 3.SparkSQL的执行过程 
      本次主要整理内存模型相关内容
    

    Spark的内存模型

    1.Spark2.0采用的是统一内存管理方式 unified Memory Manager

     01.特点是: 存储内存和计算内存在同一空间,并且可以动态的使用彼此的空闲区域
     02.构成:  内存分为堆内内存和堆外内存
            001.堆外内存式由Spark控制,直接在工作节点的系统内存中开辟空间,即对于大内存,Spark自行和内存打交道
                   堆外内存只区分 Execution 内存和 Storage 内存
        这部分用户代码无法直接操作。 堆外内存部分主要用于JVM自身,如字符串、NIO Buffer等开销,
    另外还有部分堆外内存由spark.memory.offHeap.enabled及spark.memory.offHeap.size控制的堆外内存,这部分也归offheap,
       但主要是供统一内存管理使用的。
    
           002.堆内内存依赖JVM,
            – Execution Memory  Execution 内存	主要用于存放 Shuffle、Join、Sort、Aggregation 等计算过程中的临时数据
            – Storage Memory    Storage 内存	主要用于存储 spark 的 cache 数据,例如RDD的缓存、unroll数据
            – User Memory       用户内存(User Memory)	主要用于存储 RDD 转换操作所需要的数据,例如 RDD 依赖等信息
            – Reserved Memory   预留内存(Reserved Memory)	系统预留内存,会用来存储Spark内部对象
           动态占用-- 存储内存和计算内存 一般我们使用的Spark.driver.memory 和 spark.executor.memory
                Spark在一个Executor中的内存分为三块,一块是execution内存,一块是storage内存,一块是other内存
            storage memory 和 Executor memory
    	      Executor memory: 主要存储Shuffle、Join、Sort、Aggregation等计算过程中的临时数据;
    

    2. 驱动器和执行器功能

        Driver和Executor都是JVM进程,内存由MemoryManager统一管理
         Driver的功能
            1)一个Spark作业运行时包括一个Driver进程,也是作业的主进程,具有main函数,
        	           并且有SparkContext的实例,是程序的人口点;
             2)功能:负责向集群申请资源,向master注册信息,负责了作业的调度,
                 负责作业的解析、生成Stage并调度Task到Executor上。包括DAGScheduler,TaskScheduler
         Executor 
           01.Executor 的内存管理建立在 JVM 的内存管理之上
            Executor 内运行的并发任务共享 JVM 堆内内存,这些内存被规划为 存储(Storage)内存 和 执行(Execution)内存
        	一块儿是专门用来给RDD的cache、persist操作进行RDD数据缓存用的;
        	另外一块儿,用来给spark算子函数的运行使用的,存放函数中自己创建的对象
            02. Executor  堆外内存
    

    3.内存溢出有两点:

       1. Driver 内存不够  2. Executor 内存不够
         Driver 内存不够:   1. 读取数据太大    
      	                    2. 数据回传
         Executor 内存不够: 1. map 类操作产生大量数据,包括 map、flatMap、filter、mapPartitions 等
                             2. shuffle 后产生数据倾斜
       Driver内存溢出的解决方式:
          读取数据太大 增加 Driver 内存,具体做法为设置参数 --driver-memory
      	   collect 大量数据回传 Driver,造成内存溢出:解决思路是  分区输出   
       Executor内存溢出解决方式
          map 过程产生大量对象
      	     解决思路是    减少每个 task 的大小,从而减少每个 task 的输出;
      		 具体做法是在 会产生大量对象的 map 操作前 添加 repartition(重新分区) 方法,分区成更小的块传入 map
      		 解决思路: 用 mapPartitions 替代多个 map,减少 Executor 内存压力
      	    shuffle:  
      	    broadcast join
      		缓存 RDD 既可以节省内存,也可以提高性
      		DataFrame 代替 RDD
      	Reduce
      	   增加 reduce 并行度其实就是增加 reduce 端 task 的数量, 这样每个 task 处理的数据量减少,避免 oom
    

    4.数据倾斜

    常见的问题解决方式: 发现-- 定位 --确认 --解决
    1.数据倾斜
       01.什么现象看出有数据倾斜 -发现倾斜 -会看日志
          表现一:某个stage运行时间过长
          表现二:shuffle read的数据量和shuffle write的数据量相差巨大
          表现三:点进stage运行长的,查看task的运行情况 task运行时间过长,读写数据量相差巨大
          表现四: 某个executor上运行时间过长
       02.哪里出现了倾斜--定位倾斜
         哪段代码造成了倾斜,数据倾斜发生在哪一个stage之后,接着我们就需要根据stage划分原理,
          推算出来发生倾斜的那个stage对应代码中的哪一部分,这部分代码中肯定会有一个shuffle类算子
           (注: 需要了解最基本的stage划分的原理,以及stage划分后shuffle操作是如何在两个stage的边界处执行)
          通过DAG图查看
          还可以看看 异常栈信息就可以定位到你的代码中哪一行发生了内存溢出。然后在那行代码附近找找
       03.怎么解决倾斜-解决倾斜
           分析一下那个执行了shuffle操作并且导致了数据倾斜的RDD/Hive表,查看一下其中key的分布情况
    	    数据倾斜: 1. 过滤导致倾斜的 key  2. 使用随机 key 进行双重聚合
                     3.两阶段聚合(局部聚合+全局聚合)
      		     4.提高shuffle操作的并行度
                    sample 采样对倾斜 key 单独进行 join
    2.资源调优-诊断内存的消耗,针对内存调优
        对多次使用的RDD进行持久化或Checkpoint
    

    5.Java内存

    主要的图例:
    

    参考:

    Spark数据倾斜之发现篇 https://blog.csdn.net/dpengwang/article/details/83213825
    Spark性能优化指南——高级篇 (很详细) https://blog.csdn.net/lukabruce/article/details/81504220
  • 相关阅读:
    洛谷P2504 [HAOI2006]聪明的猴子
    洛谷P1516 青蛙的约会
    洛谷P1991 无线通讯网
    洛谷P1265 公路修建
    可展开的列表组件
    网格视图(GridView)功能和用法
    自动完成文本框的功能和用法
    扩展BaseAdapter实现不存储列表项的ListView
    使用SimpleAdapter创建ListView
    实例:基于ListActivity实现列表
  • 原文地址:https://www.cnblogs.com/ytwang/p/13665187.html
Copyright © 2020-2023  润新知