Spark数据倾斜-采样倾斜key并分拆join操作-详细图解与代码
本文修改自[1]中的方案六。
?
下面的方案簡述來自[1]
方案適用場景:兩個(gè)RDD/Hive表進(jìn)行join的時(shí)候,如果數(shù)據(jù)量都比較大,無法采用“解決方案五”,那么此時(shí)可以看一下兩個(gè)RDD/Hive表中的key分布情況。如果出現(xiàn)數(shù)據(jù)傾斜,是因?yàn)槠渲心骋粋€(gè)RDD/Hive表中的少數(shù)幾個(gè)key的數(shù)據(jù)量過大,而另一個(gè)RDD/Hive表中的所有key都分布比較均勻,那么采用這個(gè)解決方案是比較合適的。
方案實(shí)現(xiàn)思路:?
* 對(duì)包含少數(shù)幾個(gè)數(shù)據(jù)量過大的key的那個(gè)RDD,通過sample算子采樣出一份樣本來,然后統(tǒng)計(jì)一下每個(gè)key的數(shù)量,計(jì)算出來數(shù)據(jù)量最大的是哪幾個(gè)key。
* 然后將這幾個(gè)key對(duì)應(yīng)的數(shù)據(jù)從原來的RDD中拆分出來,形成一個(gè)單獨(dú)的RDD,并給每個(gè)key都打上n以內(nèi)的隨機(jī)數(shù)作為前綴,而不會(huì)導(dǎo)致傾斜的大部分key形成另外一個(gè)RDD。
* 接著將需要join的另一個(gè)RDD,也過濾出來那幾個(gè)傾斜key對(duì)應(yīng)的數(shù)據(jù)并形成一個(gè)單獨(dú)的RDD,將每條數(shù)據(jù)膨脹成n條數(shù)據(jù),這n條數(shù)據(jù)都按順序附加一個(gè)0~n的前綴,不會(huì)導(dǎo)致傾斜的大部分key也形成另外一個(gè)RDD。
* 再將附加了隨機(jī)前綴的獨(dú)立RDD與另一個(gè)膨脹n倍的獨(dú)立RDD進(jìn)行join,此時(shí)就可以將原先相同的key打散成n份,分散到多個(gè)task中去進(jìn)行join了。
* 而另外兩個(gè)普通的RDD就照常join即可。
* 最后將兩次join的結(jié)果使用union算子合并起來即可,就是最終的join結(jié)果。
方案實(shí)現(xiàn)原理:對(duì)于join導(dǎo)致的數(shù)據(jù)傾斜,如果只是某幾個(gè)key導(dǎo)致了傾斜,可以將少數(shù)幾個(gè)key分拆成獨(dú)立RDD,并附加隨機(jī)前綴打散成n份去進(jìn)行join,此時(shí)這幾個(gè)key對(duì)應(yīng)的數(shù)據(jù)就不會(huì)集中在少數(shù)幾個(gè)task上,而是分散到多個(gè)task進(jìn)行join了。具體原理見下圖。
方案優(yōu)點(diǎn):對(duì)于join導(dǎo)致的數(shù)據(jù)傾斜,如果只是某幾個(gè)key導(dǎo)致了傾斜,采用該方式可以用最有效的方式打散key進(jìn)行join。而且只需要針對(duì)少數(shù)傾斜key對(duì)應(yīng)的數(shù)據(jù)進(jìn)行擴(kuò)容n倍,不需要對(duì)全量數(shù)據(jù)進(jìn)行擴(kuò)容。避免了占用過多內(nèi)存。
方案缺點(diǎn):如果導(dǎo)致傾斜的key特別多的話,比如成千上萬個(gè)key都導(dǎo)致數(shù)據(jù)傾斜,那么這種方式也不適合。
?
?
美團(tuán)給出的這個(gè)方案的圖解不是太清楚,所以我根據(jù)代碼在原有圖基礎(chǔ)上做了大量的標(biāo)注:
由于美團(tuán)給出的代碼是2016年的,那個(gè)時(shí)候的spark版本非常舊,并且有很多bug
是不是覺得看得見摸不著?呵呵~我已經(jīng)將其在Spark3.0下面調(diào)試+補(bǔ)充完整:
優(yōu)化前的完整Java工程
優(yōu)化后的完整Java工程
Reference:
[1]Spark性能優(yōu)化指南——高級(jí)篇
總結(jié)
以上是生活随笔為你收集整理的Spark数据倾斜-采样倾斜key并分拆join操作-详细图解与代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何免费破解BBE Sonic Swee
- 下一篇: excel中npv公式怎么用? Exce