数据倾斜与解决办法

hadoop数据倾斜

1)提前在map进行combine,减少传输的数据量
在Mapper加上combiner相当于提前进行reduce,即把一个Mapper中的相同key进行了聚合,减少shuffle过程中传输的数据量,以及Reducer端的计算量。
如果导致数据倾斜的key大量分布在不同的mapper的时候,这种方法就不是很有效了。
2)导致数据倾斜的key 大量分布在不同的mapper
(1)局部聚合加全局聚合。
第一次在map阶段对那些导致了数据倾斜的key 加上1到n的随机前缀,这样本来相同的key 也会被分到多个Reducer中进行局部聚合,数量就会大大降低。
第二次mapreduce,去掉key的随机前缀,进行全局聚合。
思想:二次mr,第一次将key随机散列到不同reducer进行处理达到负载均衡目的。第二次再根据去掉key的随机前缀,按原key进行reduce处理。
这个方法进行两次mapreduce,性能稍差。
(2)增加Reducer,提升并行度
JobConf.setNumReduceTasks(int)
(3)实现自定义分区
根据数据分布情况,自定义散列函数,将key均匀分配到不同Reducer

hive数据倾斜

怎么产生的数据倾斜
(1)不同数据类型关联产生数据倾斜
情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时。
后果:处理此特殊值的reduce耗时;只有一个reduce任务。默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。
解决方式:把数字类型转换成字符串类型
select * from users a
left outer join logs b
on a.usr_id = cast(b.user_id as string)
(2)控制空值分布
在生产环境经常会用大量空值数据进入到一个reduce中去,导致数据倾斜。
解决办法:
自定义分区,将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注意:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少
3)解决数据倾斜的方法?
(1)group by
注:group by 优于distinct group
解决方式:采用sum() group by的方式来替换count(distinct)完成计算。
(2)mapjoin(适用于小表JOIN大表的场景)
(3)开启数据倾斜时负载均衡
set hive.groupby.skewindata=true;
思想:就是先随机分发并处理,再按照key group by来分发处理。
操作:当选项设定为true,生成的查询计划会有两个MRJob。
第一个MRJob中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的原始GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
点评:它使计算变成了两个mapreduce,先在第一个中在shuffle过程partition时随机给 key打标记,使每个key随机均匀分布到各个reduce上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上。
所以需要第二次的mapreduce,这次就回归正常shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次mr中随机分布到各个节点完成。

spark数据倾斜

**数据倾斜产生原因**
我们以Spark和Hive的使用场景为例。
他们在做数据运算的时候会涉及到,count distinct、group by、join on等操作,这些都会触发Shuffle动作。一旦触发Shuffle,所有相同key的值就会被拉到一个或几个Reducer节点上,容易发生单点计算问题,导致数据倾斜。
一般来说,数据倾斜原因有以下几方面:
1)key分布不均匀;

在这里插入图片描述

2)建表时考虑不周
我们举一个例子,就说数据默认值的设计吧,假设我们有两张表:
user(用户信息表):userid,register_ip
ip(IP表):ip,register_user_cnt
这可能是两个不同的人开发的数据表。如果我们的数据规范不太完善的话,会出现一种情况:
user表中的register_ip字段,如果获取不到这个信息,我们默认为null;
但是在ip表中,我们在统计这个值的时候,为了方便,我们把获取不到ip的用户,统一认为他们的ip为0。
两边其实都没有错的,但是一旦我们做关联了,这个任务会在做关联的阶段,也就是sql的on的阶段卡死。
3)业务数据激增
比如订单场景,我们在某一天在北京和上海两个城市多了强力的推广,结果可能是这两个城市的订单量增长了10000%,其余城市的数据量不变。
然后我们要统计不同城市的订单情况,这样,一做group操作,可能直接就数据倾斜了。

**解决数据倾斜思路**
很多数据倾斜的问题,都可以用和平台无关的方式解决,比如更好的数据预处理,异常值的过滤等。因此,解决数据倾斜的重点在于对数据设计和业务的理解,这两个搞清楚了,数据倾斜就解决了大部分了。
1)业务逻辑
我们从业务逻辑的层面上来优化数据倾斜,比如上面的两个城市做推广活动导致那两个城市数据量激增的例子,我们可以单独对这两个城市来做count,单独做时可用两次MR,第一次打散计算,第二次再最终聚合计算。完成后和其它城市做整合。
2)程序层面
比如说在Hive中,经常遇到count(distinct)操作,这样会导致最终只有一个Reduce任务。
我们可以先group by,再在外面包一层count,就可以了。比如计算按用户名去重后的总用户量:
(1)优化前 只有一个reduce,先去重再count负担比较大:
select name,count(distinct name)from user;
(2)优化后
// 设置该任务的每个job的reducer个数为3个。Hive默认-1,自动推断。
set mapred.reduce.tasks=3;
// 启动两个job,一个负责子查询(可以有多个reduce),另一个负责count(1)select count(1) from (select name from user group by name) tmp;
3)调参方面
Hadoop和Spark都自带了很多的参数和机制来调节数据倾斜,合理利用它们就能解决大部分问题。
4)从业务和数据上解决数据倾斜
很多数据倾斜都是在数据的使用上造成的。我们举几个场景,并分别给出它们的解决方案。
有损的方法:找到异常数据,比如ip为0的数据,过滤掉
无损的方法:对分布不均匀的数据,单独计算
先对key做一层hash,先将数据随机打散让它的并行度变大,再汇集
数据预处理
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值