广播变量在spark中的用法以及数据倾斜问题的解决方法

本文介绍了Spark中广播变量的应用场景,其通过减少网络传输提升性能,并重点讲解了map-sidejoin在处理大规模join操作时的优势,如何在map任务本地解决数据倾斜问题,以提高join效率。
1. spark中的广播变量
  • 应用场景:广播变量用于在集群的各个节点的executor 中高效的分发一个只读的变量副本

  • 操作原理:创建一个广播变量时,spark会将变量序列化并发送到每一个executor,每一个executor存一个副本,而不需要每次执行任务重新重driver或其他节点来获取,spark任务涉及到对该变量的访问时就只需要从本地executor内存中来获取即可,避免了在网络中频繁的传输大量重复的数据

  • 目的: 就是为了减少冗余数据在网络中的传输,提升了分布式计算环境下的访问速度和整体的性能

  • 广播变量适合场景: 那些需要在多个任务中共享, 且数据量适中可以存在executor内存中的情况

2. 广播join (map-side join)  在map task 本地解决join
  • 应用场景: 在处理大规模的join操作时,其中一方的数据集明显较小,就是所谓的小表就可以通过广播join, 将小的数据集加载到每一个map task的executor的内存中,那种join操作中某些key对应的键的record数量远大于其他key的record数量,导致在reducer task 严重的负载不均衡问题

  • 操作原理:广播join 发生在map端非reduce 端无需通过网络传输shuffle就可以到达reduce 端,减少I/O,hive将小表的数据全部加载到map task 的内存中作为广播变量,然后对每一条大表的record ,在本地内存中查找是否有匹配的小表record ,并立即完成join操作,

    由于每个join 在每个map task内部独立完成 ,无需经过网络shuffle 就可以到达reduce 端,进而大大减少了网络传输和磁盘i/o,消除了因为数据倾斜造成的

  • 目的主要目的是利用小表数据可以被广播到所有的map task 内存的特点 提前在map 端完成了join 操作,避免了常规的join操作中需要的昂贵的shuffle过程,特别是适合于数据倾斜问题,显著提高了join的操作效率

    这种策略的前提是小表的数据必须要足够小,能够被全部加载到每个节点的内存中

  • 代码:

        
        def main(args: Array[String]): Unit = {
          /**
           * rdd 处理数据倾斜-广播join
           */
          val spark = SparkSession
            .builder()
            .appName("MapSideBroadcastJoin")
            .getOrCreate()
    
          // 假设已经读取了大表和小表的数据,并转换为RDD[(String, String)]
          // 大表
          val bigTable: RDD[(String, String)] = spark.sparkContext.textFile("hdfs://path/to/big_table.csv")
            .map(line => line.split(",")).map(arr => (arr(0), arr(1)))
    
          // 小表
          val smallTable: RDD[(String, String)] = spark.sparkContext.textFile("hdfs://path/to/small_table.csv")
            .map(line => line.split(",")).map(arr => (arr(0), arr(1)))
    
          // 将小表转换为本地集合并广播
          val smallTableBroadcast: Broadcast[Map[String, String]] = spark.sparkContext.broadcast(
            smallTable.collectAsMap().toMap
          )
    
          // 定义Map函数,执行Map-Side JOIN
          def joinWithSmallTable(bigRecord: (String, String)): Option[(String, (String, String))] = {
            smallTableBroadcast.value.get(bigRecord._1).map { smallValue =>
              (bigRecord._1, (bigRecord._2, smallValue))
            }
          }
    
          // 应用Map函数,过滤掉没有匹配的小表记录
          val joinedData: RDD[(String, (String, String))] = bigTable.flatMap(joinWithSmallTable)
    
          // 打印或进一步处理joinedData
          joinedData.foreach(println)
    
          spark.stop()

3 . reduce_side join

都是基于优化分布式计算思想

关于使用广播join  使用map-side 函数在map端进行merage 在本地executor 中完成join过程

减少网络传输, 以及减少磁盘的I/O

Spark中,数据倾斜(Data Skew)是指在数据处理过程中,某些数据分区的数据量过大,导致这些分区的数据处理速度远慢于其他分区,从而影响整个作业的性能和稳定性。数据倾斜问题在实际应用中比较常见,需要采取一些措施来解决。以下是一些解决数据倾斜问题方法: 1. 均衡数据分区。我们可以通过重新划分分区的方式来均衡数据分布,从而减少数据倾斜的发生。例如,可以使用repartition()方法对RDD或DataFrame进行重新分区,或者使用coalesce()方法将多个小分区合并成一个大分区。 2. 使用随机前缀法(Random Prefix)等技术。随机前缀法是一种比较常用的解决数据倾斜问题的技术,其主要思想是在数据处理之前给每个键值对添加一个随机前缀,从而使数据均匀地分布在不同的分区中。Spark的groupByKey()方法和reduceByKey()方法都提供了参数来支持随机前缀法。 3. 使用聚合操作。聚合操作(例如countByKey()、reduceByKey()等)可以将相同的键值对合并在一起,从而减少数据倾斜的发生。在进行聚合操作时,可以使用combineByKey()方法来控制每个分区的聚合方式。 4. 使用广播变量。如果某些变量在整个Job过程中都需要使用,可以使用广播变量将其缓存起来,从而避免数据倾斜广播变量可以将变量复制到每个节点上,从而减少数据倾斜的发生。 5. 使用第三方库。除了Spark自带的解决数据倾斜方法之外,还可以使用一些第三方库来解决数据倾斜问题。例如,可以使用Alibaba的DataX、eBay的Kylin等库来解决数据倾斜问题。 通过以上几种方法,可以有效地解决Spark中的数据倾斜问题,提高作业的性能和稳定性。在实际应用中,需要根据具体的场景和数据分布情况选择合适的方法解决数据倾斜问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值