General
MapReduce for Dummies
0 views

MapReduce for Dummies
Say you need to grep for "Hi There" across a petabyte of text spread over thousands of files. A single machine reading that much data sequentially could take hours — I/O alone becomes the bottleneck, before you even count the CPU time to scan every line.
The fix: split the work. Hand different files to different machines (workers) so they scan in parallel, and use a central coordinator to hand out tasks, track progress, and reassign anything that fails.
That's MapReduce in one sentence: split, distribute, collect.
You can find the full implementation of this lab in this commit.
Sample Working example
We use mapReduce to perform grep over 100 files using n=10 workers.
Step 1- Define the coordinator and pass on the tasks
c := Coordinator{
mu: sync.Mutex{},
mapTasks: make([]Task, len(files)),
reduceTasks: make([]Task, nReduce),
nMap: len(files), //100
nReduce: nReduce, //10
}
for i, file := range files {
c.mapTasks[i] = Task{
Id: i,
File: file,}
}
Step 2- Initialize workers and run them until task is complete
// rpc call to co-ordinator
for {
task, err := fetchTask()
}
func fetchTask() (*Task, error) {
ok := call("Coordinator.FetchTask", &req, &reply)
if !ok {
return &Task{Type: IdleTask}, fmt.Errorf("failed to fetch task")
}
return &reply.Task, nil
}
Step 3- Perform Map Task (In this case calling grep)
This step contains the crux of MapReduce -
Tasks should be atomic, tasks failed mid-way are discarded
Each Map task is divided into N(=10) reduce tasks. So, in total there are map-tasks * NReduce(=10) distinct tasks across nodes.
To prevent a stuck/failed worker from hoarding the task, ideally create a deadline which automatically fails the task on crossing it.
content, err := os.ReadFile(task.File)
if err != nil {
return err
}
if err := c.Err(); err != nil {
return err
}
// Call map function
kva := grepMyFile(task.File, string(content))
// Write intermediate key-value pairs to files
buckets := make([][]KeyValue, task.NReduce)
for _, kv := range kva {
// hash ... to be done
haskKey := ihash(kv.Key) % task.NReduce
buckets[haskKey] = append(buckets[haskKey], kv)
}
for y, bucket := range buckets {
// **IMP : create temp file for atomicity
fileName := fmt.Sprintf("mr-%d-%d", task.Id, y)
tmpFile, err := os.CreateTemp(".", "mr-tmp-*")
enc := json.NewEncoder(tmpFile)
for _, kv := range bucket {
enc.Encode(&kv)
}
tmpFile.Close()
os.Rename(tmpFile.Name(), fileName)
}
Step 4 - Perform Reduce Task
The reduce Step works in similar way as Map Step. You collect the results produced by various workers to create a unified result.
Read original: https://dev.to/ruturaj_d/mapreduce-for-dummies-3aoe
PreviousMapQuest is now the No. 1 US app after bucking Trump’s ‘Lake America’ renamingNextMAPS: Netflix’s Multimodal Asset Personalization at Scale
Related posts
Third person dies of bird flu since virus started jumping to livestock
0Ars Technica
'NAZA' Has Nada on Israel
0Hacker News New
The Self-Making World
0Hacker News New
Salary Transparency
0Hacker News New
100% accurate next token prediction model
0Hacker News New
Which Chinese movies can you understand? 117 films ranked by HSK level
0Hacker News New