首页 > 数据库 > 数据库开发技术 > Spark Shuffle及其优化
shuffle 在 Spark 中表示 map task 和 reduce task 之间数据交换的过程。
shuffle 的目的就是为了对数据进行分组,把相同的 key 放在一起。
我们知道,Spark RDD 之间的关系分为窄依赖(父 RDD 和子 RDD 分区是一对一的关系)和宽依赖(父 RDD 和子 RDD 分区是一对多的关系)。
宽依赖也叫做 shuffle 依赖,所以说,发生宽依赖必然会发生 Shuffle,也就是宽依赖算子必然会发生 Shuffle 操作。而 shuffle 也是划分 Stage 的依据。

拉取的数据首先会放到内存中,然后进行数据处理,并写入相应的位置。如果 spark.shuffle.spilis=false,则处理后的数据将使用 AppendOnlyMap 仅写入内存中;否则,处理后的数据将使用 ExternalAppendOnlyMap 写入内存和磁盘。
yarn-site.xml 中新增如下属性:
<!-- NodeManager中一个长期运行的辅助服务,用于提升Shuffle 计算性能 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>spark_shuffle</value>
</property>
<!-- NodeManager中辅助服务对应的类 -->
<property>
<name>yarn.nodemanager.aux-services.spark_shuffle.class</name>
<value>org.apache.spark.network.yarn.YarnShuffleService</value>
</property>
<!-- Shuffle服务监听数据获取请求的端口。可选配置,默认为7337 -->
<property>
<name>spark.shuffle.service.port</name>
<value>7337</value>
</property>
重启 NodeManager,会自动启动 ESS(External shuffle Service)。
spark.shuffle.service.enabled true
spark.shuffle.service.port 7337
处理 Shuffle 除了可以使用 ESS,还可以使用 RSS。
ESS 的原理是 Map 任务在计算节点本地将相同 Partition 数据合并到一起;
RSS 的原理是 Map 任务将相同 Partition 数据 Push 到远端的 RSS 服务,RSS服务 将同一 partition 的数据合并。
这里就不得不提一下这个项目:Apache Celeborn,它是 RSS 的一种开源解决方案。大家可以自行去官网查看项目详情:https://celeborn.apache.org/
ESS 和 RSS 都是为了解决 spark shuffle 过程中大量小文件读写和大量磁盘IO和网络IO,其目的都是为了优化 shuffle 过程,提高 shuffle 的效率和可靠性。
ESS 是一个在每个节点上运行的独立服务,它负责管理该节点上所有 Executor 生成的 Shuffle 数据。主要优势包括:
① 提高了可靠性,即使Executor进程因GC或其他原因挂掉,也不会影响Shuffle数据的可用性。
② 允许释放闲置的Executor以节省集群资源。
③ 支持动态资源分配,即Executor可以根据需要动态增加或减少。
当然它也有一些缺点:
① 脆弱的网络模型
② 低效的小文件IO
③ 缺乏Shuffle数据的Locality调度
RSS 是一种将 Shuffle 数据写入远端服务的解决方案。它的优点主要包括:
① 存储和计算分离,使计算节点和存储节点能够各司其职。
② 支持动态资源分配,任务完成后可以立即释放资源。
③ 能够很好地集成资源调度组件,如Kubernetes。
④ 灵活性比较大,在实际应用中,各大公司可以根据实际情况定制自己的 RSS 服务。
⑤ 减少Shuffle文件数量和读写磁盘次数,以及提供数据备份和负载均衡。
总之:
ESS 通过在每个节点上提供常驻服务来提高 Shuffle 数据的可靠性和可用性;
RSS 通过将 Shuffle 数据的存储和计算分离,进一步提高了资源利用率和系统稳定性。
选择使用 ESS 还是 RSS,或者它们的特定实现,通常取决于具体的使用场景和集群环境。
往期推荐
原文作者:毛毛小妖的笔记;如有侵权,请联系管理员删除。