数据倾斜
就是在计算数据的时候,数据的分散度不够,导致大量的数据集中到了集群中的一台或者几台机器上计算,而集群中的其他节点空闲。这些倾斜了的数据的’计算速度远远低于’平均计算速度,导致整个计算过程过慢。
产生原理:
以Spark和Hive的使用场景为例数据运算的时候会涉及到,'count distinct、group by、join on'等操作,这些都会触发'Shuffle'动作。一旦触发Shuffle,所有'相同key'的值就会被拉到'一个或几个Reducer'节点上,容易发生单点计算问题,导致数据倾斜。
数据倾斜原因有:
- key分布不均匀
- 业务数据本身的特性
- 建表时考虑不周
- 某些SQL语句本身就有数据倾斜
解决:
要么将 reduce 端的隐患在 map 端就解决,要么就是对 key 的操作,以减缓reduce 的压力
MapReduce阶段:
-
导致数据倾斜的数据分布分布在相同的mapper
- 提前在map进行combine,减少传输的数据量
即把一个Mapper中的相同key进行了聚合,减少shuffle过程中传输的数据量,以及Reducer端的计算量
- 提前在map进行combine,减少传输的数据量
-
导致数据倾斜的数据分布分布在不同的Mapper
- 增加Reducer,提升并行度
- 根据数据分布情况,自定义散列函数,将key均匀分配到不同Reducer
-
小表join大表:
问题:
小表key值集中,shuffle全到一个reduce
解决:
使用 MapJoin把小表全部加载到内存在map端进行join。如果需要的数据在 Map 的过程中可以访问到则不再需要Reduce -
大表join小表
问题:
大表与大表join,但是分桶的判断字段0值或空值过多,会交给同一个reduce处理
解决:
给null换成一个字符串加随机数,null本身无意义,加上后对结果无影响
代码层面:
在Hive中,经常遇到count(distinct)操作,这样会导致最终只有一个Reduce任务。我们可以先group by,再在外面包一层count,就可以了
数据层面:
- 有损的方法:
- 找到异常数据,比如ip为0的数据,过滤掉
- 无损的方法:
- 对分布不均匀的数据,单独计算
- 先对key做一层hash,先将数据随机打散让它的并行度变大,再汇集