SPARK 是怎么清除Shuffle中间结果数据的

Spark Shuffle机制解析 文章目录Shuffle简介与其发展Shuffle机制的实现ShuffleManager接口简介ShuffleManager的创建具体实现类SortShuffleManagerregisterShuffle方法getWriter方法getReader方法Shuffle Writer过程解析数据聚合与排序聚合排序溢写磁盘数据合并与持久化生成索引文件Shuffle Reader过程解析获取map任务输出的位置信息获取blocks数据划分本地与远程Block获取远程Block获取本地Blockreduce端聚合数据 阅读详情

背景

本文基于 SPARK 3.2.1
我们知道在Spark中,shuffle的数据会存在ESS或者BlockManager中的,但是spark什么时候会删除shuffle的中间结果数据呢?这篇文章我们来分析一下

分析

我们知道spark肯定会删除shuffle结果数据,要不然长期以往,磁盘肯定会爆掉。
其中清除的组件就是ContextCleaner,代码如下:

private[spark] class ContextCleaner(
    sc: SparkContext,
    shuffleDriverComponents: ShuffleDriverComponents) extends Logging {

  /**
   * A buffer to ensure that `CleanupTaskWeakReference`s are not garbage collected as long as they
   * have not been handled by the reference queue.
   */
  private val referenceBuffer =
    Collections.newSetFromMap[CleanupTaskWeakReference](new ConcurrentHashMap)

  private val referenceQueue = new ReferenceQueue[AnyRef]

  private val cleaningThread = new Thread() { override def run(): Unit = keepCleaning() }

  private val periodicGCService: ScheduledExecutorService =
    ThreadUtils.newDaemonSingleThreadScheduledExecutor("context-cleaner-periodic-gc")
 ...
    /** Register a ShuffleDependency for cleanup when it is garbage collected. */
  def registerShuffleForCleanup(shuffleDependency: ShuffleDependency[_, _, _]): Unit = {
    registerForCleanup(shuffleDependency, CleanShuffle(shuffleDependency.shuffleId))
  }

在spark driver端,每生成一个ShuffleDependency对象,就会把该对象注册到ContextCleaner中,数据链路如下:

   ShuffleDependency
  _rdd.sparkContext.cleaner.foreach(_.registerShuffleForCleanup(this))
                ||
                \/
  registerForCleanup(shuffleDependency, CleanShuffle(shuffleDependency.shuffleId))
                      ||
                      \/
  referenceBuffer.add(new CleanupTaskWeakReference(task, objectForCleanup, referenceQueue))

可以看到会把该对象组装成CleanupTaskWeakReference实例(也是WeakReference实例)放到一个buffer中,关于WeakReference的作用大家可以自行网上查阅,作用就是如果一个对象只被WeakReference实例引用的话,
那该对象就会被GC,并且会把它放入该Reference实例相关联的ReferenceQueue。

再看cleaningThread 这个线程调用的方法keepCleaning:

private def keepCleaning(): Unit = Utils.tryOrStopSparkContext(sc) {
    while (!stopped) {
      try {
        val reference = Option(referenceQueue.remove(ContextCleaner.REF_QUEUE_POLL_TIMEOUT))
          .map(_.asInstanceOf[CleanupTaskWeakReference])
        // Synchronize here to avoid being interrupted on stop()
        synchronized {
          reference.foreach { ref =>
            logDebug("Got cleaning task " + ref.task)
            referenceBuffer.remove(ref)
            ref.task match {
              case CleanRDD(rddId) =>
                doCleanupRDD(rddId, blocking = blockOnCleanupTasks)
              case CleanShuffle(shuffleId) =>
                doCleanupShuffle(shuffleId, blocking = blockOnShuffleCleanupTasks)
              case CleanBroadcast(broadcastId) =>
                doCleanupBroadcast(broadcastId, blocking = blockOnCleanupTasks)
              case CleanAccum(accId) =>
                doCleanupAccum(accId, blocking = blockOnCleanupTasks)
              case CleanCheckpoint(rddId) =>
                doCleanCheckpoint(rddId)
              case CleanSparkListener(listener) =>
                doCleanSparkListener(listener)
            }
          }
        }
      } catch {
        case ie: InterruptedException if stopped => // ignore
        case e: Exception => logError("Error in cleaning thread", e)
      }
    }
  }

他会循环的从关联的队列里获取对应的被GC的对象,之后去调用对应的方法去清理数据,如doCleanupShuffle:

def doCleanupShuffle(shuffleId: Int, blocking: Boolean): Unit = {
    try {
      if (mapOutputTrackerMaster.containsShuffle(shuffleId)) {
        logDebug("Cleaning shuffle " + shuffleId)
        // Shuffle must be removed before it's unregistered from the output tracker
        // to find blocks served by the shuffle service on deallocated executors
        shuffleDriverComponents.removeShuffle(shuffleId, blocking)
        mapOutputTrackerMaster.unregisterShuffle(shuffleId)
        listeners.asScala.foreach(_.shuffleCleaned(shuffleId))
        logDebug("Cleaned shuffle " + shuffleId)
      } else {
        logDebug("Asked to cleanup non-existent shuffle (maybe it was already removed)")
      }
    } catch {
      case e: Exception => logError("Error cleaning shuffle " + shuffleId, e)
    }
  }

这里就会以消息的方式发送给BlockManager去清理对应的shuffle数据。
对应的持久化RDD/Accumulator/Broadcast/CheckpointData等数据的清理也是通过这个机制。
这里额外说一点:
对于persist方法去持久化RDD的时候,是在Task运行的时候才会把RDD组成RDDBlockId(id, partition.index)的方式且按照存储的level存储到对应的executlor的BlockManager中。
persist方法只是设置一个level的级别,如下:

private def persist(newLevel: StorageLevel, allowOverride: Boolean): this.type = {
    // TODO: Handle changes of StorageLevel
    if (storageLevel != StorageLevel.NONE && newLevel != storageLevel && !allowOverride) {
      throw SparkCoreErrors.cannotChangeStorageLevelError()
    }
    // If this is the first time this RDD is marked for persisting, register it
    // with the SparkContext for cleanups and accounting. Do this only once.
    if (storageLevel == StorageLevel.NONE) {
      sc.cleaner.foreach(_.registerRDDForCleanup(this))
      sc.persistRDD(this)
    }
    storageLevel = newLevel
    this
  }

注意:在Driver会用periodicGCService ScheduledExecutorService定期的触发GC,默认的频率是30分钟,也可以通过spark.cleaner.periodicGC.interval进行设置

至此关于spark清理shuffle中间结果数据也就分析完了。

“戏”说spark---spark Shuffle详解(二) Spark中两种ShuffleManager,HashShuffleManager和SortShuffleManager,那么在Shuffle中,Reduce节点是怎么知道map端溢写文件的位置的呢?Reduce端是怎么拉取数据的呢? 阅读详情

相关推荐

Docker容器n8n中 read/write files from disk 无法读取容器内文件解决方案

《n8n文件读写Docker部署常见问题解决方案》摘要:针对n8n 1.90.2版本在Docker环境下文件读写失败问题,本文分析常见错误包括路径错误(ENOENT)、权限不足(EACCES)及节点误用问题。核心解决方案为:1)通过-v参数挂载宿主机目录到容器(如/files);2)使用新版Read/WriteFilesfromDisk节点操作文件;3)确保权限设置正确。提供可直接导入的示例工作流JSON,演示从CSV读取到结构化数据处理的全流程。特别强调已部署用户需重新挂载卷的正确操作方式,并附解决方案对

m0_74822402的博客 2184

spark动态资源调度中的shuffle service的数据清理

但在不同的集群部署方案中,如 YARN,Mesos,Standalone配置外部的 shuffle 服务的方式都不一样,每当有新的部署方案,例如支持 Kubernetes 集群,都需要实现对应的 shuffle 服务以支持动态资源分配,可以看到动态资源分配与资源集群耦合太紧,从而限制其灵活性。动态分配根据任务数量生成的最大并行度,默认提供最大并行度,该为 0.5 则降低一半新增的 executor 的数量,对某些小任务会提高资源利用率,受minExecutors和maxExecutors值的影响。

三劫散仙 1126

保姆级教程:用K210麦克风阵列模块实现声源定位(附完整Python代码与坐标计算)

本教程详细介绍了如何使用K210麦克风阵列模块实现高精度声源定位,包括硬件连接、算法解析与实战代码。通过Python代码示例,展示了从原始数据获取到三维空间坐标计算的完整流程,适用于智能家居、机器人导航等场景。

weixin_42558093的博客 226

spark数据清洗解决方案

数据倾斜的解决方案 之 小表join大表转为小表broadcast+map大表实现。 适用场景:在对RDD使用join类操作,或者是在Spark SQL中使用join语句时, 并且join操作中的一个RDD或表的数据量比较小(比如几百M或者一两G)。 实现原理:普通的join是会走shuffle过程的,而一旦shuffle, 就相当于会将相同key的数据拉取到一个shuffle read task...

qq_43193797的博客 2571

逆向实战:Soul聊天协议加密与Frida绕过检测

本文详细解析了Soul聊天协议逆向分析的全过程,重点介绍了如何利用Frida绕过应用的反调试检测机制。通过静态分析定位关键SO库,并编写Frida脚本动态Hook线程创建函数,成功实现对抗。文章还进一步追踪了基于DES算法的加密流程,并探讨了协议数据结构的解析方法,为移动应用安全研究提供了实战参考。

2w3e4r5t6y的博客 1131

zynq7020的arm A9核降频实录

zynq arm9 cortex a9 降频

qq_40011737的博客 8763

spark/work爆满如何清理

#spark-env.sh中添加自动清理配置 export SPARK_WORKER_OPTS="-Dspark.worker.cleanup.enabled=true -Dspark.worker.cleanup.interval=60 -Dspark.worker.cleanup.appDataTtl=120"

咸鱼的博客 2357

如何将 Fiori Elements Object Page Header 工具栏里按钮用 JavaScript 代码设置成禁用状态

本文介绍了如何在SAP Fiori Elements应用中动态控制Object Page工具栏按钮的可用状态。通过UI5 Inspector工具分析发现,这些按钮的enabled属性都双向绑定到/ui/enabled模型字段。在StatusExt.controller.js中,通过获取按钮ID前缀拼接完整控件ID,使用setEnabled(false)方法即可禁用按钮。关键点包括:1)使用extensionAPI获取视图ID前缀;2)注意事件回调中的this上下文绑定;3)通过修改模型字段可同步更新所有绑定

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 370

Spark缓存清理机制

unpersist http://homepage.cs.latrobe.edu.au/zhe/ZhenHeSparkRDDAPIExamples.html#unpersist Dematerializes the RDD (i.e. Erases all data items from hard-disk and memory). However, the RDD object remains

u014033218的专栏 8017

uniapp:实现APP获取陀螺仪数据、加速传感器、线性加速传感器,uniApp实时监听陀螺仪【XYZ】数据及停止监听与资源释放等功能示例源码,根据需求做功能(完美兼容Android安卓、苹果ios)

uniapp陀螺仪,uniapp加速传感器,uniapp线性加速传感器,APP陀螺仪数据,uniapp app 端获取陀螺仪数据示例代码,手机中获取陀螺仪的数据,uniApp实时获取陀螺仪xyz数据,android陀螺仪方向,获得陀螺仪传感器,处理传感器数据,停止监听与资源释放,Android使用陀螺仪,uniapp苹果ios陀螺仪,uni-app设备之(加速计,罗盘,陀螺仪)插件安卓/IOS APP提供了获取陀螺仪数据的能力,手机陀螺仪传感器获得手机自身旋转的角度,陀螺仪获取旋转角度,陀螺仪、加速度传感器

✅ 精选推荐文章 4265

一文搞懂 JavaScript 模块化规范:CommonJS、AMD、ES6 Module

在现代 JavaScript 开发中,模块化是提升代码组织性和可维护性的关键。本文深入解析三种主流的模块化规范——CommonJS、AMD 和 ES6 Module。

Allen- 3477

spark性能优化----缓存清除

spark是一款优秀的框架,计算性能相当优异,已经发展成大数据主流计算引擎,在spark开发过程中有很多优化的点。其中去除重复计算是非常重要的。一般操作调用cache/persist,来缓存中间结果,避免重复计算。其中cache是persist的一个特列(cache相当于persist())。persist拥以下几个级别的缓存:NONE 默认配置(不缓存) DISK_ONLY 数据缓存到磁盘,...

u010990043的博客 1万+

Python爬虫实战:如何爬取汽车之家报价信息

本文通过实战介绍了如何使用Python编写爬虫,抓取汽车之家网站的车型、价格、配置等信息。在爬虫实现过程中,我们使用了requests库来发送HTTP请求,使用解析HTML页面,提取嵌入的JSON数据,并将数据存储到CSV文件中。同时,我们还介绍了如何使用反爬虫策略(如随机User-Agent、请求延时、代理池等)来规避反爬虫机制,确保爬虫的稳定性。

2201_76125261的博客 1594

Spark Push Based Shuffle 原理分析_spark remoteblockpushresolver

问题: merger location 是现在运行的 executor 地址。如 application 刚开始运行时队列资源紧张,第 1 个 mapper 处理完时,getMergerLocation 时,申请到的 executor 不多,但是任务很大,后续可能申请到更多 executor。就会出现把 shuffle 数据 push 到少数 ess 上, 照成 shuffle 数据倾斜。是否可能用所有的 ESS 地址参加 get merger locations 的计算?

2401_84164527的博客 1013

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

理解Shuffle

Shuffle是spark跨不同分区重新分布分组数据的机制,这个操作会跨executor、机器copy数据 底层机制 以 reduceByKey 为例 将所有属于key的values经过func运算聚合成一个tuple(key,new calc value)。问题是,并不是跟key相关的所有values都会出现在一个分区里,甚至出现在同一个节点里,而这些数据都需要全部归集起来进行计算。相当于从所有...

一只破碗 670

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Mesos shuffle service unusable in Spark1.6

报错提示:WARN TaskSetManager: Lost task 132.0 in stage 2.0 (TID 5951, spark047207): java.io.FileNotFoundException: /data1/spark/tmp/blockmgr-5363024d-29a4-4f6f-bf87-127b95669c7c/1c/temp_shuffle_7dad1a33-28

偷闲小苑 943

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

11、spark

第十二(十一)天:spark一、spark(一)介绍(Ⅰ)spark起源(Ⅱ)Spark的技术背景(二)spark vs MapReduce(Ⅰ)MapReduce存在的问题(Ⅱ)Spark的优势(Ⅲ)Hadoop 的 MapReduce 为什么不使用内存存储?二、spark安装(一)单机模式(Ⅰ)上传文件(Ⅱ)解压并修改文件名(Ⅲ)修改配置文件(Ⅳ)启动(二)集群模式(三)On yarn(集群,资源管理交给yarn调度)三、RDD(一)RDD介绍(Ⅰ)概述(Ⅱ)查看RDD(Ⅲ)分区概念(Ⅳ)简单使用(RD

qq_44304788的博客 2075

数据开发校招笔试题全解析:从HashMap到Hive/Spark核心考点

大数据开发岗位的校招笔试,历来是筛选候选人基础能力的关键环节。这类题目看似考察具体框架API,实则聚焦于语言功底、组件原理、SQL功底与工程思维。从Java集合与JVM内存模型,到HDFS读写与MapReduce Shuffle机制,再到Hive数仓建模中的内外部表、分区分桶及数据倾斜解法,每一个考点都指向生产环境中的真实问题。而Spark的RDD血缘、宽窄依赖,Kafka的ISR机制与一致性保证,以及Flink的Checkpoint与Exactly Once语义,更是大数据组件原理的高频考察方向。此外,手

weixin_33782386的博客 263

大数据面试题_Spark篇

大数据面试题中Spark的部分

weixin_42570840的博客 711

Spark数据倾斜和调优

spark数据倾斜和调优

weixin_45629153的博客 913

Spark分布式计算原理

Spark分布式计算原理一、RDD特征1、Lineage:血统、遗传2、依赖关系二、DAG(有向无环图)工作原理三、Spark Shuffle过程四、RDD持久化1、RDD缓存机制2、缓存策略3、缓存应用场景4、检查点五、RDD共享变量1、广播变量2、累加器六、RDD分区设计1、分区大小限制为2G2、分区太少3、分区过多4、经验5、数据倾斜 一、RDD特征 1、Lineage:血统、遗传 RDD最重要的特性之一,保存了RDD的依赖关系 RDD实现了基于Lineage的容错机制 2、依赖关系 宽依赖 一个

绿萝蔓蔓绕枝生 883

大数据面试题Spark篇(1)

对于窄依赖而言,由于窄依赖实质是指父RDD的分区最多被一个子RDD使用,在此情况下出现部分计算的错误,由于计算结果的数据只与依赖的父RDD的相关数据有关,所以不需要重新计算所有数据,只重新计算出错部分的数据即可。RDD可以从本地集合并行化、从外部文件系统、其他RDD转化得到,能从其他RDD通过Transformation创建新的RDD的原因是RDD之间有依赖关系,代表了RDD之间的依赖关系,即血缘,RDD和他依赖的父RDD有两种不同的类型,即宽依赖和窄依赖。RDD持久化是可以手动选择不同的策略的。

weixin_51981189的博客 4131

大数据-Spark(七)

大数据-Spark(七) RDD的依赖关系 RDD和它依赖的父RDD的关系有两种不同的类型,窄依赖(narrow dependency)和宽依赖(wide dependency)。 窄依赖:窄依赖指的是每一个父RDD的Partition最多被子RDD的一个Partition使用。map/flatMap/filter/union等这些算子操作是窄依赖,所有的窄依赖不会产生shuffle。 宽依赖 :宽依赖指的是多个子RDD的...

海恋北斗星 355

spark

文章目录概述spark为什么比hadoop快?RDDTransformation -- 变换--懒操作Actions - 执行单词统计计算宽依赖和窄依赖DAGStageSpark ShuffleRDD缓存CheckpointSpark调度 概述 离线批处理+实时流处理 spark为什么比hadoop快? hadoop的shuffle产生大量的磁盘IO影响了效率。 spark在内存中操作,尽量避免数据落盘操作(窄依赖不进行shuffle) sh spark-shell --master=local(单机模

zhouben12的博客 174

Spark 资源自动清理

Spark运行一次SQL,根据SQL的具体执行情况,可能会产生很多垃圾。譬如你可以很容易观察到的就是在Spark UI上跑完SQL后会有Storage Memory的占用:这个应该是SQ...

allwefantasy的专栏 1454

Spark2.3.2 Configuration 参数配置

SPARKConfiguration 参数配置表,有能力的请直接看原文 http://spark.apache.org/docs/2.3.2/configuration.html Spark Streaming 名称 默认 含义 spark.streaming.backpressure.enabled false 启用或禁用Spark Streaming的内部背...

tianhouquan的专栏 985
上一篇: SPARK push-based shuffle mapTask是怎么获取ESS列表信息
下一篇: SPARK中 会对Scan的小文件做合并到一个Task去处理么?
鸿乃江边鸟
博客等级 码龄6年 3746粉丝 235原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值