【面试】数据倾斜

109 阅读2分钟

数据倾斜(Data Skew)


1. 在哪些场景会遇到数据倾斜

  • Elasticsearch 聚合查询:某些字段的值高度集中,导致部分分片数据量过大,查询时间变长。
  • Kafka 消费端:某些 key 过于集中,导致个别 partition 的消费压力远大于其他 partition。
  • 分布式计算(如 Spark/Flink/Hive) :某个 key 频繁出现,导致某个计算节点的数据远多于其他节点,引发计算瓶颈。

2. 数据倾斜的成因

数据倾斜通常是由数据分布不均衡造成的,具体原因包括:

  1. Key 值分布不均

    • 例如,在 Spark/Flink 进行 groupByjoin 时,如果某些 Key 出现频率远高于其他 Key,就会导致数据集中到某些节点上。
    • Elasticsearch 中,基于 term 的聚合查询可能会导致某个分片查询压力过大。
  2. 默认分区策略不合理

    • 例如,Kafka 生产数据时默认使用 Key 进行分区,如果部分 Key 过热,数据会集中到某些分区,导致消费端处理不均衡。
  3. 数据倾斜导致的计算瓶颈

    • 在 Spark Shuffle 过程中,某个 Task 处理的数据远超其他 Task,导致计算延迟,甚至导致 OOM(内存溢出)。
    • 在 Elasticsearch 查询时,部分分片的查询压力远大于其他分片,导致整体查询变慢。

3. 解决方案

不同场景下,数据倾斜的解决方案也不同:

(1)减少 Key 的热点

  • 随机前缀/哈希散列

    • groupByjoin 之前,给 Key 添加一个随机前缀,增加数据分布的随机性,比如 key + random(0, N)
    • 在 Elasticsearch 查询时,可以使用 composite aggregation 来避免单个分片负载过高。
  • 热点 Key 拆分

    • 对于极少数高频 Key,可以手动拆分成多个 Key 处理,后续再合并结果。

(2)优化分区策略

  • Kafka 分区优化

    • 采用自定义分区策略,让高频 Key 分散到多个 Partition。
    • 增加 Partition 数量,提高并发消费能力。
  • Spark/Flink 数据重分区

    • repartition(n):强制数据均匀分布,增加计算节点负载均衡。
    • salting:在 key 上加随机数后 groupBy,减少数据热点。

(3)调整计算逻辑

  • 本地聚合后再全局聚合

    • 例如在 Spark 计算中,可以先对数据进行 map-side 预聚合,减少数据传输量,然后再进行全局聚合。
    • 在 Elasticsearch 里,可以使用 pre-filter 方式减少查询范围,降低查询压力。
  • 调整 SQL 执行策略

    • 在 Hive 或 SparkSQL 中,可以使用 skew join hint,让 Spark 采用 广播 joinbroadcast join)而不是 shuffle join,减少数据倾斜的影响。