在本節中,我們主要來學習maptask的內部實現。
整體執行流程
如上圖示,maptask的整個處理流程分五個階段:
●read階段:通過recordreader從inputsplit分片中將資料解析成乙個個key/value。
●map階段:將由recordreader解析出的key/value交給map()方法處理,並生成乙個個新的key/value。
●collect階段:將map()中新生成key/value由outpcollector.collect()寫入記憶體中的環形資料緩衝區。
●spill階段:當環形緩衝區達到一定閥值後,會將資料寫到本地磁碟上,生成乙個spill檔案。在寫檔案之前,會先將資料進行一次本地排序,必要的時候(按配置要求)還會對資料進行壓縮。
●combine階段:當所有資料處理完後,將所有的臨時的spill檔案進行一次合併,最終之生成乙個資料檔案。
接下來我們會對該流程中最重要的collect、spill和combine三個階段進行更深入的學習。
collect過程
前階段的map中新生成key/value對後,會呼叫outpcollector.collect(key,value),在該方法內部,先呼叫partitioner.getpartition()獲取該記錄的分割槽號,然後將傳給mapoutputbuffer.collect()作進一步的處理。
mapoutputbuffer內部使用了乙個內部的環形的緩衝區來暫時儲存使用者的輸出資料,當緩衝區使用率達到一定閥值後,由spillthread執行緒將緩衝區中的資料spill到本地磁碟上,當所有的資料處理完畢後,對所有的檔案進行合併,最終只生成乙個檔案。該資料緩衝區直接用想到maptask的寫效率。
環形緩衝區使得collect階段和spill階段可以並行處理。
mapoutputbuffer內部採用了兩級索引結構,涉及三個環形的記憶體緩衝區,分別是kvoffsets、kvindices和kvbuffer,這個環形緩衝區的大小可以通過io.sot.mb來設定,預設大小是100mb,圖示如下:
kvoffsets即偏移量索引陣列,用於儲存key/value在kvindices中的偏移量。乙個key/value對在kvoffsets陣列中佔乙個int的大小,而在kvindices陣列中站3個int的大小(如上圖示,包括分割槽號partition,key的起始位置和value的起始位置)。
當kvoffsets的使用率超過io.sort.spill.percent(預設為80%)後,便會觸發spilltread執行緒將資料spill到磁碟上。
kvindices即文職索引陣列,用於儲存實際的key/value在資料緩衝區kvbuffer中的起始位置。
kvbuffer即資料局緩衝區,用於實際儲存key/value,預設情況下可使用io.sort.mb的95%,當該緩衝區使用率使用率超過io.sort.spill.percent後,便會觸發spilltread執行緒將資料spill到磁碟上。
spill過程
在collect階段的執行過程中,當記憶體中的環形資料緩衝區中的資料達到一定發之後,便會觸發一次spill操作,將部分資料spill到本地磁碟上。spillthread執行緒實際上是kvbuffer緩衝區的消費者,主要**如下:
spilllock.lock();
while(true)
spilldone.unlock();
//排序並將緩衝區kvbuffer中的資料spill到本地磁碟上
sortandspill();
spilllock.lock;
//重置各個指標,為下一下spill做準備
if(bufend < bufindex && bufindex < bufstart)
vstart = vend;
bufstart = bufend;
} spilllock.unlock();
sortandspill()方法中的內部流程是這樣的:
第一步,使用用快速排序演算法對kvbuffer[bufstart,bufend)中的資料排序,先對partition分割槽號排序,然後再按照key排序,經過這兩輪排序後,資料就會以分割槽為單位聚集在一起,且同一分區內的資料按key有序;
第二步,按分割槽大小由小到大依次將每個分割槽中的資料寫入任務的工作目錄下的臨時檔案中,如果使用者設定了combiner,則寫入檔案之前,會對每個分割槽中的資料做一次聚集操作,比如和合併; (不確定是否正確這句話,有的說是在merge時將相同key的value合成list,待我研究下,)
第三步,將分割槽資料的元資訊寫到記憶體索引資料結構spillrecord中。分割槽的元資料資訊包括臨時檔案中的偏移量、壓縮前資料的大小和壓縮後資料的大小。
combine過程
當任務的所有資料都處理完後,maptask會將該任務所有的臨時檔案年合併成乙個大檔案,同時生成相應的索引檔案。在合併過程中,是以分割槽文單位進行合併的。
讓每個task最終生成乙個檔案,可以避免同時開啟大量檔案和對小檔案產生隨機讀帶來的開銷。
UIApplication深入學習
新建乙個任意型別的ios應用工程,加入我們在class prefix輸入是tc,我們可以看到工程中生成乙個類 在main函式中,autoreleasepool 函式中 說明 當應用程式將要入非活動狀態執行,在此期間,應用程式不接收訊息或事件。比如來 了。說明 當應用程式入活動狀態執行,這個剛好跟上面...
深入學習CSS
什麼是css?在之前的這篇文章中已經介紹了初步的介紹,詳細請看 div加css進一步講解了css中的內容,先總結如下圖 其實在實際開發中,我們通常採用是外部樣式的匯入,這樣做的好處是對於很對有同樣設計樣式的頁面可以實現樣式的共享,這樣我們不僅僅可以節省了大量的時間,並且也方便我們可以靈活的呼叫的樣式...
block深入學習
block的宣告和使用看上一節就行了。本章主要講block內部的實現過程及原理。block的定義和函式指標非常相似 對比一下 block定義 void someblock 函式指標定義 void functionpionter void functionname 當然區別還是有的,block的返回型...