1. 程式人生 > 其它 >JavaScript獲取元素

JavaScript獲取元素

1.3 lab1我的版本

0 前置知識-MapReduce

0.1 MapReduce的出現背景與應用場景

MapReduce的思想是,應用程式設計人員和分散式運算的使用者,只需要寫簡單的Map函式和Reduce函式,而不需要知道任何有關分散式的事情,MapReduce框架會處理剩下的事情。

分散式Grep:map函式在匹配到給定的pattern時輸出一行。reduce函式只是將給定的中間資料複製到輸出上。

URL訪問頻次統計:map函式處理網頁請求的日誌,對每個URL輸出〈URL, 1〉。reduce函式將相同URL的所有值相加並輸出〈URL, 總次數〉對。

倒轉Web連結圖:map函式在source頁面中針對每個指向target的連結都輸出一個〈target, source〉對。reduce函式將與某個給定的target相關聯的所有source連結合併為一個列表,並輸出〈target, list(source)〉對。

倒排索引:map函式解析每個文件,並輸出一系列〈單詞, 文件ID〉對。reduce函式接受給定單詞的所有中間對,將它們按文件ID排序,再輸出〈單詞, list(文件ID)〉對。所有輸出對的集合組成了一個簡單的倒排索引。使用者可以很輕鬆的擴充套件這個過程來跟蹤單詞的位置。

分散式排序:map函式從每條記錄中提取出key,並輸出〈key, 記錄〉對。reduce函式不改變這些中間對,直接輸出。這個過程依賴於4.1節介紹的劃分機制和4.2節介紹的排序性質。

0.2 程式設計模型

使用者自定義的Map函式 接收一個輸入的key/value pair值,然後產生一箇中間key/value pair值的集合。

MapReduce庫把所有具有相同key值的value值集合在一起,傳遞給reduce函式。

使用者自定義的Reduce函式接受一個key值I和相關的一個value值的集合。Reduce函式合併這些value值,形成一個較小的value值的集合。一般,每次Reduce函式呼叫只產生0或1個輸出value值。通常我們通過一個迭代器把中間value值提供給Reduce函式,這樣我們就可以處理無法全部放入記憶體中的大量的value值的集合。

0.3 舉例

統計多個檔案中每個單詞的出現次數: 對每個檔案呼叫map函式,最後對所有map函式的輸出呼叫reduce函式。

1、splitting

MapReduce庫

將輸入的檔案拆分成M個數據分片,每個資料片段的大小一般從 16MB到64MB(可以通過可選的引數來控制每個資料片段的大小),

將這些小塊傳送到不同的機器上(對應一個worker)

2、mapping

每個機器對拿到的資料,執行map函式

入參key是檔名,value是檔案內容,

輸出一個key-value對(中間結果),key是該單詞,value是1。如 "black":1, "black":1,"white":1 這種。

3、shuffling

reduce階段 : 將所有map產生的內容彙總。 變成 key:list(value)的形式(中間結果)

4、reduce

使用者編寫的reduce函式處理中間結果,形成輸出。

0.4 實現

1、使用者程式呼叫MapReduce庫,MapReduce庫將輸入檔案分成M個數據片,每個資料片段的大小一般從 16MB到64MB(可以通過可選的引數來控制每個資料片段的大小)。這些分片傳送給不同的機器, 每個機器都啟動一個worker。 2、程式副本中的有一個特殊的程式–master。副本中其它的程式都是worker程式。 由master分配任務。有M個Map任務和R個Reduce任務將被分配。 3、被分配了map任務的worker程式讀取相關的輸入資料片段,從輸入的資料片段中解析出key/value pair,然後把key/value pair傳遞給使用者自定義的Map函式,由Map函式生成並輸出的中間key/value pair,並快取在記憶體中。 4、快取中的key/value pair通過分割槽函式分成R個區域,之後週期性的寫入到本地磁碟上(圖中切成了2塊)。快取的key/value pair在本地磁碟上的儲存位置將被回傳給master,由master負責把這些儲存位置再傳送給Reduce worker。 5、當Reduce worker程式接收到master程式發來的資料儲存位置資訊後,使用RPC從Map worker所在主機的磁碟上讀取這些快取資料。當Reduce worker讀取了中間資料後,通過對key進行排序後使得具有相同key值的資料聚合在一起。由於許多不同的key值會對映到相同的Reduce任務上,因此必須進行排序。如果中間資料太大無法在記憶體中完成排序,那麼就要在外部進行排序。 6、Reduce worker程式遍歷排序後的中間資料,對於每一個唯一的中間key值,Reduce worker程式將這個key值和它相關的中間value值的集合傳遞給使用者自定義的Reduce函式。Reduce函式的輸出被追加到所屬分割槽的輸出檔案。 7、當所有的Map和Reduce任務都完成之後,master喚醒使用者程式。在這個時候,在使用者程式裡的對MapReduce呼叫才返回。

在成功完成任務之後,MapReduce的輸出存放在R個輸出檔案中(對應每個Reduce任務產生一個輸出檔案,檔名由使用者指定)。一般情況下,使用者不需要將這R個輸出檔案合併成一個檔案–他們經常把這些檔案作為另外一個MapReduce的輸入,或者在另外一個可以處理多個分割檔案的分散式應用中使用。

0.5 容錯

worker失效

worker故障

master週期性的ping每個worker。如果在一個約定的時間範圍內沒有收到worker返回的資訊,master將把這個worker標記為失效。

map失效後:

  • 已完成的map task標記為idle。當worker故障時,由於已經完成的Map任務的輸出儲存在這臺機器上,Map任務的輸出已不可訪問了,因此必須重新執行。

  • 已完成的reduce task不用變。已經完成的Reduce任務的輸出儲存在全域性檔案系統上(GFS),因此不需要再次執行。

當一個Map任務首先被worker A執行,之後由於worker A失效了又被排程到worker B執行,這個“重新執行”的動作會被通知給所有執行Reduce任務的worker。任何還沒有從worker A讀取資料的Reduce任務將從worker B讀取資料。

master失效

週期性備份資料。

master週期性的將上面描述的資料結構寫入磁碟,即檢查點(checkpoint)。如果這個master任務失效了,可以從最後一個檢查點(checkpoint)開始啟動另一個master程序。

0.6 備用任務

如果最後的幾個任務執行時間過長怎麼辦?存在這種case,10個任務用5分鐘完成了其中9個,但最後一個任務因為當前機器的負載過高花費了20分鐘執行完畢,這麼整個任務的執行週期就是20分鐘。 如何能應對這一問題呢?

當僅剩下1%的任務時,可以啟動備用任務,即同時在兩個節點上執行相同的任務。這樣只要其中一個先返回即可結束整個任務,同時釋放未完成的任務所佔用的資源。

1 實驗要求

實現一個分散式 MapReduce,它由兩個程式組成,master 和 worker。只有一個主程序和一個或多個並行執行的工作程序。Master 應該注意到一個 worker 是否沒有在合理的時間內完成它的任務(對於本實驗,使用 10 秒),並將相同的任務分配給不同的 worker。

2 程式設計

主要包括三個檔案

  • master 與 Worker 間的 RPC 通訊,對應的rpc.go檔案

  • master對應 mr/master.go

  • Worker mr/worker.go

資料結構

task資訊

拆成兩部分,MasterStoreTask包含Task。 前者存在master裡,後者傳給worker。前者包含的資訊更多,這樣做降低了網路的傳輸量。

type Task struct {
TaskStage Stage //task的型別
NReducer int
TaskNumber int

Input string
Intermediates []string //存
Output string
}
//task的其他資訊,儲存在master即可,不需要通過rpc在master和worker之間傳輸。降低消耗
type MasterStoreTask struct {
TaskStatus Status //idle 等等
StartTime time.Time //記錄該task的啟動時間
TaskBody *Task //Task本體
}

master

type Master struct {
TaskQueue chan *Task ///task佇列,儲存所有等待執行的task。使用buffered channel作為queue存的task指標
TaskMap map[int]*MasterStoreTask // 儲存當前所有task的資訊。key:為task的idx value:MasterStoreTask指標,
MasterPhase Stage // Master當前所處的階段
NReduce int
InputFiles []string
Intermediates [][]string // Map任務產生的R箇中間檔案的資訊
}

執行流程

1.建立master,初始化各種引數m.MakeMaster()

坑:TaskQueue的大小為max(nReduce, len(files)),而非 len(files)

原因:該佇列存的是當前等待執行的任務數量,map階段的值是len(files),reduce階段的值是nReduce。預設設定時應該二者取其大。

2.建立map任務

每個檔案建立一個map任務。

3.等待連線

4.worker

死迴圈,不停的向master索要任務。根據任務型別,決定下一步的操縱。

4.1 worker索要任務

Master.GetTask

4.2 master響應

返回一個任務

Master.GetTask
入參:ExampleArgs
出參:Task{}

4.3 worker處理

根據task.TaskStage 判斷任務型別:map reduce wait exit

4.3.1 mapper函式

接收切分後的input檔案,執行mapf函式,並將輸出得到的結果切成R份,存到本地磁碟。

4.4.1通知master任務完成

call("Master.TaskCompleted", task, &reply)

4.4.2 master響應

將map中存的該task的狀態設定為completed,處理worker的執行結果:將map產生的檔案內容儲存到本地。如果所有任務都完成了,則建立reduce任務,進入到reduce階段。

4.5 其他

reduce的操作與map基本相同。

4.6 容錯

執行一個協程,每隔1秒判斷一次,任務是否超時(當前時間減去任務的開始時間大於10秒。)

超時則處理該任務。

3 踩坑

 TaskQueue chan *Task 的緩衝大小。

不能使用map元素的指標。