spark-shuffle总结及调优

本文详细介绍了Spark中HashShuffle和SortShuffle两种shuffle机制的工作原理及优化方法,包括文件生成方式、排序策略、合并过程及关键参数配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spark1.2  默认使用的是 HashShuffle 

写入磁盘流程:

    将每个task 处理的数据,按照 key 的 hash 进行分类,从而相同的 key 写入到同一个磁盘文件里面,而每个磁盘文件都只属于下游 stage 的一个 task,将数据写入到磁盘前,会先将数据写入到内存缓冲中,当内存缓冲填满后,溢写到磁盘文件中

    不排序,当前 stage 的每个 maptask,会为下个 stage每个 reducetask生成一个文件;

        文件数量计算公式:maptask_num * reducetask_num 

        比如当时 stage 有50个 task,下个 stage 有100个 task,那么每个 task 会创建100个文件,总共需要创建50*100

    缺点:大量随机 io,大量内存占用

下图为优化后的 hashShuffle ,开启了 File consolidation 机制

    针对第一版 shuffle 进行改进,引入 File Consolidation 机制

        文件数量计算公式:core_num * reducetask_num

        举例来说:stage 有50个 task,当前有10个core,下个 stage 有100个 task,那么每个 core会创建100个文件,总共需要创建10*100

        其它等式

            executor_core_num = shuffleFilegroup_num 

            shuffleFilegroup 产生的文件数量 = 下游 stage 的 task 数量

        开启 consolidate机制:设置 spark.shuffle.consolidateFiles = true; 开启后, shufflewrite 阶段,task 就不会再为下游 stage 的每个 task 都创建一个磁盘文件,会有shuffleFilegroup 概念,每个 shuffleFilgroup 会对应一批磁盘文件,文件数量=下游 stage 的 task 数量。一个 executor有几个 core,就会有几个 shuffleFilegroup 数量,第一批 task 并行,创建相应的文件,第二批直接利用第一批已经创建的文件


spark1.2后使用的量 sortshuffle

    sortshufflemanager 运行机制有两个:普通运行机制,另外一个是 bypass 运行机制

    普通运行机制:

    

    

文件数量: 当前 stage maptask 数量,比如当前stage的task数量为50,那么会产生50个文件

流程:

    数据先写入一个内存结构(根据不同的算子,选择不同的数据结构;如果是 bykey类,写入Map;如果是 join 类,写入 Array),接着每写入一条数据,判断是否达到溢写到磁盘的阀值(10000),如果达到阀值溢写到磁盘,然后清空内存;

    在写入磁盘前,在内存中进行排序,写入磁盘使用的是 java 的BufferedOutputStream 实现,BufferedOutputStream 是 java 的缓冲输出流,首先将内存缓存在内存里,当内存满溢后,再写入到磁盘中,减少了 io,提升性能;

    一个 task 将所有数据写入到内存结构时,会发生多次磁盘溢写,产生多个临时文件,最后将之前的文件合并,写入到最终文件里,称为merge;

    由于一个 task 只能产生一个文件,那么意味着下游task 所需文件都在这个文件里面,因此还写了一份索引文件,记录了下游各 task的数据在文件中的start offset, end offset

    

bypass 机制

当shuffle read task 数量小于等于 spark.shuffle.sort.bypassMergeThreshold参数时(默认值200)就会启用bypass 机制

前段处理与 hashshuffle 一致,当前task 为下游每个 task 创建一个文件,按照 key 的 hash值,写入到对应的文件里面;只是最后有个 merge过程,合并成一个文件,并添加索引文件

与普通机制不同点:

        1 写磁盘文件不同

        2 bypass 机制不排序


shuffle 调优

1 spark.shuffle.file.buffer

    默认:32k

    作用:用于设置 shuffle wite task 的 bufferedOutputStream 的 buffer 缓冲大小;数据写入到磁盘前,先写入到 buffer 缓冲中,待缓冲用完后,再写入到磁盘

    建议:如果资源充足,增加这个参数大小,从而减小 shuffle write 过程溢写磁盘文件的次数,一般提升1%~5%

2 spark.reducer.maxSizeInFlight

    默认:48m

    作用:用于设置 shuffle read task 的buffer 缓冲大小,决定了每次能拉多少数据

    建议:如果内存资源充足,调大这个参数,减少拉取数据次数,也就可以减少网络传输次数,一般提升1%~5%

3 spark.shuffle.io.maxRetries 

    默认:3

    作用:shuffle read task从 shuffle write task 节点拉取数据,如果遇到网络原因拉取失败,最大重试次数,如果重试超过最大次数,还没有成功,那么任务失败

    建议:对于那些包含了特征耗时的 shffle 操作,增加重试次数,防止由于 full GC,或者网络不稳定原因导致任务失败

4 spark.shuffle.io.retryWait

    默认:5s

    作用:每次重试拉取时间间隔

    建议:建议增大,以增加 shuffle 的稳定

5 spark.shuffle.memoryFraction

    默认:0.2

    作用:Executor 内存中,分配级 shuffle read task 进行聚合操作的内存比例

    建议:如果内存充足且很少使用持久化操作,建议调高这个比例,给 shuffle read 的聚合操作更多的内存,以避免由于内存不足导致聚合操作频繁读写磁盘;合理设置,可提高性能 10%

6 spark.shuffle.manager

    默认:sort

    作用:用于设置 shuffle类型 sort,hash

    建议:SortShuffleManager 为默认值;如果业务不需要排序,那么可以把 bypass 默认值调大,或者使用优化后的 hashshufle

7 spark.shuffle.sort.bypassMergeThreshold 

    默认:200

    作用:触发 bypass 机制的阀值,如果 shuffle read task 的数量小于这个阀值,则 shuffle write 过程不会进行排序操作,而是直接按照未经优化的 HashShuffleManager 的方式去写数据,但是最后会将每个 task 产生的临时磁盘文件都合并成一个文件,并创建单独的索引文件

    建议:如果不需要排序操作,就把这个值调大,大于 shuffle read task 数量,那么就会启动 bypass 机制

8 spark.shuffle.consolidateFiles

    默认:false

    作用:如果使用 HashShuffleManager,该参数有效,如果设置为 true,那么就会启动 consolidate机制,会大副合并 shuffle write 输出的文件

Spark SQL是Apache Spark对SQL的支持部分,它允许用户通过结构化查询语言操作大规模数据集。在使用Spark SQL时,性能化通常涉及到以下几个方面的参数整: 1. **`spark.sql.shuffle.partitions`**:这是用于划分任务的数据分区数,增加此值可以提高并行处理能力,但也可能导致内存消耗增大。要找到合适的值,需要考虑可用内存、数据大小和机器资源。 2. **`spark.default.parallelism`**:默认的并行任务数,如果不清楚如何分配,可以将其设为executor的数量。过高可能导致溢出,过低则会限制效率。 3. **`spark.sql.execution.arrow.enabled`**:启用Arrow Columnar Memory,能提升数据读取速度,但需确保系统支持 Arrow。 4. **`spark.sql.streaming.checkpointLocation`**:检查点目录,定期保存运行状态以避免失败后的重新计算。合理选择位置有助于减少恢复时间。 5. **`spark.sql.autoBroadcastJoinThreshold`**:自动广播join阈值,超过这个大小的数据会被广播到所有节点。应根据数据量和网络带宽来整。 6. **`spark.memory.fraction`** 或 `spark.executor.memory`:内存管理配置,保证足够的内存给数据倾斜和中间结果存储。 7. **`spark.sql.queryExecution.arrowOptimization`**:开启化,对于大数据集可能会有显著提升。 为了,建议首先监控性能指标如CPU、内存使用情况和任务完成时间,并根据实际需求逐步整这些参数。同时,使用Spark SQL的内置分析工具(如`EXPLAIN`命令)来诊断性能瓶颈。最后,记得每次更改参数后都要测试其效果,因为最化的配置可能因数据、环境等因素而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值