数据倾斜的解决办法
产生原因
- 数据的key分化严重不均,造成一部分数据很多,一部分数据很少的局面
- 机器配置和数据量比例不合理,总会有key的数量超出机器处理能力,导致reduce卡顿
- 业务逻辑不合理导致:
- 分组 注:group by 优于distinct group 情形:group by 维度过小,某值的数过多 后果:处理某值的reduce非常耗时
- 去重 distinct count(distinct xx) 情形:某特殊值过多 后果:处理此特殊值的reduce耗时
- 连接 join 情形1:其中一个表较小,但是key集中 后果1:分发到某一个或几Reduce上的数据远高于平均值
- 连接 join 情形2:大表与大表,但是分桶的判断字段0值或空值过多 后果2:这些空值都由一个reduce处理,非常慢
具体表现(以常见的平台Hadoop和Spark为例)
Hadoop中的数据倾斜
Hadoop中直接贴近用户使用使用的时Mapreduce程序和Hive程序,虽说Hive最后也是用MR来执行(至少目前Hive内存计算并不普及),但是毕竟写的内容逻辑区别很大,一个是程序,一个是Sql,因此这里稍作区分。Hadoop中的数据倾斜主要表现在ruduce阶段卡在99.99%,一直99.99%不能结束。 这里如果详细的看日志或者和监控界面的话会发现:
- 有一个多几个reduce卡住
- 各种container报错OOM
- 读写的数据量极大,至少远远超过其它正常的reduce
- 伴随着数据倾斜,会出现任务被kill等各种诡异的表现。
- Hive的数据倾斜,一般都发生在Sql中Group和On上,而且和数据逻辑绑定比较深。
Spark中的数据倾斜
Spark中的数据倾斜也很常见,这里包括Spark Streaming和Spark Sql,表现主要有下面几种:
- Executor lost,OOM,Shuffle过程出错
- Driver OOM
- 单个Executor执行时间特别久,整体任务卡在某个阶段不能结束
- 正常运行的任务突然失败
- 补充:在Spark streaming程序中,数据倾斜更容易出现,特别是在程序中包含一些类似sql的join、group这种操作的时候。 因为Spark Streaming程序在运行的时候,我们一般不会分配特别多的内存,因此一旦在这个过程中出现一些数据倾斜,就十分容易造成OOM。
如何解决倾斜问题
调优参数
- hive.map.aggr=true:在map中会做部分聚集操作,效率更高但需要更多的内存。
- hive.groupby.skewindata=true:数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
- 起至关作用的是第二项,他分为了两个mapreduce,第一个在shuffle过程中partition时随机给key打标记,使其分布在不同的reduce上计算,但不能完成全部运算,所以需要第二次mapreduce整合回归正常的shuffle,由于数据分布不均问题在第一次时得到改善,所以基本解决数据倾斜问题。
针对key
- 在 map 阶段将造成倾斜的key 先分成多组,例如 aaa 这个 key,map 时随机在 aaa 后面加上 1,2,3,4 这四个数字之一,把 key 先分成四组,先进行一次运算,之后再恢复 key 进行最终运算。
group操作
- 能先进行 group 操作的时候先进行 group 操作,把 key 先进行一次 reduce,之后再进行 count 或者 distinct count 操作。
join操作
- join 操作中,使用 map join 在 map 端就先进行 join ,免得到reduce 时卡住。
- 以上4中方式,都是根据数据倾斜形成的原因进行的一些变化。要么将 reduce 端的隐患在 map 端就解决,要么就是对 key 的操作,以减缓reduce 的压力。总之了解了原因再去寻找解决之道就相对思路多了些,方法肯定不止这4种。
转载于:https://juejin.im/post/5b90db72e51d450e482b9eeb