99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁(yè)精彩閱讀Apache Spark源碼走讀_數(shù)據(jù)分析師
Apache Spark源碼走讀_數(shù)據(jù)分析師
2014-12-14
收藏

Apache Spark源碼走讀_數(shù)據(jù)分析師

Spark是發(fā)源于美國(guó)加州大學(xué)伯克利分校AMPLab的集群計(jì)算平臺(tái),它立足于內(nèi)存計(jì)算,性能超過(guò)Hadoop百倍,即使使用磁盤(pán),迭代類型的計(jì)算也會(huì)有10倍速度的提升。Spark從多迭代批量處理出發(fā),兼收并蓄數(shù)據(jù)倉(cāng)庫(kù)、流處理和圖計(jì)算等多種計(jì)算范式,是罕見(jiàn)的全能選手。Spark當(dāng)下已成為Apache基金會(huì)的頂級(jí)開(kāi)源項(xiàng)目,擁有著龐大的社區(qū)支持——活躍開(kāi)發(fā)者人數(shù)已超過(guò)Hadoop MapReduce)。這里,我們?yōu)榇蠹曳窒碓S鵬的“Apache Spark源碼走讀”系列博文,從源碼方面對(duì)這個(gè)流行大數(shù)據(jù)計(jì)算框架進(jìn)行深度了解。

  以下為博文

  楔子

  源碼閱讀是一件非常容易的事,也是一件非常難的事。容易的是代碼就在那里,一打開(kāi)就可以看到。難的是要通過(guò)代碼明白作者當(dāng)初為什么要這樣設(shè)計(jì),設(shè)計(jì)之初要解決的主要問(wèn)題是什么。

  在對(duì)Spark的源碼進(jìn)行具體的走讀之前,如果想要快速對(duì)Spark的有一個(gè)整體性的認(rèn)識(shí),閱讀Matei Zaharia做的Spark論文是一個(gè)非常不錯(cuò)的選擇。

  在閱讀該論文的基礎(chǔ)之上,再結(jié)合Spark作者在2012 Developer Meetup上做的演講Introduction to Spark Internals,那么對(duì)于Spark的內(nèi)部實(shí)現(xiàn)會(huì)有一個(gè)比較大概的了解。

  有了上述的兩篇文章奠定基礎(chǔ)之后,再來(lái)進(jìn)行源碼閱讀,那么就會(huì)知道分析的重點(diǎn)及難點(diǎn)。

  基本概念(Basic Concepts)

  1. RDD——Resillient Distributed Dataset 彈性分布式數(shù)據(jù)集。

  2. Operation——作用于RDD的各種操作分為transformation和action。

  3. Job——作業(yè),一個(gè)JOB包含多個(gè)RDD及作用于相應(yīng)RDD上的各種operation。

  4. Stage——一個(gè)作業(yè)分為多個(gè)階段。

  5. Partition——數(shù)據(jù)分區(qū), 一個(gè)RDD中的數(shù)據(jù)可以分成多個(gè)不同的區(qū)。

  6. DAG——Directed Acycle graph,有向無(wú)環(huán)圖,反應(yīng)RDD之間的依賴關(guān)系。

  7. Narrow dependency——窄依賴,子RDD依賴于父RDD中固定的data partition。

  8. Wide Dependency——寬依賴,子RDD對(duì)父RDD中的所有data partition都有依賴。

  9. Caching Managenment——緩存管理,對(duì)RDD的中間計(jì)算結(jié)果進(jìn)行緩存管理以加快整體的處理速度。

  編程模型(Programming Model)

  RDD是只讀的數(shù)據(jù)分區(qū)集合,注意是數(shù)據(jù)集。

  作用于RDD上的Operation分為transformantion和action。 經(jīng)Transformation處理之后,數(shù)據(jù)集中的內(nèi)容會(huì)發(fā)生更改,由數(shù)據(jù)集A轉(zhuǎn)換成為數(shù)據(jù)集B;而經(jīng)Action處理之后,數(shù)據(jù)集中的內(nèi)容會(huì)被歸約為一個(gè)具體的數(shù)值。

  只有當(dāng)RDD上有action時(shí),該RDD及其父RDD上的所有operation才會(huì)被提交到cluster中真正的被執(zhí)行。

  從代碼到動(dòng)態(tài)運(yùn)行,涉及到的組件如下圖所示。

  演示代碼

  運(yùn)行態(tài)(Runtime view)

  不管什么樣的靜態(tài)模型,其在動(dòng)態(tài)運(yùn)行的時(shí)候無(wú)外乎由進(jìn)程,線程組成。

  用Spark的術(shù)語(yǔ)來(lái)說(shuō),static view稱為dataset view,而dynamic view稱為parition view。關(guān)系如圖所示

  在Spark中的task可以對(duì)應(yīng)于線程,worker是一個(gè)個(gè)的進(jìn)程,worker由driver來(lái)進(jìn)行管理。

  那么問(wèn)題來(lái)了,這一個(gè)個(gè)的task是如何從RDD演變過(guò)來(lái)的呢?下節(jié)將詳細(xì)回答這個(gè)問(wèn)題。

  部署(Deployment view)

  當(dāng)有Action作用于某RDD時(shí),該action會(huì)作為一個(gè)job被提交。

  在提交的過(guò)程中,DAGScheduler模塊介入運(yùn)算,計(jì)算RDD之間的依賴關(guān)系。RDD之間的依賴關(guān)系就形成了DAG。

  每一個(gè)JOB被分為多個(gè)stage,劃分stage的一個(gè)主要依據(jù)是當(dāng)前計(jì)算因子的輸入是否是確定的,如果是則將其分在同一個(gè)stage,避免多個(gè)stage之間的消息傳遞開(kāi)銷。

  當(dāng)stage被提交之后,由taskscheduler來(lái)根據(jù)stage來(lái)計(jì)算所需要的task,并將task提交到對(duì)應(yīng)的worker。

  Spark支持以下幾種部署模式,Standalone、Mesos和YARN。這些部署模式將作為taskscheduler的初始化入?yún)ⅰ?/span>

  RDD接口(RDD Interface)

  RDD由以下幾個(gè)主要部分組成

  partitions——partition集合,一個(gè)RDD中有多少data partition

  dependencies——RDD依賴關(guān)系

  compute(parition)——對(duì)于給定的數(shù)據(jù)集,需要作哪些計(jì)算

  preferredLocations——對(duì)于data partition的位置偏好

  partitioner——對(duì)于計(jì)算出來(lái)的數(shù)據(jù)結(jié)果如何分發(fā)

  緩存機(jī)制(caching)

  RDD的中間計(jì)算結(jié)果可以被緩存起來(lái),緩存先選Memory,如果Memory不夠的話,將會(huì)被寫(xiě)入到磁盤(pán)中。

  根據(jù)LRU(last-recent update)來(lái)決定哪先內(nèi)容繼續(xù)保存在內(nèi)存,哪些保存到磁盤(pán)。

  容錯(cuò)性(Fault-tolerant)

  從最初始的RDD到衍生出來(lái)的最后一個(gè)RDD,中間要經(jīng)過(guò)一系列的處理。那么如何處理中間環(huán)節(jié)出現(xiàn)錯(cuò)誤的場(chǎng)景呢?

  Spark提供的解決方案是只對(duì)失效的data partition進(jìn)行事件重演,而無(wú)須對(duì)整個(gè)數(shù)據(jù)全集進(jìn)行事件重演,這樣可以大大加快場(chǎng)景恢復(fù)的開(kāi)銷。

  RDD又是如何知道自己的data partition的number該是多少?如果是HDFS文件,那么HDFS文件的block將會(huì)成為一個(gè)重要的計(jì)算依據(jù)。

  集群管理(cluster management)

  task運(yùn)行在cluster之上,除了Spark自身提供的Standalone部署模式之外,Spark還內(nèi)在支持Yarn和mesos。

  Yarn來(lái)負(fù)責(zé)計(jì)算資源的調(diào)度和監(jiān)控,根據(jù)監(jiān)控結(jié)果來(lái)重啟失效的task或者是重新distributed task一旦有新的node加入cluster的話。本文:CDA數(shù)據(jù)分析師官網(wǎng)

  這一部分的內(nèi)容需要參Yarn的文檔。

  小結(jié)

  在源碼閱讀時(shí),需要重點(diǎn)把握以下兩大主線。

  靜態(tài)view 即 RDD,transformation and action

  動(dòng)態(tài)view 即 life of a job, 每一個(gè)job又分為多個(gè)stage,每一個(gè)stage中可以包含多個(gè)rdd及其transformation,這些stage又是如何映射成為task被distributed到cluster中

數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼

若不方便掃碼,搜微信號(hào):CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說(shuō)明請(qǐng)參見(jiàn):http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }