解决实际业务中出现的数据倾斜

解决Spark中出现的数据倾斜

使用重写UDAF完成Map端聚合来解决

业务背景:
为了求城市的热门栅格的相关属性 需要关联用户拉链表和城市栅格表来做分析
但是热门栅格的人数和非热门栅格的差别过大会导致数据倾斜

具体实现:

package com.exmaple
 
import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._

class ActionMapUDAF extends UserDefinedAggregateFunction {
  override def inputSchema: StructType = {
  //	定义输入格式
    StructType(
      StructField("action_datetime", StringType) ::
        StructField("action_info", StringType) :: Nil)
  }

  override def bufferSchema: StructType = {
  //	定义存储中间结果的状态格式
    StructType(StructField("hashmap", MapType(StringType, StringType)) :: Nil)
  }

  override def dataType: DataType = {
  //	最终的输出格式
    MapType(StringType, StringType)
  }

  override def deterministic: Boolean = {
  //	对给定的一组输入值,UDAF的输出值是否相同
    true
  }

  override def initialize(buffer: MutableAggregationBuffer): Unit = {
  //	初始化
    buffer(0) = Map()
  }

  override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
  //	Reduce的更新操作:如何根据一行新数据, 更新一个聚合buffer的中间结果
    val map1 = buffer.getAs[Map[String, String]](0)
    val key = input.getAs[String](0)
    val value = input.getAs[String](1)
    buffer(0) = map1 + (key -> value)
  }

  override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
  //	Reduce的merge操作:两个buffer结果合并到其中一个bufer上
    var mp1 = buffer1.getAs[Map[String, String]](0)
    var mp2 = buffer2.getAs[Map[String, String]](0)
    buffer1(0) = mp1 ++ mp2.map{ case (k, v) => k -> (v + "," + mp1.getOrElse(k, "")) }
  }

  override def evaluate(buffer: Row): Any = {
  //	最终的结果
    buffer.getAs[Map[String, String]](0)
  }
}

问题一:这种处理类似于Hive的Mapjoin 那么这个UDAF会导致OOM吗?

我们知道Hive的MapJoin是把小表一次性的全部读取到内存当中来进行处理 因为堆内存有限所以当表数据量大的时候会造成OOM

但是Spark在使用这个UDAF之前,一定是已经把数据读取读取到了栈空间内了 然后再进行聚合 这样会压缩数据的规模

当然 因为聚合离不开状态的存在 而状态一定会驻留在内存当中 如果这时遇到了OOM问题该如何处理?

方法一:增加读入数据的分区数 让每个Executor读取的数据减少 降低OOM的风险
方法二:增加执行内存的大小

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值