Spark-RDD分區(qū)

RDD分區(qū)

在分布式程序中,通信的代價(jià)是很大的睁枕,因此控制數(shù)據(jù)分布以獲得最少的網(wǎng)絡(luò)傳輸可以極大地提升整體性能搜变。所以對(duì)RDD進(jìn)行分區(qū)的目的就是減少網(wǎng)絡(luò)傳輸?shù)拇鷥r(jià)以提高系統(tǒng)的性能凤巨。

RDD的特性

在講RDD分區(qū)之前,先說一下RDD的特性男摧。

RDD宾舅,全稱為Resilient Distributed Datasets,是一個(gè)容錯(cuò)的彩倚、并行的數(shù)據(jù)結(jié)構(gòu)筹我,可以讓用戶顯式地將數(shù)據(jù)存儲(chǔ)到磁盤和內(nèi)存中,并能控制數(shù)據(jù)的分區(qū)帆离。同時(shí)蔬蕊,RDD還提供了一組豐富的操作來操作這些數(shù)據(jù)。在這些操作中哥谷,諸如map岸夯、flatMap、filter等轉(zhuǎn)換操作實(shí)現(xiàn)了monad模式们妥,很好地契合了Scala的集合操作猜扮。除此之外,RDD還提供了諸如join监婶、groupBy旅赢、reduceByKey等更為方便的操作(注意齿桃,reduceByKey是action,而非transformation)煮盼,以支持常見的數(shù)據(jù)運(yùn)算短纵。

通常來講,針對(duì)數(shù)據(jù)處理有幾種常見模型僵控,包括:Iterative Algorithms香到,Relational Queries,MapReduce报破,Stream Processing悠就。例如Hadoop MapReduce采用了MapReduces模型,Storm則采用了Stream Processing模型充易。RDD混合了這四種模型理卑,使得Spark可以應(yīng)用于各種大數(shù)據(jù)處理場(chǎng)景。

RDD作為數(shù)據(jù)結(jié)構(gòu)蔽氨,本質(zhì)上是一個(gè)只讀的分區(qū)記錄集合藐唠。一個(gè)RDD可以包含多個(gè)分區(qū),每個(gè)分區(qū)就是一個(gè)dataset片段鹉究。RDD可以相互依賴宇立。如果RDD的每個(gè)分區(qū)最多只能被一個(gè)Child RDD的一個(gè)分區(qū)使用,則稱之為narrow dependency自赔;若多個(gè)Child RDD分區(qū)都可以依賴妈嘹,則稱之為wide dependency。不同的操作依據(jù)其特性绍妨,可能會(huì)產(chǎn)生不同的依賴润脸。例如map操作會(huì)產(chǎn)生narrow dependency,而join操作則產(chǎn)生wide dependency他去。
Spark之所以將依賴分為narrow與wide毙驯,基于兩點(diǎn)原因。

首先灾测,narrow dependencies可以支持在同一個(gè)cluster node上以管道形式執(zhí)行多條命令爆价,例如在執(zhí)行了map后,緊接著執(zhí)行filter媳搪。相反铭段,wide dependencies需要所有的父分區(qū)都是可用的,可能還需要調(diào)用類似MapReduce之類的操作進(jìn)行跨節(jié)點(diǎn)傳遞秦爆。

其次序愚,則是從失敗恢復(fù)的角度考慮。narrow dependencies的失敗恢復(fù)更有效等限,因?yàn)樗恍枰匦掠?jì)算丟失的parent partition即可爸吮,而且可以并行地在不同節(jié)點(diǎn)進(jìn)行重計(jì)算芬膝。而wide dependencies牽涉到RDD各級(jí)的多個(gè)Parent Partitions。下圖說明了narrow dependencies與wide dependencies之間的區(qū)別:

pic-1.png

本圖來自Matei Zaharia撰寫的論文An Architecture for Fast and General Data Processing on Large Clusters拗胜。圖中,一個(gè)box代表一個(gè)RDD怒允,一個(gè)帶陰影的矩形框代表一個(gè)partition埂软。

另外給一張join的操作過程圖片:

pic-2.png

RDD分區(qū)

我們分析這樣一個(gè)應(yīng)用,它在內(nèi)存中保存著一張很大的用戶信息表(UserData)——也就是一個(gè)由(UserId, UserInfo)對(duì)組成的RDD纫事,其中UserInfo包含一個(gè)該用戶所訂閱的主題列表勘畔。該應(yīng)用會(huì)周期性性地將這張表與一個(gè)小文件進(jìn)行組合,這個(gè)小文件中存著過去五分鐘內(nèi)發(fā)生的事件(events)——其實(shí)就是一個(gè)由(UserID, LinkInfo)對(duì)組成的表丽惶。如果我們要進(jìn)行對(duì)用戶訪問情況的統(tǒng)計(jì)炫七,就需要對(duì)這兩個(gè)表進(jìn)行join操作,以獲得(UserID,UserInfo,LinkInfo)信息钾唬。

如圖pic-2默認(rèn)情況下万哪,join操作會(huì)將兩個(gè)數(shù)據(jù)集中的所有的鍵的哈希值都求出來,將哈希值相同的記錄傳送到同一臺(tái)機(jī)器上抡秆,之后在該機(jī)器上對(duì)所有鍵相同的記錄進(jìn)行join操作奕巍。

所以這種情況之下,每次進(jìn)行join都會(huì)有數(shù)據(jù)混洗的問題儒士。造成了很大的網(wǎng)絡(luò)傳輸開銷的止。

這種情況之下由于UserData表比events表要大得多,所以選擇將UserData進(jìn)行分區(qū)着撩。如果對(duì)UserData進(jìn)行分區(qū)诅福,之后Spark就會(huì)知曉該RDD是根據(jù)鍵的哈希值來分區(qū)的,這樣在調(diào)用join()時(shí)拖叙,Spark就會(huì)利用這一點(diǎn)氓润。當(dāng)調(diào)用UserData.join(events)時(shí),Spark只會(huì)對(duì)events進(jìn)行數(shù)據(jù)混洗操作薯鳍,將events中特定的UserID的記錄發(fā)送到userData的對(duì)應(yīng)分區(qū)所在的那臺(tái)機(jī)器上旺芽。如下圖:

pic3.png

自定義分區(qū)

我們都知道Spark內(nèi)部提供了HashPartitioner和RangePartitioner兩種分區(qū)策略,這兩種分區(qū)策略在很多情況下都適合我們的場(chǎng)景辐啄。但是有些情況下采章,Spark內(nèi)部不能符合咱們的需求,這時(shí)候我們就可以自定義分區(qū)策略壶辜。為此悯舟,Spark提供了相應(yīng)的接口,我們只需要擴(kuò)展Partitioner抽象類砸民,然后實(shí)現(xiàn)里面的三個(gè)方法:

pic-4.png

def numPartitions: Int:這個(gè)方法需要返回你想要?jiǎng)?chuàng)建分區(qū)的個(gè)數(shù)抵怎;   
def getPartition(key: Any): Int:這個(gè)函數(shù)需要對(duì)輸入的key做計(jì)算奋救,然后返回該key的分區(qū)ID,范圍一定是0到numPartitions-1反惕;   
equals():這個(gè)是Java標(biāo)準(zhǔn)的判斷相等的函數(shù)尝艘,之所以要求用戶實(shí)現(xiàn)這個(gè)函數(shù)是因?yàn)镾park內(nèi)部會(huì)比較兩個(gè)RDD的分區(qū)是否一樣。
  假如我們想把來自同一個(gè)域名的URL放到一臺(tái)節(jié)點(diǎn)上姿染,比如:http://www.csdn.nethttp://www.csdn.net/bolg/背亥,如果你使用HashPartitioner,這兩個(gè)URL的Hash值可能不一樣悬赏,這就使得這兩個(gè)URL被放到不同的節(jié)點(diǎn)上狡汉。所以這種情況下我們就需要自定義我們的分區(qū)策略,可以如下實(shí)現(xiàn):

pic-5.png

因?yàn)閔ashCode值可能為負(fù)數(shù)闽颇,所以我們需要對(duì)他進(jìn)行處理盾戴。然后我們就可以在partitionBy()方法里面使用我們的分區(qū):

pic-6.png

類似的,在Java中定義自己的分區(qū)策略和Scala類似兵多,只需要繼承org.apache.spark.Partitioner尖啡,并實(shí)現(xiàn)其中的方法即可。
在Python中剩膘,你不需要擴(kuò)展Partitioner類可婶,我們只需要對(duì)iteblog.partitionBy()加上一個(gè)額外的hash函數(shù),如下:


pic-7.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末援雇,一起剝皮案震驚了整個(gè)濱河市矛渴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惫搏,老刑警劉巖具温,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異筐赔,居然都是意外死亡铣猩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門茴丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來达皿,“玉大人,你說我怎么就攤上這事贿肩÷鸵” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵汰规,是天一觀的道長汤功。 經(jīng)常有香客問我,道長溜哮,這世上最難降的妖魔是什么滔金? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任色解,我火速辦了婚禮,結(jié)果婚禮上餐茵,老公的妹妹穿的比我還像新娘科阎。我一直安慰自己,他們只是感情好忿族,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布锣笨。 她就那樣靜靜地躺著,像睡著了一般肠阱。 火紅的嫁衣襯著肌膚如雪票唆。 梳的紋絲不亂的頭發(fā)上朴读,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天屹徘,我揣著相機(jī)與錄音,去河邊找鬼衅金。 笑死噪伊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氮唯。 我是一名探鬼主播鉴吹,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼惩琉!你這毒婦竟也來了豆励?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤瞒渠,失蹤者是張志新(化名)和其女友劉穎良蒸,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伍玖,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫩痰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窍箍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片串纺。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖椰棘,靈堂內(nèi)的尸體忽然破棺而出纺棺,到底是詐尸還是另有隱情,我是刑警寧澤邪狞,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布五辽,位于F島的核電站,受9級(jí)特大地震影響外恕,放射性物質(zhì)發(fā)生泄漏杆逗。R本人自食惡果不足惜乡翅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罪郊。 院中可真熱鬧蠕蚜,春花似錦、人聲如沸悔橄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癣疟。三九已至挣柬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睛挚,已是汗流浹背邪蛔。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扎狱,地道東北人侧到。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像淤击,于是被迫代替她去往敵國和親匠抗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容