亚洲精品久久久久久第一页-人妻少妇精彩视品一区二区三区-91国产自拍免费视频-免费一级a在线播放视频正片-少妇天天日天天射天天爽-国产大屁股喷水视频在线观看-操美女骚穴抽插性爱视频-亚洲 欧美 中文字幕 丝袜-成人免费无码片在线观看

shuffle什么意思 sx是什么意思


shuffle什么意思 sx是什么意思

文章插圖
專題介紹
2009 年,Spark 誕生于加州大學(xué)伯克利分校的 AMP 實(shí)驗(yàn)室(the Algorithms, Machines and People lab),并于 2010 年開源 。2013 年,Spark 捐獻(xiàn)給阿帕奇軟件基金會(huì)(Apache Software Foundation),并于 2014 年成為 Apache 頂級(jí)項(xiàng)目 。
如今,十年光景已過,Spark 成為了大大小小企業(yè)與研究機(jī)構(gòu)的常用工具之一,依舊深受不少開發(fā)人員的喜愛 。如果你是初入江湖且希望了解、學(xué)習(xí) Spark 的“小蝦米”,那么 InfoQ 與 FreeWheel 技術(shù)專家吳磊合作的專題系列文章——《深入淺出 Spark:原理詳解與開發(fā)實(shí)踐》一定適合你!
本文系專題系列第二篇 。
書接前文,在上一篇《內(nèi)存計(jì)算的由來 —— RDD》,我們從“虛”、“實(shí)”兩個(gè)方面介紹了RDD 的基本構(gòu)成 。RDD 通過dependencies 和compute 屬性首尾相連構(gòu)成的計(jì)算路徑,專業(yè)術(shù)語稱之為L(zhǎng)ineage —— 血統(tǒng),又名DAG(Directed Acyclic Graph,有向無環(huán)圖) 。一個(gè)概念為什么會(huì)有兩個(gè)稱呼呢?這兩個(gè)不同的名字又有什么區(qū)別和聯(lián)系?簡(jiǎn)單地說,血統(tǒng)與DAG 是從兩個(gè)不同的視角出發(fā),來描述同一個(gè)事物 。血統(tǒng),側(cè)重于從數(shù)據(jù)的角度描述不同RDD 之間的依賴關(guān)系;DAG,則是從計(jì)算的角度描述不同RDD 之間的轉(zhuǎn)換邏輯 。如果說RDD 是Spark 對(duì)于分布式數(shù)據(jù)模型的抽象,那么與之對(duì)應(yīng)地,DAG 就是Spark 對(duì)于分布式計(jì)算模型的抽象 。
顧名思義,DAG 是一種“圖”,圖計(jì)算模型的應(yīng)用由來已久,早在上個(gè)世紀(jì)就被應(yīng)用于數(shù)據(jù)庫系統(tǒng)(Graph databases)的實(shí)現(xiàn)中 。任何一個(gè)圖都包含兩種基本元素:節(jié)點(diǎn)(Vertex)和邊(Edge),節(jié)點(diǎn)通常用于表示實(shí)體,而邊則代表實(shí)體間的關(guān)系 。例如,在“倚天屠龍”社交網(wǎng)絡(luò)的好友關(guān)系中,每個(gè)節(jié)點(diǎn)表示一個(gè)具體的人,每條邊意味著兩端的實(shí)體之間建立了好友關(guān)系 。
倚天屠龍社交網(wǎng)絡(luò)
在上面的社交網(wǎng)絡(luò)中,好友關(guān)系是相互的,如張無忌和周芷若互為好友,因此該關(guān)系圖中的邊是沒有指向性的;另外,細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn),上面的圖結(jié)構(gòu)是有“環(huán)”的,如張無忌、謝遜、白眉鷹王構(gòu)成的關(guān)系環(huán),張無忌、謝遜、紫衫龍王、小昭之間的關(guān)系環(huán),等等 。像上面這樣的圖結(jié)構(gòu),術(shù)語稱之為“無向有環(huán)圖” 。沒有比較就沒有鑒別,有向無環(huán)圖(DAG)自然是一種帶有指向性、不存在“環(huán)”結(jié)構(gòu)的圖模型 。各位看官還記得土豆工坊的例子嗎?
土豆工坊DAG
在上面的土豆加工DAG 中,每個(gè)節(jié)點(diǎn)是一個(gè)個(gè)RDD,每條邊代表著不同RDD 之間的父子關(guān)系 —— 父子關(guān)系自然是單向的,因此整張圖是有指向性的 。另外我們注意到,整個(gè)圖中是不存在環(huán)結(jié)構(gòu)的 。像這樣的土豆加工流水線可以說是最簡(jiǎn)單的有向無環(huán)圖,每個(gè)節(jié)點(diǎn)的入度(Indegree,指向自己的邊)與出度(Outdegree,從自己出發(fā)的邊)都是1,整個(gè)圖看下來只有一條分支 。
不過,工業(yè)應(yīng)用中的Spark DAG 要比這復(fù)雜得多,往往是由不同RDD 經(jīng)過關(guān)聯(lián)、拆分產(chǎn)生多個(gè)分支的有向無環(huán)圖 。為了說明這一點(diǎn),我們還是拿土豆工坊來舉例,在將“原味”薯片推向市場(chǎng)一段時(shí)間后,工坊老板發(fā)現(xiàn)季度銷量直線下滑,老板心急如焚、一籌莫展 。此時(shí)有人向他建議:“何不推出更多風(fēng)味的薯片,來迎合大眾的多樣化選擇”,于是老板一聲令下,工人們對(duì)流水線做了如下改動(dòng) 。
土豆工坊高級(jí)生產(chǎn)線
與之前相比,新的流程增加了3 條風(fēng)味流水線,用于分發(fā)不同的調(diào)料粉 。新流水線上的辣椒粉被分發(fā)到收集小號(hào)薯片的流水線、孜然粉分發(fā)到中號(hào)薯片流水線,相應(yīng)地,番茄粉分發(fā)到大號(hào)薯片流水線 。經(jīng)過改造,土豆工坊現(xiàn)在可以生產(chǎn)3 種風(fēng)味、不同尺寸的薯片,即麻辣味的小號(hào)薯片、孜然味的中號(hào)薯片和番茄味的大號(hào)薯片 。如果我們用flavoursRDD 來抽象調(diào)味品的話,那么工坊新作業(yè)流程所對(duì)應(yīng)的DAG 會(huì)演化為如下所示帶有2 個(gè)分支的有向無環(huán)圖 。
多個(gè)分支的DAG
在上一篇,我們探討了Spark Core 內(nèi)功心法的第一要義 —— RDD,這一篇,咱們來說說內(nèi)功心法的第二個(gè)秘訣 —— DAG 。
RDD 算子 —— DAG 的邊 在上一篇《內(nèi)存計(jì)算的由來 —— RDD》最后,我們以 WordCount 為例展示不同 RDD 之間轉(zhuǎn)換而形成的 DAG 計(jì)算圖 。通讀代碼,從開發(fā)的角度來看,我們發(fā)現(xiàn) DAG 構(gòu)成的關(guān)鍵在于 RDD 算子調(diào)用 。不同于 Hadoop MapReduce,Spark 以數(shù)據(jù)為導(dǎo)向提供了豐富的 RDD 算子,供開發(fā)者靈活地排列組合,從而實(shí)現(xiàn)多樣化的數(shù)據(jù)處理邏輯 。那么問題來了,Spark 都提供哪些算子呢?
數(shù)據(jù)來源: https://spark.apache.org/docs/latest/rdd-programming-guide.html
從表格中我們看到,Spark 的 RDD 算子豐富到讓人眼花繚亂的程度,對(duì)于初次接觸 Spark 的同學(xué)來說,如果不稍加歸類,面對(duì)多如繁星的算子還真是無從下手 。Apache Spark 官網(wǎng)將 RDD 算子歸為 Transformations 和 Actions 兩種類型,這也是大家在各類 Spark 技術(shù)博客中常見的分類方法 。為了說明 Transformations 和 Actions 算子的本質(zhì)區(qū)別,我們必須得提一提 Spark 計(jì)算模型的“惰性計(jì)算”(Lazy evaluation,又名延遲計(jì)算)特性 。
掌握一個(gè)新概念最有效的方法之一就是找到與之相對(duì)的概念 —— 與“惰性計(jì)算”相對(duì),大多數(shù)傳統(tǒng)編程語言、編程框架的求值策略是“及早求值”(Eager evaluation) 。例如,對(duì)于我們熟悉的 C、C 、Java 來說,每一條指令都會(huì)嘗試調(diào)度 CPU、占用時(shí)鐘周期、觸發(fā)計(jì)算的執(zhí)行,同時(shí),CPU 寄存器需要與內(nèi)存通信從而完成數(shù)據(jù)交換、數(shù)據(jù)緩存 。在傳統(tǒng)編程模式中,每一條指令都很“急”(Eager),都恨不得自己馬上被調(diào)度到“前線”、參與戰(zhàn)斗 。
惰性計(jì)算模型則不然 —— 具體到 Spark,絕大多數(shù) RDD 算子都很“穩(wěn)”、特別能沉得住氣,他們會(huì)明確告訴 DAGScheduler:“老兄,你先往前走著,不用理我,我先繃會(huì)兒、抽袋煙 。隊(duì)伍的前排是我們帶頭大哥,沒有他的命令,我們不會(huì)貿(mào)然行動(dòng) ?!庇辛硕栊杂?jì)算和及早求值的基本了解,我們?cè)僬f回 Transformations 和 Actions 的區(qū)別 。在 Spark 的 RDD 算子中,Transformations 算子都屬于惰性求值操作,僅參與 DAG 計(jì)算圖的構(gòu)建、指明計(jì)算邏輯,并不會(huì)被立即調(diào)度、執(zhí)行 。惰性求值的特點(diǎn)是當(dāng)且僅當(dāng)數(shù)據(jù)需要被物化(Materialized)時(shí)才會(huì)觸發(fā)計(jì)算的執(zhí)行,RDD 的 Actions 算子提供各種數(shù)據(jù)物化操作,其主要職責(zé)在于觸發(fā)整個(gè) DAG 計(jì)算鏈條的執(zhí)行 。當(dāng)且僅當(dāng) Actions 算子觸發(fā)計(jì)算時(shí),DAG 從頭至尾的所有算子(前面用于構(gòu)建 DAG 的 Transformations 算子)才會(huì)按照依賴關(guān)系的先后順序依次被調(diào)度、執(zhí)行 。
說到這里,各位看官不禁要問:Spark 采用惰性求值的計(jì)算模型,有什么優(yōu)勢(shì)嗎?或者反過來問:Spark 為什么沒有采用傳統(tǒng)的及早求值?不知道各位看官有沒有聽說過“延遲滿足效應(yīng)”(又名“糖果效應(yīng)”),它指的是為了獲取長(zhǎng)遠(yuǎn)的、更大的利益而自愿延緩甚至放棄目前的、較小的滿足 。正所謂:“云想衣裳花想容,豬想發(fā)福人想紅” 。Spark 這孩子不僅天資過人,小小年紀(jì)竟頗具城府,獨(dú)創(chuàng)的內(nèi)功心法意不在贏得眼下的一招半式,而是著眼于整個(gè)武林 。扯遠(yuǎn)了,我們收回來 ?;\統(tǒng)地說,惰性計(jì)算為 Spark 執(zhí)行引擎的整體優(yōu)化提供了廣闊的空間 。關(guān)于惰性計(jì)算具體如何幫助 Spark 做全局優(yōu)化 —— 說書的一張嘴表不了兩家事,后文書咱們慢慢展開 。
還是說回 RDD 算子,除了常見的按照 Transformations 和 Actions 分類的方法,筆者又從適用范圍和用途兩個(gè)維度為老鐵們做了歸類,畢竟人類的大腦喜歡結(jié)構(gòu)化的知識(shí),官網(wǎng)上一字長(zhǎng)蛇陣的羅列總是讓人看了昏昏欲睡 。有了這個(gè)表格,我們就知道 *ByKey 的操作一定是作用在 Paired RDD 上的,所謂 Paired RDD 是指 Schema 明確區(qū)分(Key, Value)對(duì)的 RDD,與之相對(duì),任意 RDD 指的是不帶 Schema 或帶任意 Schema 的 RDD 。從用途的角度來區(qū)分 RDD 算子的歸類相對(duì)比較分散,篇幅的原因,這里就不一一展開介紹,老鐵們各取所需吧 。
值得一提的是,對(duì)于相同的計(jì)算場(chǎng)景,采用不同算子實(shí)現(xiàn)帶來的執(zhí)行性能可能會(huì)有天壤之別,在后續(xù)的性能調(diào)優(yōu)篇咱們?cè)倬唧w問題具體分析 。好吧,坑越挖越多,列位看官您稍安勿躁,咱們按照 FIFO 的原則,先來說說剛剛才提到的、還熱乎的 DAGScheduler 。
DAGScheduler —— DAG 的向?qū)Ч?DAGScheduler 是 Spark 分布式調(diào)度系統(tǒng)的重要組件之一,其他組件還包括 TaskScheduler、MapOutputTracker、SchedulerBackend 等 。DAGScheduler 的主要職責(zé)是根據(jù) RDD 依賴關(guān)系將 DAG 劃分為 Stages,以 Stage 為粒度提交任務(wù)(TaskSet)并跟蹤任務(wù)進(jìn)展 。如果把 DAG 看作是 Spark 作業(yè)的執(zhí)行路徑或“戰(zhàn)略地形”,那么 DAGScheduler 就是這塊地形的向?qū)Ч?,這個(gè)向?qū)Ч儇?fù)責(zé)從頭至尾將地形摸清楚,根據(jù)地形特點(diǎn)排兵布陣 。更形象地,回到土豆工坊的例子,DAGScheduler 要做的事情是把抽象的土豆加工 DAG 轉(zhuǎn)化為工坊流水線上一個(gè)個(gè)具體的薯片加工操作任務(wù) 。那么問題來了,DAGScheduler 以怎樣的方式摸索“地形”?如何劃分 Stages?劃分 Stages 的依據(jù)是什么?更進(jìn)一步,將 DAG 劃分為 Stages 的收益有哪些?Spark 為什么要這么做?
DAGScheduler 的核心職責(zé)
為了回答這些問題,我們需要先對(duì)于 DAG 的“首”和“尾”進(jìn)行如下定義:在一個(gè) DAG 中,沒有父 RDD 的節(jié)點(diǎn)稱為首節(jié)點(diǎn),而沒有子 RDD 的節(jié)點(diǎn)稱為尾節(jié)點(diǎn) 。還是以土豆工坊為例,其中首節(jié)點(diǎn)有兩個(gè),分別是 potatosRDD 和 flavoursRDD,而尾節(jié)點(diǎn)是 flavouredBakedChipsRDD 。
DAG 中首與尾的定義
DAGScheduler 在嘗試探索 DAG“地形”時(shí),是以首尾倒置的方式從后向前進(jìn)行 。具體說來,對(duì)于土豆工坊的 DAG,DAGScheduler 會(huì)從尾節(jié)點(diǎn) flavouredBakedChipsRDD 開始,根據(jù) RDD 依賴關(guān)系依次向前遍歷所有父 RDD 節(jié)點(diǎn),在遍歷的過程中以 Shuffle 為邊界劃分 Stage 。Shuffle 的字面意思是“洗牌”,沒錯(cuò),就是撲克游戲中的洗牌,在大數(shù)據(jù)領(lǐng)域 Shuffle 引申為“跨節(jié)點(diǎn)的數(shù)據(jù)分發(fā)”,指的是為了實(shí)現(xiàn)某些計(jì)算邏輯需要將數(shù)據(jù)在集群范圍內(nèi)的不同計(jì)算節(jié)點(diǎn)之間定向分發(fā) 。在絕大多數(shù)場(chǎng)景中,Shuffle 都是當(dāng)之無愧的“性能瓶頸擔(dān)當(dāng)”,毫不客氣地說,有 Shuffle 的地方,就有性能優(yōu)化的空間 。關(guān)于 Spark Shuffle 的原理和性能優(yōu)化技巧,后面我們會(huì)單獨(dú)開一篇來專門探討 。在土豆工坊的 DAG 中,有兩個(gè)地方發(fā)生了 Shuffle,一個(gè)是從 bakedChipsRDD 到 flavouredBakedChipsRDD 的計(jì)算,另一個(gè)是從 flavoursRDD 到 flavouredBakedChipsRDD 的計(jì)算,如下圖所示 。
土豆工坊 DAG 中的 Shuffle
各位看官不禁要問:DAGScheduler 如何判斷 RDD 之間的轉(zhuǎn)換是否會(huì)發(fā)生 Shuffle 呢?那位看官說了:“前文書說了半天算子是 RDD 之間轉(zhuǎn)換的關(guān)鍵,莫不是根據(jù)算子來判斷會(huì)不會(huì)發(fā)生 Shuffle?”您還真猜錯(cuò)了,算子與 Shuffle 沒有對(duì)應(yīng)關(guān)系 。就拿 join 算子來說,在大部分場(chǎng)景下,join 都會(huì)引入 Shuffle;然而在 collocated join 中,左右表數(shù)據(jù)分布一致的情況下,是不會(huì)發(fā)生 Shuffle 的 。所以您看,DAGScheduler 還真不能依賴算子本身來判斷發(fā)生 Shuffle 與否 。要回答這個(gè)問題,咱們還是得回到前文書《內(nèi)存計(jì)算的由來 —— RDD》中介紹 RDD 時(shí)提到的 5 大屬性 。
屬性名 成員類型 屬性含義 dependencies 變量 生成該 RDD 所依賴的父 RDD compute 方法 生成該 RDD 的計(jì)算接口 partitions 變量 該 RDD 的所有數(shù)據(jù)分片實(shí)體 partitioner 方法 劃分?jǐn)?shù)據(jù)分片的規(guī)則 preferredLocations 變量 數(shù)據(jù)分片的物理位置偏好
RDD 的 5 大屬性及其含義
其中第一大屬性 dependencies 又可以細(xì)分為 NarrowDependency 和 ShuffleDependency,NarrowDependency 又名“窄依賴”,它表示 RDD 所依賴的數(shù)據(jù)無需分發(fā),基于當(dāng)前現(xiàn)有的數(shù)據(jù)分片執(zhí)行 compute 屬性封裝的函數(shù)即可;ShuffleDependency 則不然,它表示 RDD 依賴的數(shù)據(jù)分片需要先在集群內(nèi)分發(fā),然后才能執(zhí)行 RDD 的 compute 函數(shù)完成計(jì)算 。因此,RDD 之間的轉(zhuǎn)換是否發(fā)生 Shuffle,取決于子 RDD 的依賴類型,如果依賴類型為 ShuffleDependency,那么 DAGScheduler 判定:二者的轉(zhuǎn)換會(huì)引入 Shuffle 。在回溯 DAG 的過程中,一旦 DAGScheduler 發(fā)現(xiàn) RDD 的依賴類型為 ShuffleDependency,便依序執(zhí)行如下 3 項(xiàng)操作: