赞
踩
目录
数据倾斜是一种很常见的问题(依据二八定律),简单来说,比方WordCount中某个Key对应的数据量非常大的话,就会产生数据倾斜,导致两个后果:
Shuffle时,需将各节点的相同key的数据拉取到某节点上的一个task来处理,若某个key对应的数据量很大就会发生数据倾斜。比方说大部分key对应10条数据,某key对应10万条,大部分task只会被分配10条数据,很快做完,个别task分配10万条数据,不仅运行时间长,且整个stage的作业时间由最慢的task决定。
数据倾斜只会发生在Shuffle过程,以下算法可能触发Shuffle操作:
distinct:
distinct的操作其实是把原RDD进行map操作,根据原来的key-value生成为key,value使用null来替换,并对新生成的RDD执行reduceByKey的操作,也就是说,Distinct的操作是根据key与value一起计算不重复的结果.只有两个记录中key与value都不重复才算是不重复的数据。
groupByKey:
groupByKey会将RDD[key,value] 按照相同的key进行分组,形成RDD[key,Iterable[value]]的形式, 有点类似于sql中的groupby,例如类似于mysql中的group_concat
reduceByKey:
reduceByKey,就是将key相同的键值对,按照Function进行计算。如代码中就是将key相同的各value进行累加。得到的结果就是类似于[(key2,2), (key3,1), (key1,2)] 形式。
aggregateByKey 函数:
对PairRDD中相同的Key值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey'函数最终返回的类型还是PairRDD,对应的结果是Key和聚合后的值,而aggregate函数直接返回的是非RDD的结果。
join:
join类似于SQL的inner join操作,返回结果是前面和后面集合中配对成功的,过滤掉关联不上的。
cogroup:
对两个RDD中的kv元素,每个RDD中相同key中的元素分别聚合成一个集合。与reduceByKey不同的是针对两个RDD中相同的key的元素进行合并。
repartition:
返回一个恰好有numPartitions个分区的RDD,可以增加或者减少此RDD的并行度。内部,这将使用shuffle重新分布数据,如果你减少分区数,考虑使用coalesce,这样可以避免执行shuffle
以上等等。
步骤一: 看数据倾斜发生在哪个stage(也就是看以上算子出现在哪个阶段)。yarn-client模式下查看本地log或Spark Web UI中当前运行的是哪个stage;yarn-cluster模式下,通过Spark Web UI查看运行到了哪个Stage。
主要看最慢的Stage各task分配的数据量,来确定是否是数据倾斜。
步骤二:根据Stage划分,推算倾斜发生的代码(必然有Shuffle类算子)。简单实用方法:只要看到shuffle类算子或Spark SQL的SQL语句会有Shuffle类的算子的句子,就可以知道该地方划分为前后两个Stage。(用Python的PySpark接口,Spark Web UI会查看task在源码中的行数,Java或者Scala 同理。)
实际中,需综合着对业务全盘考虑,可先用方案一和二进行预处理,同时在需要Shuffle的操作提升Shuffle的并行度,最后针对数据分布选择后面方案中的一种或多种。实际中需要对数据和方案思路理解灵活应用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。