数据倾斜常见原因和解决办法

数据倾斜常见原因和解决办法,第1张

数据倾斜常见原因和解决办法

数据倾斜在MapReduce编程模型中十分常见,多个节点并行计算,如果分配的不均,就会导致长尾问题(大部分节点都完成了任务,一直等待剩下的节点完成任务),本文梳理了常见的发生倾斜的原因以及相应的解决办法。

1.map端发生数据倾斜

产生原因:
  1. 读取数据时,上游文件大小分布不均,存在大量小文件。导致在读入数据时读小文件的maptask很快结束了,而读大文件的maptask进度可能进度才刚开始。

  2. map端做聚合的时候,由于数据存在大量的count distinct,我们通过combiner在map端提前做聚合的时候,热点key被放大N倍( N = count distinct 数),其所对应的maptaskconbiner *** 作时间被拉长。

解决办法:

对于1的问题,我们可以通过提前合并小文件和参数调优,一个是maptask的数量,另一个是maptask读取的文件数量限制。

对于2的问题,我们可以通过使用distribute by rand(),将map里面的值再进行打乱分发。

2.join时发生数据倾斜

首先我们可以了解一下mapreduce框架下的join的实现原理

感兴趣的同学可以去看美团的文章。

Hive SQL的编译过程 - 美团技术团队

产生原因:
  1. 大表与小表join,可能存在小表的某个key

  2. 数据分布不均,且数据倾斜问题是由key中存在的空值导致的。

  3. 数据分布不均,且数据倾斜问题是由热点key导致的。

解决办法:

对于1的问题,可以设置自动mapjoin的方式来规避。

对于2的问题,我们可以通过nvl(key,rand()*9999)或者coalesce()函数,将空值替换为key中不会存在的值,再被过滤,注意这里的随机值必须要key中不可能存在的才行,否则就会污染数据。

对于3的问题,我们可以通过先将数据根据一定的规则,分为热点数据和非热点数据,这里的筛选规则只能根据具体情况来定。一般来说热点key的数量应该是比较少的,所以可以通过mapjoin完成,而非热点key的数据根据具体情况是否使用mapjoin。

3.reduce时发生倾斜

Reduce端负责的是对 Map端梳理后的有序 key-value键值对进行聚 合,即进行 Count、 Sum、 Avg 等聚合 *** 作,得到最终聚合的结果。

产生原因:
  1. 动态分区数过多时可能造成小文件过多,从而引起 Reduce 端长尾。

  2. Map 端直接做聚合时出现 key 值分布不均匀,造成 Reduce 端长尾。

  3. 一段代码中存在多个distinct,数据会被分发多次,不仅会造成数据膨胀 N 倍,还会把长尾现象放大 N 倍。

解决办法:

对于1的问题,动态分区通过map阶段完成还是通过reduce阶段完成。可以通过动态分区的数量来判断。当动态分区数较多时,可以通过开启reduce任务,经过shuffle之后,将数据发到了reduce端整合再写入到分区当中,如果分区较少,就没必要reduce,浪费资源。

对于2的问题,可以参考join中的问题3的解决办法,将热点数据与非热点数据分开处理。

对于3的问题,使用distinct的原因是该字段不是最细粒度,如果我们将问题转化为不使用最细粒度即可 。比如我要求通过订单表计算每日乘客数,我们可以通过group先计算每日每个乘客的订单数量,此时的粒度是乘客,在通过判断每个乘客数量是否>0,来sum乘客数量,完成统计,从而避免了使用distinct。

总结

数据倾斜主要由于数据分布不均导致的,我们所有 *** 作的目的就是将数据分布向平均靠拢,而这个 *** 作是以牺牲代码的可读性来换取。所以我们在调优时要同时考虑运行时间和代码可读性两方面。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5683367.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存