美文网首页
随机数为什么能解决数据倾斜和实现负载均衡

随机数为什么能解决数据倾斜和实现负载均衡

作者: 呆板板板板 | 来源:发表于2019-12-14 21:16 被阅读0次

        我的一位同学,工作上遇到这么一个问题,问我怎么解决。问题是这样的:

“Spark写 Hive 的时候,有390多个文件是1k多,其他几个大文件都是几百 M 或者几个 G”

        这种情况,明显是数据倾斜了,还是严重的倾斜,我给他的一句话就是,在做计算之前,先加随机数前缀,让这些数据均匀分布到各个节点,然后再去掉随机数前缀,最后再进行计算。我们都知道,大数据的计算框架都坚持的一个理念,就是“移动数据不如移动计算”,就是说,在计算过程中移动数据不如将计算任务分配到数据所在的节点上,计算是直接获取节点本地数据进行计算的。要实现计算的高效,前提得有均匀的数据,木桶能装多少水,取决于最短的那块板,而整体的计算速度,则取决于计算时间最长的那个节点,所以,要让集群做高效的计算,在计算之前要保证数据不倾斜(分布均匀),有这前提,各节点的计算(并行计算)时间都差不多,拖后腿的节点不会那么严重。

        哈哈,废话有点多了,言归正传。很多人只知道随机数能解决数据倾斜和实现负载均衡这么回事,但不知道为什么?本文将围绕随机数展开叙述。

        假设我们用来做计算的节点有50个,用以下代码做例子:

图 1 生成100000条1到 50的随机数

代码中是假设每个(←特别指明“每个”)split中的数据有100000条,生成的随机数以前缀(或者后缀)的形式添加到这100000条数据中,然后写个Partitioner(分区器),只用前缀(后缀)进行分区。

        就拿HashPartitioner来说吧,对前缀进行Hash后,对进行Reduce的节点个数进行求模(对50求模),求模后的结果就是分区号,进行Shuffle的时候,Reduce端(Reduce Task)会根据分区号拉取对应分区的数据,在Reduce端进行去除前缀后本地化,这样就实现了数据均匀分布在各个节点上。你可能会问为什么是均匀?或者会问随机数问什么能让数据均匀分布在各个节点上?答案就是这篇文章的目的所在。

        均不均匀,那就看随机数的生成均不均匀,除了看随机数的底层源码之外,那就是对随机数的生成结果进行可视化展示,直观的看其均不均匀,下图就是上面代码的执行结果,借助了 Python 的 matplotlib,样式有点low,但是不影响说明问题:

图 2 随机数生成结果直方图效果

是不是很均匀?

        跟我同学说了之后,他说,数据中有uuid,也是随机数啊。我说那也不行,还是再加个前缀,为什么呢?因为uuid是已经生成的了,是死的了,而且uuid能被重复利用。拿点击流举个例子,当使用同一设备点击那些需要记录uuid的不同埋点,触发不同的事件,记录的还是同一个uuid,往极端的想,只有一台设备点击了这些埋点,触发了很多事件,那是不是很多条数据记录的都是同一个uuid,当用这些数据进行计算的时候,使用uuid进行hash是不是一样的,那是不是这些数据都会在同一个partition,是不是还是数据倾斜了,所以说生成后的随机数就不能再用来解决数据倾斜了,除非它们都是唯一的,为什么,自己琢磨。

        其实本文还引申了另一个解决数据倾斜的方案,不知道大家有没有发现,就是双重聚合。就是在添加前缀后的Reduce端是一个聚合,后面如果再进行聚合计算,那又是一个聚合。双重聚合不在本期文章的范围,所以不再做过多的累赘。到这应该也能知道为什么能实现负载均衡了吧。

--大佬不喜勿喷,欢迎留言指出文章问题所在

相关文章

网友评论

      本文标题:随机数为什么能解决数据倾斜和实现负载均衡

      本文链接:https://www.haomeiwen.com/subject/ohfhnctx.html