Spark RDD sortBy算子什么情况会触发shuffle

在 Spark 的 RDD 中,sortBy 是一个排序算子,虽然它在某些场景下可能看起来是分区内排序,但实际上在需要全局排序时会触发 Shuffle。这里我们分析其底层逻辑,结合源码和原理来解释为什么会有 Shuffle 的发生。


1. 为什么 sortBy 会触发 Shuffle?

关键点 1:全局有序性要求

sortBy 并非单纯的分区内排序。它的目标是按照用户指定的键对整个 RDD 的数据进行排序,这种操作需要保证全局顺序。为实现这一点,必须:

  • 对数据进行 重新分区(Repartition),确保每个分区中的数据按照全局范围内的排序键正确分布;
  • 每个分区内部再完成排序。

这些步骤不可避免地引入了 Shuffle,因为数据需要从一个分区转移到另一个分区以保证全局有序性。


关键点 2:底层调用 repartitionAndSortWithinPartitions

sortBy 的底层实现会调用 repartitionAndSortWithinPartitions 方法:

this.keyBy(f).repartitionAndSortWithinPartitions(
  new RangePartitioner(numPartitions, this, ascending))(ordInverse).values
  1. keyBy(f)

    • 将数据转化为 (key, value) 格式,key 是排序的关键字,value 是原始数据。
  2. RangePartitioner

    • 使用 RangePartitioner 将数据根据排序键重新分区(这一步需要 Shuffle)。
  3. repartitionAndSortWithinPartitions

    • 先 Shuffle 数据以保证每个分区内的 key 是按范围划分的;
    • 然后对每个分区内的数据进行排序。
Shuffle 的触发
  • 当目标分区数量与当前分区数量不一致时(用户指定分区数或默认分区数),会触发 Shuffle;
  • 即使目标分区数一致,只要需要保证全局有序,也需要重新分布数据来确保各分区内数据按键范围划分。

2. Shuffle 的作用

  • 全局排序:分区间重新分布数据,确保所有分区的排序键范围是连续的。
  • 负载均衡:通过 RangePartitioner 分布数据,避免某些分区过大或过小的问题。
  • 分区内排序:确保每个分区内部数据按键排序。

3. 源码分析

repartitionAndSortWithinPartitions 的核心逻辑如下:

def repartitionAndSortWithinPartitions(
    partitioner: Partitioner)(
    implicit ord: Ordering[K]): RDD[(K, V)] = withScope {
  val shuffled = new ShuffledRDD[K, V, V](this, partitioner)
  shuffled.setKeyOrdering(ord)
  new MapPartitionsRDD(shuffled, (context, pid, iter) => {
    val sorter = new ExternalSorter[K, V, V](context, Some(partitioner), Some(ord))
    sorter.insertAll(iter)
    context.taskMetrics().incMemoryBytesSpilled(sorter.memoryBytesSpilled)
    context.taskMetrics().incDiskBytesSpilled(sorter.diskBytesSpilled)
    context.taskMetrics().incPeakExecutionMemory(sorter.peakMemoryUsedBytes)
    sorter.iterator
  })
}
  1. ShuffledRDD

    • 触发 Shuffle,将数据根据分区器重新分布。
  2. ExternalSorter

    • 对每个分区内的数据进行排序(如果数据超出内存,会使用磁盘作为临时存储)。

4. 举例说明 Shuffle 的发生

sortBy 的行为取决于传递的参数。为了实现分区内排序,你需要明确控制 sortBy 的参数设置。如果不显式指定目标分区数(numPartitions 参数),sortBy 默认不会触发 Shuffle,因此只会在分区内排序。

例子 1:带 Shuffle 的全局排序
val rdd = sc.parallelize(Seq(5, 2, 4, 3, 1), numSlices = 2)
val sortedRdd = rdd.sortBy(x => x, ascending = true, numPartitions = 3)// 指定目标分区数
println(sortedRdd.collect().mkString(", "))
  • 初始数据分区
    分区 1:[5, 2],分区 2:[4, 3, 1]
  • 重新分区和排序后
    分区 1:[1, 2],分区 2:[3, 4],分区 3:[5]
  • Shuffle 触发原因
    数据必须重新分布,确保分区键范围([1-2], [3-4], [5])。
  • 特点
    触发 Shuffle 操作,数据按照 RangePartitioner 进行分区。
    每个分区内局部排序后,实现全局排序。
例子 2:分区内排序(无 Shuffle)
val rdd = sc.parallelize(Seq(5, 2, 4, 3, 1), numSlices = 2) // 两个分区
// 如果只需要分区内排序,mapPartitions 提供了无 Shuffle 的选择。
val sorted = rdd.mapPartitions(partition => partition.toList.sorted.iterator)
sorted.collect().foreach(println)
  • 初始数据分区
    分区 1:[5, 2],分区 2:[4, 3, 1]
  • 排序后
    分区 1:[2, 5],分区 2:[1, 3, 4]
  • 无 Shuffle 原因
    数据仅在分区内排序,分区间顺序无全局保证。

5. 总结

  • sortBy 在需要全局排序时触发 Shuffle,这是为了重新分区以确保分区范围和分区内排序。
  • 如果只需要分区内排序,mapPartitions 提供了无 Shuffle 的选择。

注意事项

  • 全局排序带来的 Shuffle 会显著增加网络传输和计算成本。
  • 如无必要,尽量避免全局排序,优先考虑局部排序或 Top-N 算法以优化性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/919046.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用redis的key失效监听器KeyExpirationEventMessageListener作任务定时提醒功能

某需求: 要求在任务截止日期的前3天时,系统自动给用户发一条消息提醒。 用定时任务的话感觉很不舒服。间隔时间不好弄。不能精准卡到那个点。 由于系统简单,没有使用消息列队,也不能使用延时队列来做。 用Timer的话开销还挺大的&a…

数造科技亮相第26届高交会并接受媒体采访,以数据智能赋能未来

11 月 14 日至 16 日,第二十六届中国国际高新技术成果交易会(简称“高交会”)在深圳成功举办。本届大会以“科技引领发展,产业融合聚变”为主题,汇聚了全球最新的科技成果,打造了一场科技界的盛大聚会。 在…

Facebook广告投放如何提高过审率?

在Facebook进行广告投放活动时,如何让广告过审应该是让很多人头疼的事情,前期花时间准备文案素材等,结果广告不过审,等于一切的前期准备都打水漂了,特别是黑五类的一些产品。许多独立站会架设斗篷,根据市场…

springBoot插件打包部署

打包插件spring-boot-maven-plugin 不使用插件,运行时,异常信息为“没有主清单属性” 本地部署 杀进程

VSCode+ESP-IDF开发ESP32-S3-DevKitC-1(2)第一个工程 LED心跳灯

VSCodeESP-IDF开发ESP32-S3-DevKitC-1(2)第一个工程 LED心跳灯 前言1.新建工程2.编写控制LED代码3.LED控制独立成.c和.h文件 前言 实际开发中很多时候我们需要有一个类似心跳灯或运行指示灯的灯以不同的状态闪烁以表示程序的运行状态,所以第…

【金融风控项目-06】:风控建模流程

文章目录 2 风控建模流程2.1 ABC评分卡简介2.2 机器学习模型工作的完整流程2.3 项目准备期2.3.1 明确需求 2.4 模型设计2.4.1 业务抽象成分类/回归问题2.4.2 模型算法2.4.3 模型输入2.4.4 Y标签定义2.4.5 样本选取2.4.6 样本采样2.4.7 观察期和表现期2.4.8 Y标签阈值确定2.4.9 …

Gartner发布中国PAM特权访问管理创新洞察:PAM的8个主要目标和国内9个主要提供商

特权账户是攻击者的主要目标,对每个组织来说都是重大的安全风险。安全和风险管理领导者可以利用这项研究来了解技术前景并降低特权访问风险。 主要发现 合规在推动中国采用特权访问管理 (PAM) 工具方面发挥着重要作用。然而,这些工具的实施经常遭到IT管理…

mayo介绍和QTqmake编译基于Opencascade开发的mayo工程-小白配置

目录: 一、mayo介绍:zap: 最新功能(截止7.8.2)在这里插入图片描述 二、编译准备三、编译过程3.1QT Creator打开源码的pro工程3.2修改几处pro配置3.3复制所需的动态链接库3.4编译完成 一、mayo介绍 1️⃣mayo是一个基于opencascade开源库开发的一个开源CA…

ISUP协议视频平台EasyCVR私有化部署视频平台如何实现RTMP推流将大疆无人机的视频画面回传?

在现代视频监控和流媒体技术领域,EasyCVR视频融合云平台以其卓越的性能和灵活性,成为了跨区域、网络化视频监控综合管理的理想选择。作为TSINGSEE青犀视频“云边端”架构体系中的核心组件,私有化部署视频平台EasyCVR不仅能够实现视频数据的集…

如何高效实现汤臣倍健营销云数据集成到SQLServer

新版订单同步-(Life-Space)江油泰熙:汤臣倍健营销云数据集成到SQL Server 在企业信息化建设中,数据的高效集成和管理是提升业务运营效率的关键。本文将分享一个实际案例——如何通过新版订单同步方案,将汤臣倍健营销云…

OpenHarmony-2.DeviceInfo适配

DeviceInfo适配说明 1.启动子系统设备信息说明 2.OHOS 2.1.OHOS 固定值参数适配 OHOS 固定值参数: const.ohos.version.security_patch const.ohos.releasetype const.ohos.apiversion const.ohos.fullname适配说明: OHOS 固定值参数由OHOS系统填充&#xff0…

Java实现两数交换

文章目录 实现两数交换方法一、(数组的方式进行交换)方法二、(对象的方式进行交换)总结 实现两数交换 实现两数交换,没有办法通过直接传递数字达到交换的结果,定义的int型变量是被存储在栈空间上的&#xf…

uniapp 购物弹窗组件 (微信小程序)

效果图&#xff0c;暂时只适应单规格&#xff0c;居中弹出和下方弹出&#xff0c;如需求不满足&#xff0c;请自行修改代码 &#xff08;更新于24/11/15) 居中显示效果 下方弹出效果 html <template><view class"" v-if"show":class"mod…

革新车间照明,分布式IO模块引领智能制造新纪元

在智能制造的浪潮中&#xff0c;每一个细节的优化都是推动生产效率与能耗管理迈向新高度的关键。车间照明系统&#xff0c;作为生产环境中不可或缺的一环&#xff0c;其智能化升级正成为众多企业转型升级的重要着力点。 一、从传统到智能&#xff1a;照明系统的变革之旅 传统…

Java基于微信小程序+SSM的校园失物招领小程序

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

微软Office 2021 24年11月授权版

概述 Microsoft Office LTSC 2021 专业增强版是微软公司推出的一款专为企业客户设计的办公软件套件。该版本于2024年11月进行了批量许可版更新推送&#xff0c;旨在为企业用户提供更加稳定、高效的办公体验。 主要特点 LOGO设计趋势强化&#xff1a;新版Office将棱角改为圆角…

uniapp实现中英文切换

home.js const data {ZH: {content1: "苹果",},EN: {content1: “Apple”,} } export default dataindex.js import home from "./home.js" export default {home }en.js import part1 from ./data/part1/index.js const en {language: {name: "…

go-zero(七) RPC服务和ETCD

go-zero 实现 RPC 服务 在实际的开发中&#xff0c;我们是通过RPC来传递数据的&#xff0c;下面我将通过一个简单的示例&#xff0c;说明如何使用go-zero框架和 Protocol Buffers 定义 RPC 服务。 一、生成 RPC项目 在这个教程中&#xff0c;我们根据user.api文件&#xff0…

C#.Net筑基-字符串超全总结

字符串是日常编码中最常用的引用类型了&#xff0c;可能没有之一&#xff0c;加上字符串的不可变性、驻留性&#xff0c;很容易产生性能问题&#xff0c;因此必须全面了解一下。 01、字符与字符编码 1.1、字符Char 字符 char 表示为 Unicode字符&#xff0c;在C#中用 UTF-16 …

ROS Action

在 ROS 中&#xff0c;Action 是一种支持长时间异步任务的通信机制。与 Service 不同&#xff0c;Action 允许客户端发起一个请求&#xff0c;并在任务执行的过程中不断接收反馈&#xff0c;直到任务完成。这种机制非常适用于可能需要较长时间来完成的任务&#xff0c;比如机器…