Bootstrap

大数据面试之路 (一) 数据倾斜

记录大数据面试历程

数据倾斜

 大数据岗位 ,数据倾斜面试必问的一个问题。

一、数据倾斜的表现与原因

  1. 表现

    • 某个或某几个Task执行时间过长,其他Task快速完成。

    • Spark/MapReduce作业卡在某个阶段(如reduce阶段),日志显示少数Task处理大量数据。

    • 资源利用率不均衡(如CPU、内存集中在某些节点)。

  2. 常见场景

    • Key分布不均:如某些Key对应的数据量极大(如用户ID为空的记录、热点事件)。

    • 数据分区策略不合理:Hash分区时Key冲突,或Range分区时范围划分不均衡。

    • 业务逻辑导致倾斜:如大表Join小表时小表广播失败,或笛卡尔积操作。

二、检测数据倾斜的方法 

  1. 日志分析

    • 查看任务执行时间分布(如Spark UI的Stage详情)。

    • 检查Shuffle读写数据量(如Shuffle Read/Write Records)。

  2. 抽样统计

    • 对Key进行采样,统计Top N高频Key(如用countByKeysample)。

  3. 监控工具

    • 使用Ganglia、Prometheus等监控节点资源负载。

三、通用解决方案

1. 预处理:过滤或隔离倾斜数据

  • 过滤异常Key:直接删除无意义的倾斜Key(如空值、测试数据)。

  • 分离热点数据:将高频Key单独处理,与非倾斜数据合并结果。

-- 示例:将热点用户的行为日志单独处理
SELECT * FROM logs WHERE user_id = 'hot_user' -- 单独处理
UNION ALL
SELECT * FROM logs WHERE user_id != 'hot_user' -- 正常处理 

 2. 调整Key分布

 增加随机前缀(Salting):对Key添加随机数,分散数据到不同分区。

# Spark示例:对倾斜Key添加随机前缀
skewed_rdd = rdd.map(lambda x: (x[0] + "_" + str(random.randint(0, 9)), x[1])) 

 两阶段聚合

  1. 对Key加随机前缀,局部聚合;

  2. 去掉前缀,全局聚合。

3. 优化Shuffle过程 

  • 提高并行度:增加分区数(如spark.sql.shuffle.partitions=2000)。

  • 使用Combiner:在Map端预聚合(如ReduceByKey替代GroupByKey)。

  • 广播小表:在Join时,将小表广播到所有Executor,避免Shuffle。

4. 使用特定框架优化 

  • Spark AQE(Adaptive Query Execution)
    Spark 3.0+ 支持动态合并倾斜分区(spark.sql.adaptive.skewJoin.enabled=true)。

  • Flink KeyBy前加盐:类似Spark的随机前缀方法。

  • Hive参数调优
    set hive.map.aggr=true; (Map端聚合)
    set hive.groupby.skewindata=true; (生成两个MR Job分散负载)。

 四、场景化解决方案

 场景1:Join操作倾斜

 方案1:将小表广播

-- Spark SQL广播Join
SELECT /*+ BROADCAST(small_table) */ * 
FROM big_table JOIN small_table ON big_table.key = small_table.key; 

 方案2:拆分倾斜Key

若大表和大表Join且某些Key倾斜:

  1. 提取倾斜Key单独Join;

  2. 非倾斜Key正常Join;

  3. 合并结果

场景2:Group By/Aggregation倾斜 

方案:两阶段聚合(加盐与去盐 

-- 第一阶段:对Key加随机后缀,局部聚合
SELECT key || '_' || suffix AS salted_key, SUM(value) 
FROM table 
GROUP BY key || '_' || suffix;

-- 第二阶段:去除后缀,全局聚合
SELECT REPLACE(salted_key, '_*', '') AS key, SUM(sum_value) 
FROM temp_table 
GROUP BY REPLACE(salted_key, '_*', '');

 场景3:数据源倾斜

方案:调整文件分区 

  • 写入数据时使用合理的分区策略(如按时间+哈希混合分区)。

  • 对小文件合并,对大文件拆分。

五、预防数据倾斜的设计原则 

  1. 合理选择分区键:避免选择基数低或分布不均的字段。

  2. 数据预分析:ETL阶段提前统计Key分布,识别潜在倾斜。

  3. 动态调整:利用AQE(自适应查询执行)等自动化优化机制。

 面试回答示例

问题:如何处理Spark作业中的数据倾斜?
回答

  1. 定位倾斜:通过Spark UI查看Stage中Task的数据量分布,找到倾斜的Key。

  2. 过滤无效数据:如删除空Key或异常值。

  3. 调整Key分布:对倾斜Key加随机前缀,分两阶段聚合。

  4. 优化Shuffle:提高shuffle.partitions,使用广播Join。

  5. 框架特性:开启Spark AQE,自动合并倾斜分区。

  6. 举例:在最近的项目中,某用户行为日志的UserID存在热点,通过加盐将原本集中在1个分区的数据分散到10个分区,作业时间从2小时缩短至15分钟。

数据倾斜调优 

更多信息请参 阿里云帮助中心 

 数据倾斜调优_云原生大数据计算服务 MaxCompute(MaxCompute)-阿里云帮助中心

;