一起学Spark(13) -- 数据 Shuffle 与分区器

许多转换操作需要在集群中shuffle数据,包括join,各种ByKey等。所有这些操作都很消耗性能,因为它们可能需要对整个数据集进行shuffle,排序以及重新分区。

但是有一个小技巧可以提高性能,即预分区。如果rdd已分区,就能避免数据shuffle,因为假设rdd已分区,那么特定的键值就会在同一个分区内,因此能在本机进行处理,这种方式就不需要通过网络做数据shuffle了。

val partitionRDD = pairRDD.partitionBy(new HashPartitioner(3))
val joinedRDD = partitionRDD.join(otherRDD)

已分区的RDD将分区器传给生成的RDD,这个RDD将在worker中进行本机处理,只有那个未分区RDD需要排序,并装载到合适的节点。可进一步优化如下:

val partitionRDD = pairRDD.partitionBy(new HashPartitioner(3))
val otherRDD = partitionedRDD.mapValues(value => value + 1)
val joinedRDD = partitionedRDD.join(ohterRDD)

在python中数据重新混洗分区

partitionedRDD = rdd.repartition(n) #n 是重新分区的数量,这会造成数据重新混洗
#如果要减少分区,则coalesce比repartition 更高效,因为coalesce 没有打乱数据
partitionedRDD = rdd.coalesce(n)

SPARK 分区器:目前有两种内置的分区器 HashPartitioner 和 RangePartitioner,默认选择方式是:
1.当任何输入的RDD用到了某一分区器,输出的RDD也会用此分区器

2.否则,在Pair RDD情形下,默认使用 HashPartitioner

HashPartitioner 基于键(key)的哈希吗(hash code)把值分布到各个分区上。通过计算键的哈希码与分区数的模,得到分区索引值,在计算中也需要考虑到哈希码的正负情况。
RangePartitioner 根据范围对可排序项进行分区。对RDD 内容进行取样能决定大致的范围区间,最终的分区数可能要小于配置的分区数。分区数至少应当等于集群分配给应用程序的cpu核心数,建议设为cpu数的 2 - 4 倍。
也可以自定义分区器

注:有一些操作比如 map,flatMap 也会影响分区,在map操作中,可以改变一个PairRDD中的键,这样分区就会发生变化。这种情况下,生成的RDD将设有分区集。可以用mapValues 以及 faltMapValues 处理以及保留分区器。

shuffle数据:shuffle过程严重影响性能是因为它涉及数据排序,重分区,网络传输时的序列化和反序列化,为减少I/O带宽及磁盘I/O操作,还要对数据进行压缩。在spark中,可以引入中间的merge阶段输出少一点但大一些的文件。这个阶段就叫做shuffle文件合并。所有运行在相同cpu核上的map任务都将输出相同的shuffle文件。要启动shuffle文件合并,必须把spark.shuffle.consolidateFiles 设置为 true

在python 中不能将 HashPartitioner 对象传递给partitionBy,只需要把需要的分区数传递过去

pairRDD.partitionBy(100)   #100分区

算子与shuffle:
groupByKey : 特定键的所有值必须在一个任务中进行处理。为达到这个目的,整个数据被shuffle,特定键的所有单词被发送到一个节点。
reduceByKey : 算子先被应用到单台机器上的一个键的全部值,处理后得到的中间结果随后会在集群中发送。性能比groupByKey 更好些。

aggregateByKey : 用法其实跟combineByKey 是一样的,其实aggregateByKey 内部是通过调用 combineByKey 实现的。唯一不同在于aggregateByKey 通过创造零值替代 combineByKey 中的第一个函数 createCombiner。aggregateByKey 避免了创建大量的对象,同时省略了额外的map转换步骤,所以相对 reduceByKey 来说又更高效一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值