MapReduce - Wordcount
Užitečné odkazy
Výpočetní úloha
V zadaném úkolu bude MapReduce provádět jednoduchou úlohu. Pro vstupní soubory spočíta četnost výskytu slov. V našem případě budou slova tvořena jedním písmenem.
Ukázkový vstupní soubor může vypadat následovně:
1
a b c a a b c
Sada vstupních souborů se bude nacházet v adresáři data. Zdrojové soubory budou mít příponu .txt.
Architektura MapReduce
V rámci simulované sítě vytvořenou knihovnou distsim bude architektura MapReduce vypadat následovně:
- jeden
masteruzel - několik
workeruzlů provádějícímapneboreduce
Parametr R
Určuje počet reduce operací. Parametr R hraje důležitou roli v hashovací funkci zmíněné níže.
Uzel master
Uzel master má několik povinností:
- Zaregistruje dostupné uzly
worker. - Rozešlě
mappožadavek všem uzlůmworker. - Počká jakmile budou
mapvýsledky hotovy pro všechny vstupní soubory. - Jakmile jsou části
maphotovy, rozešle požadavekreducevšemRuzlům typuworker. - Během těchto všech operací zasílá informační zprávy
pingvšem uzlům typuworkera kontroluje jejich odpověď.
Uzel worker
Uzel worker má v sobě uložené dvě funkce map a reduce. Uzel woker má několik povinností:
- Registruje u uzlu
master. - Periodicky odpovída na zprávy typu
ping. - V případě přijetí zprávy
mapsi otevře příslušné soubory a provede funkcimap. Výsledek uloží do speciálního souboru a jeho název pošle uzlumaster. - V případě přijetí zpávy
reducesi otevře příslušné soubory a provede funkcireduce. Výsledek uloží do speciálního souboru a jeho název pošle uzlumaster.
Speciální soubor
Jak již bylo řečeno, uzel worker výsledky operace map ukládá do speciálního souboru. Jeho název se skládá ze dvou částí. První část získame pomoci hashovací funkce hash(key) mod R, key je aktuálně zpracovávaný znak ze souboru. Druhá část je tvořena unikátním UUID vytvořeném na začátku výpočtu.
1
2
3
4
5
6
7
8
9
10
11
12
13
import hashlib
import uuid
# number of reducers
R = 4
# char, for example 'a'
s = 'a'
prefix = int(hashlib.sha1(s.encode()).hexdigest(), 16) % R
worker_task_id = str(uuid.uuid1())
filename = f'{prefix}_{worker_task_id}'
Zpracování požadavku map v uzlu worker
Jakmile uzel worker obdrží zprávu map otevře si přijaté soubory a provede funkci map. V našem případě to bude uložení hodnot ve formátu znak: četnost do speciálně vytvořeného souboru.
Příklad speciálního souboru, všimněte si, že se opakuje řádek a 1. To znamená, že vstupní soubor poslaný uzlu worker k mapování obsahoval dvě slova a.
1
2
3
4
a 1
b 1
a 1
c 1
Příklad funkce map:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def map_emit_fun(r, worker_task_id):
def emit(key, value):
prefix = int(hashlib.sha1(s.encode()).hexdigest(), 16) % r
filename = f'{prefix}_{worker_task_id}'
append_line(filename, f"{key} {value}")
return emit
def map_count (file, emit):
content = file_to_string(file)
words = content.split(" ")
for word in words:
emit(word, 1)
Vytvoření reduce požadavků v uzlu master
Jakmile uzel master obdrží výsledky od všech uzlů worker vykonávajícíh map (všechny vstupní soubory byly mapovány). Použije stejnou hashovací funkci pro rozdělení mapovacích souborů mezi R uzlů typu worker.
Pokud je R = 2 rozdělí uzel master speciální sobory s názem hash_uuid dle prefixu a rozdělené soubory (cesty k nim) zašlě uzlům worker.
Zpracování požadavku reduce v uzlu worker
Jakmile uzel worker obdrží zprávu reduce otevře si přijaté soubory a provede funkci reduce. V našem případě se bude jednat o součet četností informace ve tvaru znak: četnost. Díky použití hashovací funkce bude každý worker provádět součet pro určitou podmnožinu znaků.
Ukázkový vstupní speciální soubor do operace reduce:
1
2
3
4
a 1
b 1
a 1
c 1
Vysledek poté uloží do souboru a zašlě informaci uzlu master.
Příklad výsledku po operaci reduce:
1
2
3
a 2
b 1
c 1
Příklad funkce reduce:
1
2
3
4
5
6
7
8
9
def reduce_emit_fun(reduce_id, worker_task_id):
def emit(key, value):
filename = f'{reduce_id}_{worker_task_id}'
append_line(filename, f"{key} {value}")
return emit
def reduce_count(key, values, emit):
emit(key, len(values))