數(shù)據(jù)傾斜解決思路詳解

數(shù)據(jù)傾斜是由于某個task被分配過多數(shù)據(jù),而比其他task需要更多的執(zhí)行時間(如幾十倍,幾百倍),導致其他task執(zhí)行完進入漫長等待的一種現(xiàn)象。

數(shù)據(jù)傾斜只會發(fā)生在多對多或一對多的數(shù)據(jù)分發(fā)的過程中,如spakr的shuffle操作中,在MapReduce中的reduce階段,

常見的算子類型為:join,group by 和窗口函數(shù)如row_number 。

這是因為這些算子會進行shuffle操作,產(chǎn)生一個key值,如group by的字段,join的on字段,

為了利用多臺機器的并發(fā)能力,會按這個key值取數(shù)范圍進行均衡的分發(fā),每臺機器盡量分到相同長度的取值范圍的key,

然后將這些有key值的數(shù)據(jù)的數(shù)據(jù)傳輸過去。

這時如果某個key范圍內(nèi)的數(shù)據(jù)量大大多于其他范圍的數(shù)據(jù)量,就會發(fā)生數(shù)據(jù)傾斜。

解決辦法:

解決數(shù)據(jù)傾斜的思路在于,先找到產(chǎn)生數(shù)據(jù)傾斜的算子操作,然后針對具體的算子,解決它單個key范圍被分到過多的數(shù)據(jù)的問題,

按key的類型,由簡便到復(fù)雜依次有以下幾種解決思路:

1.直接消滅傾斜的key。

2.直接避免shuffle操作,沒有了shuffle操作也就沒有了數(shù)據(jù)傾斜

3.通過增多task的數(shù)量,減小單個task內(nèi)的數(shù)據(jù)量,這個方法適用于某個key范圍的數(shù)據(jù)多的情況。

4.通過特殊處理key值,減小單個task內(nèi)的數(shù)據(jù)量,這個方法適用于某些特定的key值的數(shù)據(jù)過多的情況


第一個解決思路比較簡單,找到傾斜的key,直接過濾掉。就沒有傾斜問題了。這種操作的適用范圍很窄。比如一些空字符串,一些缺省值等等,本身在業(yè)務(wù)上能接受它們不參與操作。

如果發(fā)現(xiàn)造成傾斜的key是這些,就可以直接過濾,非常簡單粗暴,性價比最高。


如果該key不能被過濾,就考慮能否將shuffle操作避免掉。

比如join的時候使用廣播的方式,將其中一張表廣播到所有的機器節(jié)點上,這樣一個shuffle操作就變成了一個map操作。

廣播的方式(map join)適用于join的時候某一張表的數(shù)據(jù)量比較小的時候,如果兩張表都很大,則不適用這種方式。


如果不能避免shuffle操作也不能過濾傾斜的key值,那么我們就要從key值的類型入手,如果傾斜的key值是連續(xù)的,不是由單個key值引起的,就可以增大task的數(shù)量,

比如,修改shuffle產(chǎn)生的partition參數(shù)為更大,就可以使同一個范圍內(nèi)的key值分到不同機器上,

或者使key值重新排列,倒排或者其他方式,使他們不再連續(xù),分配到不同的機器上,就可以防止傾斜。


上述3個操作都比較簡單高效,但是應(yīng)用的場景有限,如果該key不能被過濾,也不能避免shuffle,而且是1個到多個不連續(xù)的key引起的,就需要做比較復(fù)雜的操作了。

如果是group by,就可以用兩階段聚合法,

將group by a 改成 group by a,b? ,然后再group by a

或者增加一個隨機數(shù)x,將a通過concat(x,a)改成b,將group by a 改成 group by b, 然后再聚合一次去掉x后的b,group by substr(b,length(x))?

如果是join操作,就需要分開join,將傾斜的數(shù)據(jù)和不傾斜的數(shù)據(jù)分成兩部分。

然后兩站表不傾斜的部分join得到第一張表。

傾斜的數(shù)據(jù),第一張較大的表:增加一個隨機數(shù)1-x,隨機數(shù)取決于你想把數(shù)據(jù)切成幾份。

得到 concat(x,a).?

另一張較小的表將每一行復(fù)制到x份(總共增加x-1份),然后按順序標上序號1到x,如下所示:

源數(shù)據(jù),傾斜的key值為a和b,

大表:aaaaa bbbbb?

小表:aaaa bbbb

原來的join最后得到40條數(shù)據(jù). 每個key分到20條

處理過key的表,

大表:1a 2a 2a 1a 2a 1b 2b 3b 3b 2b? (增加一個隨機數(shù)前綴1-3)

小表:

1a 2a 3a 1a 2a 3a 1a 2a 3a 1a 2a 3a 這n條數(shù)據(jù)都按順序附加一個1~x的前綴

1b 2b 3b 1b 2b 3b 1b 2b 3b 1b 2b 3b

生成40條數(shù)據(jù),每個key平均分到6.66條.

6.66條的計算公式是5/3*4,? 5是大表的key的條數(shù),有5個,增加隨機數(shù)之后,被分成了3份,得到了5/3 條,小表雖然也加了隨機數(shù)但是復(fù)制了x份,

所以小表的key還是4個,所以是:5/3*4

最后將傾斜部分的數(shù)據(jù)和不傾斜的部分的數(shù)據(jù)分別join之后再union起來就可以了。


當然,解決數(shù)據(jù)傾斜的不止這些方法,這些方法只是常用的,本質(zhì)還是打散集中在某臺機器,某個task的的數(shù)據(jù)量。只要能達到這個目的,就可以。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容