Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator08 [2015/12/11 03:51]
Andrei Roșu-Cojocaru
laboratoare:laborator08 [2015/12/11 15:19] (current)
Andrei Roșu-Cojocaru
Line 56: Line 56:
   * implementarea **federaţiilor HDFS**, ce utilizează mai multe noduri (spaţii) de nume independente (care nu necesită coordonare între ele); nodurile de date sunt utilizate ca spaţii de stocare pentru blocuri de către toate nodurile de nume. Pentru implementarea unei astfel de funcţionalităţi,​ este necesar ca fiecare nod de date să fie înregistrat de toate nodurile de nume din cluster. Acestea vor transmite rapoarte periodice cu privire la blocurile pe care le stochează, gestionând comenzile care provin de la nodurile de nume.\\ \\ {{ :​laboratoare:​laborator08:​01hdfs_federations.png?​nolink }} \\ \\ Din acest motiv, nodurile de date stochează blocuri aparţinând tuturor federaţiilor de blocuri (//eng.// block pool) din cadrul cluster-ului,​ fiecare dintre ele fiind gestionate separat de alte astfel de obiecte. O federaţie de blocuri este reprezentată de un set de blocuri ce aparţine unui singur spaţiu de nume. În acest mod, un spaţiu de nume poate genera identificatori pentru blocuri fără a fi necesară coordonarea cu alte spaţii de nume şi în acelaşi timp, erorile produse la nivelul unui nod de nume nu împiedică nodul de date de a lucra cu alte noduri de nume din cluster. Un spaţiu de nume împreună cu federaţia sa de blocuri poartă denumirea de volum al spaţiului de nume, acesta fiind o unitate de gestiune autonomă. Atunci când un nod (spaţiu) de nume este şters, şi federaţia sa de blocuri de la nivelul nodurilor de date este ştearsă. Actualizările de la nivelul volumului unui spaţiu de nume se realizează unitar, atunci când se produce actualizarea unui cluster. Toate nodurile din cadrul unui cluster partajează un identificator al clusterului,​ generat în mod automat la formatarea unui nod de nume. Un astfel de identificator ar trebui să fie folosit şi pentru formatarea altor noduri de nume în cadrul cluster-ului respectiv.\\ \\ Beneficiile acestei îmbunătăţiri includ **scalabilitatea spaţiului de nume** (spaţiul de stocare al clusterului HDFS este caracterizat prin scalabilitate,​ astfel încât proiectele de dimensiuni mari sau cele care utilizează numeroase fişiere de dimensiuni mai mici pot beneficia de scalabilitatea spaţiului de nume prin adăugarea mai multor noduri de nume la cluster), **performanţa** (îmbunătăţirea ratei de transfer pentru operaţiile de citire / scriere în cadrul sistemului de fişiere prin adăugarea mai multor noduri de nume în cadrul clusterului) şi **izolarea** (categorii diferite de aplicaţii şi utilizatori pot fi izolate în cadrul unor spaţii de nume diferite). Într-o arhitectură care foloseşte un singur spaţiu de nume, într-un mediu concurent, o aplicaţie poate suprasolicita spaţiu de nume astfel încât performanţele celorlalte aplicaţii ce utilizează acelaşi spaţiu de nume vor fi afectate.   * implementarea **federaţiilor HDFS**, ce utilizează mai multe noduri (spaţii) de nume independente (care nu necesită coordonare între ele); nodurile de date sunt utilizate ca spaţii de stocare pentru blocuri de către toate nodurile de nume. Pentru implementarea unei astfel de funcţionalităţi,​ este necesar ca fiecare nod de date să fie înregistrat de toate nodurile de nume din cluster. Acestea vor transmite rapoarte periodice cu privire la blocurile pe care le stochează, gestionând comenzile care provin de la nodurile de nume.\\ \\ {{ :​laboratoare:​laborator08:​01hdfs_federations.png?​nolink }} \\ \\ Din acest motiv, nodurile de date stochează blocuri aparţinând tuturor federaţiilor de blocuri (//eng.// block pool) din cadrul cluster-ului,​ fiecare dintre ele fiind gestionate separat de alte astfel de obiecte. O federaţie de blocuri este reprezentată de un set de blocuri ce aparţine unui singur spaţiu de nume. În acest mod, un spaţiu de nume poate genera identificatori pentru blocuri fără a fi necesară coordonarea cu alte spaţii de nume şi în acelaşi timp, erorile produse la nivelul unui nod de nume nu împiedică nodul de date de a lucra cu alte noduri de nume din cluster. Un spaţiu de nume împreună cu federaţia sa de blocuri poartă denumirea de volum al spaţiului de nume, acesta fiind o unitate de gestiune autonomă. Atunci când un nod (spaţiu) de nume este şters, şi federaţia sa de blocuri de la nivelul nodurilor de date este ştearsă. Actualizările de la nivelul volumului unui spaţiu de nume se realizează unitar, atunci când se produce actualizarea unui cluster. Toate nodurile din cadrul unui cluster partajează un identificator al clusterului,​ generat în mod automat la formatarea unui nod de nume. Un astfel de identificator ar trebui să fie folosit şi pentru formatarea altor noduri de nume în cadrul cluster-ului respectiv.\\ \\ Beneficiile acestei îmbunătăţiri includ **scalabilitatea spaţiului de nume** (spaţiul de stocare al clusterului HDFS este caracterizat prin scalabilitate,​ astfel încât proiectele de dimensiuni mari sau cele care utilizează numeroase fişiere de dimensiuni mai mici pot beneficia de scalabilitatea spaţiului de nume prin adăugarea mai multor noduri de nume la cluster), **performanţa** (îmbunătăţirea ratei de transfer pentru operaţiile de citire / scriere în cadrul sistemului de fişiere prin adăugarea mai multor noduri de nume în cadrul clusterului) şi **izolarea** (categorii diferite de aplicaţii şi utilizatori pot fi izolate în cadrul unor spaţii de nume diferite). Într-o arhitectură care foloseşte un singur spaţiu de nume, într-un mediu concurent, o aplicaţie poate suprasolicita spaţiu de nume astfel încât performanţele celorlalte aplicaţii ce utilizează acelaşi spaţiu de nume vor fi afectate.
  
-  * **implementarea MapReduce NextGen** (**YARN, MRv2**) prin care se împart funcţionalităţile modulului de monitorizare a sarcinilor (//eng.// Job Tracker) – gestiunea resurselor şi planificarea sarcinilor în procese separate; în acest mod, se creează **un modul global de gestiune al resurselor** (Resource Manager) şi **un modul de bază al aplicaţiei** (Application Master) pentru fiecare aplicaţie în parte. O aplicaţie este formată fie dintr-o singură sarcină (din punctul de vedere al sarcinilor de tip MapReduce) sau conţine un graf aciclic de sarcini. Modulul de gestiune al resurselor împreună cu **modulul de gestiune al nodurilor** (Node Manager) formează cadrul de calcul al sarcinilor. Modulul de gestiune al resurselor este autoritatea care arbitrează modul de distribuire al resurselor pentru aplicaţiile din sistem. Modulul de gestiune pentru aplicaţii este de fapt o bibliotecă ce negociază resursele primite de la modulul de gestiune al resurselor colaborând cu modulele de gestiune a nodurilor pentru a executa şi pentru a monitoriza sarcinile.\\ \\ {{ :​laboratoare:​laborator08:​yarn_architecture.png?nolink }} \\ \\ Modulul pentru gestiunea resurselor cuprinde două componente de bază: **modulul de planificare** şi **modulul de gestiune al aplicaţiilor**.\\ \\  Modulul de planificare este responsabil pentru alocarea resurselor către diferite aplicaţii, caracterizate prin constrângeri referitoare la capacitate, cozi. Acesta nu oferă însă nici o garanţie în privinţa repornirii sarcinilor eşuate datorită erorilor produse la nivel hardware sau software şi nici nu se ocupă cu monitorizarea stării aplicaţiilor. Planificarea se realizează în funcţie de cerinţele pentru resurse ale aplicaţiilor,​ specificate de noţiunea abstractă container care cuprinde elemente ca memorie, procesor, disc, reţea. În versiunile anterioare ale Hadoop, singurul criteriu luat în considerare de planificator era reprezentat de memorie. Modulul de planificare suportă extensii programabile (precum CapacityScheduler sau FairScheduler) responsabile cu partiţionarea clusterului între diferite aplicaţii. Extensia programabilă CapacityScheduler suportă cozi ierarhice pentru a permite partajarea resurselor clusterului în funcţie de previziuni.\\ \\ Modulul de gestiune al aplicaţiilor se ocupă cu acceptarea sarcinilor transmise, negociind container-ul pentru executarea modulului de bază al aplicaţiei,​ oferind servicii pentru repornirea container-ului acestuia în situaţia în care s-au produs erori.\\ \\ Modulul de gestiune al nodurilor este un cadru implementat pe fiecare maşină în parte, responsabil pentru containere, monitorizându-le utilizarea resurselor (procesor, memorie, disc, reţea) şi raportând aceste valori la modulul de gestiune al resurselor şi la modulul de planificare.\\ \\ Modulul de bază al aplicaţiei are rolul de a negocia containerele de resurse corespunzătoare de la modulul de planificare,​ monitorizându-le starea.+  * **implementarea MapReduce NextGen** (**YARN, MRv2**) prin care se împart funcţionalităţile modulului de monitorizare a sarcinilor (//eng.// Job Tracker) – gestiunea resurselor şi planificarea sarcinilor în procese separate; în acest mod, se creează **un modul global de gestiune al resurselor** (Resource Manager) şi **un modul de bază al aplicaţiei** (Application Master) pentru fiecare aplicaţie în parte. O aplicaţie este formată fie dintr-o singură sarcină (din punctul de vedere al sarcinilor de tip MapReduce) sau conţine un graf aciclic de sarcini. Modulul de gestiune al resurselor împreună cu **modulul de gestiune al nodurilor** (Node Manager) formează cadrul de calcul al sarcinilor. Modulul de gestiune al resurselor este autoritatea care arbitrează modul de distribuire al resurselor pentru aplicaţiile din sistem. Modulul de gestiune pentru aplicaţii este de fapt o bibliotecă ce negociază resursele primite de la modulul de gestiune al resurselor colaborând cu modulele de gestiune a nodurilor pentru a executa şi pentru a monitoriza sarcinile.\\ \\ {{ :​laboratoare:​laborator08:​02yarn_architecture.png?nolink }} \\ \\ Modulul pentru gestiunea resurselor cuprinde două componente de bază: **modulul de planificare** şi **modulul de gestiune al aplicaţiilor**.\\ \\  Modulul de planificare este responsabil pentru alocarea resurselor către diferite aplicaţii, caracterizate prin constrângeri referitoare la capacitate, cozi. Acesta nu oferă însă nici o garanţie în privinţa repornirii sarcinilor eşuate datorită erorilor produse la nivel hardware sau software şi nici nu se ocupă cu monitorizarea stării aplicaţiilor. Planificarea se realizează în funcţie de cerinţele pentru resurse ale aplicaţiilor,​ specificate de noţiunea abstractă container care cuprinde elemente ca memorie, procesor, disc, reţea. În versiunile anterioare ale Hadoop, singurul criteriu luat în considerare de planificator era reprezentat de memorie. Modulul de planificare suportă extensii programabile (precum CapacityScheduler sau FairScheduler) responsabile cu partiţionarea clusterului între diferite aplicaţii. Extensia programabilă CapacityScheduler suportă cozi ierarhice pentru a permite partajarea resurselor clusterului în funcţie de previziuni.\\ \\ Modulul de gestiune al aplicaţiilor se ocupă cu acceptarea sarcinilor transmise, negociind container-ul pentru executarea modulului de bază al aplicaţiei,​ oferind servicii pentru repornirea container-ului acestuia în situaţia în care s-au produs erori.\\ \\ Modulul de gestiune al nodurilor este un cadru implementat pe fiecare maşină în parte, responsabil pentru containere, monitorizându-le utilizarea resurselor (procesor, memorie, disc, reţea) şi raportând aceste valori la modulul de gestiune al resurselor şi la modulul de planificare.\\ \\ Modulul de bază al aplicaţiei are rolul de a negocia containerele de resurse corespunzătoare de la modulul de planificare,​ monitorizându-le starea.
  
 <​note>​MapReduce v2 menţine compatibilitatea cu versiunile anterioare, astfel încât acestea pot rula şi în noul cadru de execuţie după ce sunt recompilate.</​note>​ <​note>​MapReduce v2 menţine compatibilitatea cu versiunile anterioare, astfel încât acestea pot rula şi în noul cadru de execuţie după ce sunt recompilate.</​note>​
Line 546: Line 546:
 ===== Activitate de Laborator ===== ===== Activitate de Laborator =====
  
-  ​* schelet de cod +**0**. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://www.github.com/​aipi2015/​Laborator08]]. În urma acestei operații, directorul Laborator08 va trebui să conțină subdirectorul ''​labtasks'',​ fișierele ''​README.md''​ și ''​LICENSE''​.
-    ​* {{ :​laboratoare:​laborator10:​aipi2014-lab10-hadoop251hbase09861.tar.gz }} (varianta Hadoop 2.5.1 / HBase 0.98.6.1) +
-    * {{ :laboratoare:​laborator10:​aipi2014-lab10-hadoop260hbase0988.tar.gz }} (varianta Hadoop 2.6.0 / HBase 0.98.8)+
  
-  * script-uri HBase: {{ :laboratoare:​laborator10:​aipi2014-lab10-hbasescripts.tar.gz }}+<​code>​ 
 +student@aipi2015:~$ git clone https://​www.github.com/​aipi2015/​Laborator08.git 
 +</​code>​
  
-**1.** Să se deschidă maşina virtuală [[http://aipi2014.andreirosucojocaru.ro/​Ubuntu1404.zip|Ubuntu 14.04]] / [[http://​aipi2014.andreirosucojocaru.ro/​Ubuntu1410.zip|Ubuntu 14.10]], autentificarea făcându-se ​cu utilizatorul aipi2014 ​şi parola StudentAipi2014.+<note tip>În cadrul acestui laborator, este necesar să se foloseasă [[:​resurse:​masina_virtuala|masina virtuală Ubuntu 14.04]] care conține instalate Hadoop 2.6.1, HBase 1.1.2 precum și un plugin pentru mediul integrat de dezvoltare Eclipse, prin intermediul căruia pot fi dezvoltate aplicațiile distribuite folosind aceste tehnologii. </​note>​ 
 + 
 +**1.** Să se pornească maşina virtuală [[http://aipi2015.andreirosucojocaru.ro/​Aipi2015.zip|Ubuntu 14.04]], autentificarea făcându-se ​folosind credențialele aipi2015 (ca nume de utilizator) ​şi StudentAipi2015 (ca parolă).
  
 **2.** Într-un terminal, să se pornească sistemul de fişiere distribuite HDFS şi sistemul de gestiune al resurselor YARN. **2.** Într-un terminal, să se pornească sistemul de fişiere distribuite HDFS şi sistemul de gestiune al resurselor YARN.
Line 563: Line 565:
 <note important>​Verificaţi faptul că au pornit corect prin inspectarea interfeţelor web de la adresele [[http://​localhost:​50070]],​ respectiv [[http://​localhost:​8088]].</​note>​ <note important>​Verificaţi faptul că au pornit corect prin inspectarea interfeţelor web de la adresele [[http://​localhost:​50070]],​ respectiv [[http://​localhost:​8088]].</​note>​
  
-**3.** Într-un terminal, să se pornească o instanţă a bazei de date distribuită ​HBase.+**3.** Într-un terminal, să se pornească o instanţă a sistemului ​de gestiune pentru baze distribuite ​HBase.
  
 <​code>​ <​code>​
Line 569: Line 571:
 </​code>​ </​code>​
  
-<note important>​Verificaţi starea bazei de date HBase prin intermediul interfeţei web disponibilă la adresa [[http://​localhost:​60010]].</​note>​ +<note important>​Verificaţi faptul că rulează toate procesele Hadoop ​/ HBase rulând comanda
- +
-<note important>​Verificaţi faptul că rulează toate procesele Hadoop rulând comanda+
 <​code>​ <​code>​
-student@aipi2015:​~$ ​/​usr/​local/​java/​jdk1.8.0_25/​bin/​jps+student@aipi2015:​~$ jps
 </​code>​ </​code>​
 +În execuție trebuie să se afle procesele Java NameNode, SecondaryNameNode,​ DataNode (ale sistemului distribuit de fișiere HDFS), ResourceManager,​ NodeManager (ale sistemului de gestiune a resurselor YARN), respectiv HRegionServer,​ HMaster și HQuorumPeer (ale sistemului de gestiune pentru baze de date distribuite HBase).
 </​note>​ </​note>​
  
-**4.** Să se ruleze script-urile HBase pentru ​crearea şi popularea ​bazei de date. Vor trebui rulate scripturile ''​Laborator10_DDLc.rb''​ şi ''​Laborator10_DML.rb''​.+**4.** Să se ruleze script-urile HBase pentru ​instalarea ​bazei de date. Vor trebui rulate scripturile ''​Laborator08_DDLc.rb''​ şi ''​Laborator08_DML.rb'',​ localizate în directorul ''​scripts''​.
  
 Va fi apelat utilitarul ''​hbase''​ (cu parametrul ''​shell''​),​ indicându-se căile absolute către scripturile care trebuie rulate. Va fi apelat utilitarul ''​hbase''​ (cu parametrul ''​shell''​),​ indicându-se căile absolute către scripturile care trebuie rulate.
  
 <code bash> <code bash>
-student@aipi2015:​~/​HBaseScripts$ hbase shell Laborator10_DDLc.rb +student@aipi2015:​~/​scripts$ hbase shell Laborator08_DDLc.rb 
-student@aipi2015:​~/​HBaseScripts$ hbase shell Laborator10_DML.rb+student@aipi2015:​~/​scripts$ hbase shell Laborator08_DML.rb
 </​code>​ </​code>​
  
-<note tip>De asemenea, există un script ''​Laborator10_DDLd.rb''​ pentru ​ştergerea tabelelor din cadrul ​bazei de date, în cazul în care acestea se doresc a fi dezinstalate.</​note>​+<note tip>De asemenea, există un script ''​Laborator08_DDLd.rb''​ pentru ​dezinstalarea ​bazei de date, în cazul în care o astfel de operație este necesară.</​note>​
  
-Este instalată o bază de date care are următoarea structură:+Structura bazei de date conține ​următoarele tabele, familii de coloane și atribute:
  
 <​html>​ <​html>​
Line 594: Line 595:
 </​html>​ </​html>​
  
-^  Tabela ​ ^  Familia de Coloane ​ ^  ​Coloane ​ ^+^  Tabela ​ ^  Familia de Coloane ​ ^  ​Atributul ​ ^
 | country | identification | name, code | | country | identification | name, code |
 | ::: | detail | description | | ::: | detail | description |
Line 643: Line 644:
 **5.** Se doreşte afişarea unei liste conţinând toţi utilizatorii (identificaţi prin nume şi prenume) precum şi sumele pe care aceştia le-au cheltuit prin achiziţia de cărţi din librăria virtuală. **5.** Se doreşte afişarea unei liste conţinând toţi utilizatorii (identificaţi prin nume şi prenume) precum şi sumele pe care aceştia le-au cheltuit prin achiziţia de cărţi din librăria virtuală.
  
-În cazul unui sistem de gestiune pentru baze de date relaţionale,​ o astfel de problemă are o soluţie foarte simplă ce constă într-o operaţie de joncţiune între tabelele ​book, user, invoice ​şi invoice_detail. Pentru un volum foarte mare de informaţii,​ o astfel de operaţie poate dura o perioadă de timp inacceptabilă,​ motiv pentru care se doreşte ca procesarea să se realizeze în paralel, pe mai multe maşini, fiecare gestionând o parte dintre înregistrările tabelelor respective.+În cazul unui sistem de gestiune pentru baze de date relaţionale,​ o astfel de problemă are o soluţie foarte simplă ce constă într-o operaţie de joncţiune între tabelele ​''​book_presentation''​, ''​user''​, ''​invoice_header'' ​şi ''​invoice_line''​. Pentru un volum foarte mare de informaţii,​ o astfel de operaţie poate dura o perioadă de timp inacceptabilă,​ motiv pentru care se doreşte ca procesarea să se realizeze în paralel, pe mai multe maşini, fiecare gestionând o parte dintre înregistrările tabelelor respective.
  
-Un sistem MapReduce poate împărţi datele de intrare (tabela ​invoice_detail ​pentru situaţia de faţă) în mai multe regiuni în mod automat, fiecare dintre acestea fiind prelucrate de un proces separat. Astfel, pentru fiecare detaliu din factură, reprezentând un produs al facturii se determină preţul total, obţinut prin înmulţirea preţului cărţii (obţinut printr-o interogare a tabelei ​cărţi) cu cantitatea precizată. Pentru o factură dată prin identificatorul său, se asociază preţul total al fiecărui produs pe care îl conţine. Ulterior, se creează o listă corespunzătoare fiecărei facturi conţinând toate preţurile totale ale produselor aferente. Acestea vor fi însumate, obţinându-se valoarea facturii.+Un sistem MapReduce poate împărţi datele de intrare (tabela ​''​invoice_line'' ​pentru situaţia de faţă) în mai multe regiuni în mod automat, fiecare dintre acestea fiind prelucrate de un proces separat. Astfel, pentru fiecare detaliu din factură, reprezentând un produs al facturii se determină preţul total, obţinut prin înmulţirea preţului ​formatului de prezentare a cărţii (obţinut printr-o interogare a tabelei ​''​book_presentation''​) cu cantitatea precizată. Pentru o factură dată prin identificatorul său, se asociază preţul total al fiecărui produs pe care îl conţine. Ulterior, se creează o listă corespunzătoare fiecărei facturi conţinând toate preţurile totale ale produselor aferente. Acestea vor fi însumate, obţinându-se valoarea facturii.
  
 <​html>​ <​html>​
Line 690: Line 691:
 Se observă faptul că structura coloanelor marcate este echivalentă,​ astfel încât aplicaţia va consta din 2 sarcini, din care una va avea atât partiţie de tip map cât şi partiţie de tip reduce, iar una va avea numai partiţie de tip reduce. De asemenea, se observă faptul că datele de ieşire ale unei sarcini reprezintă datele de intrare pentru cealaltă sarcină. Se observă faptul că structura coloanelor marcate este echivalentă,​ astfel încât aplicaţia va consta din 2 sarcini, din care una va avea atât partiţie de tip map cât şi partiţie de tip reduce, iar una va avea numai partiţie de tip reduce. De asemenea, se observă faptul că datele de ieşire ale unei sarcini reprezintă datele de intrare pentru cealaltă sarcină.
  
-În aplicaţia ''​BookStoreMapReduce'',​ cele două sarcini se numesc ''​billValue''​ şi ''​userExpenses'',​ fiind definite (prin partiţiile map şi reduce corespunzătoare) în clasa cu acelaşi nume.+În aplicaţia ''​BookStore'',​ cele două sarcini se numesc ''​invoiceValue''​ şi ''​userExpenses'',​ fiind definite (prin partiţiile map şi reduce corespunzătoare) în clasa cu acelaşi nume.
  
-**a)** în clasa ''​Map''​ a sarcinii ''​billValue''​ (clasa ''​BillValueMapper''​ din pachetul ''​ro.pub.cs.aipi.lab10.mapper''​),​ să se determine preţul cărţii analizate în mod curent (care se găseşte în detaliul de factură repartizat procesului curent);+**a)** în clasa ''​Map''​ a sarcinii ''​invoiceValue''​ (clasa ''​InvoiceValueMapper''​ din pachetul ''​ro.pub.cs.aipi.lab08.mapper''​),​ să se determine preţul ​formatului de prezentare a cărţii analizate în mod curent (care se găseşte în detaliul de factură repartizat procesului curent);
  
-Se va crea o instanţă a clasei ''​HTable'' ​şi un obiect de tip ''​Get''​ în care se va specifica atributul ce se doreşte obţinut (prin metoda ''​addColumn()'',​ indicându-se atât familia coloanei cât şi denumirea propriu-zisă a coloanei), din aplicarea acestuia generându-se un obiect ''​Result''​ pentru care se apelează metoda ''​getValue()''​ în scopul de a se obţine valoarea dorită.+<​spoiler|Indicații de rezolvare>​ 
 +Se va crea o instanţă a clasei ''​Table''​, pe baza unui obiect de tip ''​Connection''​ (obținut prin intermediul unei fabrici de conexiuni, ''​ConnectionFactory''​),​ pentru care se apelează metoda ''​createConnection()'',​ aceasta primind ca argument denumirea tabelei respective (''​TableName.valueOf(...)''​). Ulterior, se creează ​un obiect de tip ''​Get''​ în care se va specifica atributul ce se doreşte obţinut (prin metoda ''​addColumn()'',​ indicându-se atât familia coloanei cât şi denumirea propriu-zisă a coloanei), din aplicarea acestuia generându-se un obiect ''​Result''​ pentru care se apelează metoda ''​getValue()''​ în scopul de a se obţine valoarea dorită.
  
-**b)** în clasa ''​Reduce'' ​a sarcinii ''​billValue''​ (clasa ''​BillValueReducer''​ din pachetul ''​ro.pub.cs.aipi.lab10.reducer''​),​ să se calculeze preţul total pentru o factură, prin agregarea tuturor sumelor parţiale specificate în detaliile de factură;+<note important>​Nu uitați să eliberați resursele asociate atât tabelei HBase pe care se realizează interogarea cât și a conexiunii pe baza căreia aceasta a fost obținută, prin apelarea metodei ​''​close()''​.</​note>​
  
-**c)** în clasa ''​Reduce''​ a sarcinii ''​billValue''​ (clasa ''​BillValueReducer''​ din pachetul ''​ro.pub.cs.aipi.lab10.reducer''​),​ să se obţină, prin interogarea tabelei facturi, CNP-ul utilizatorului căruia i-a fost emisă factura analizată în mod curent;+</​spoiler>​
  
-**d)** în clasa ''​Reduce''​ a sarcinii ''​billValue''​ (clasa ''​BillValueReducer'' ​din pachetul ​din pachetul ''​ro.pub.cs.aipi.lab10.reducer''​),​ să se obţină, prin interogarea tabelei utilizatori,​ numele şi prenumele clientului având CNP-ul determinat anterior;+**b)** în clasa ''​Reduce''​ a sarcinii ''​invoiceValue''​ (clasa ''​InvoiceValueReducer''​ din pachetul ''​ro.pub.cs.aipi.lab08.reducer''​),​ să se calculeze preţul total pentru o factură, prin agregarea tuturor sumelor parţiale specificate în detaliile de factură;
  
-**e)** în clasa ''​BookStoreMapReduce''​ din pachetul ''​ro.pub.cs.aipi.lab10.main'', ​pentru sarcina ​''​userExpenses'', ​să se indice valorile claselor corespunzătoare cheii şi valorii datelor de ieşire;+**c)** în clasa ''​Reduce''​ a sarcinii ''​invoiceValue''​ (clasa ''​InvoiceValueReducer''​ din pachetul ''​ro.pub.cs.aipi.lab08.reducer''​), să se obţină, prin interogarea tabelei ​''​invoice_header'', ​identificatorul utilizatorului căruia i-a fost emisă factura analizată în mod curent;
  
-Întrucât datele de ieşire sunt reprezentate de tuplul (numeprenume,​ valoare), tipurile de date corespunzătoare vor fi ''​Text''​, respectiv ​''​LongWritable''​.+**d)** în clasa ''​Reduce'' ​a sarcinii ​''​invoiceValue'' ​(clasa ''​InvoiceValueReducer''​ din pachetul din pachetul ''​ro.pub.cs.aipi.lab08.reducer''​),​ să se obţină, prin interogarea tabelei ''​user'',​ numele şi prenumele clientului având identificatorul determinat anterior;
  
-**f)** în clasa ''​Reduce''​ a sarcinii ''​userExpenses''​ (clasa ''​UserExpensesFileReducer''​ din pachetul ''​ro.pub.cs.aipi.lab10.reducer''​), să determine valoarea totală a facturilor achitate de client şi să se scrie această valoare în context (folosind metoda ​''​write()'', ​cheia de rând fiind reprezentată de numele ​şi prenumele utilizatorului);+**e)** în clasa ''​BookStore''​ din pachetul ''​ro.pub.cs.aipi.lab08.main'', ​pentru sarcina ​''​userExpenses'', ​să se indice valorile claselor corespunzătoare cheii şi valorii datelor ​de ieşire;
  
-De remarcat faptul că pentru citirea datelor ​de intrare în cazul sarcinii ''​userExpenses'',​ a fost folosită o clasă specială, definită ​de utilizator ​(''​CustomFileInputFormat''​),​ în care datele au forma (cheie, valoare), iar separatorul dintre aceste entităţi este TAB-ul. Întrucât cheia este reprezentată de numele şi prenumele utilizatorilor,​ iar valoarea de suma unei facturi, tipurile de date procesate în clasa ''​CustomFileInputFormatRecordReader'' ​vor fi ''​Text'',​ respectiv ''​LongWritable''​. ​O astfel de soluţie a fost adoptată datorită faptului că nu au fost definite tipuri de fişiere de intrare care să aibă această structură.+<​spoiler|Indicații ​de Rezolvare>​ 
 +Întrucât datele ​de ieşire sunt reprezentate de tuplul ​(nume&​prenume, valoare), tipurile de date corespunzătoare ​vor fi ''​Text'',​ respectiv ''​DoubleWritable''​. 
 +</​spoiler>​
  
-**6.** Să se rezolve problema anterioară,​ stocând rezultatele nu într-un fişier ci în tabela statistici ​a bazei de date HBase, care are o singură familie ​de coloane, cheltuieli, în care o posibilă coloană ar putea fi valoare.+**f)** în clasa ''​Reduce'' ​a sarcinii ''​userExpenses''​ (clasa ''​UserExpensesFileReducer''​ din pachetul ''​ro.pub.cs.aipi.lab08.reducer''​), să determine valoarea totală a facturilor achitate ​de client şi să se scrie această valoare ​în context (folosind metoda ''​write()'',​ cheia de rând fiind reprezentată de numele şi prenumele utilizatorului);​
  
-**a)** În clasa ''BookStoreMapReduce'' din pachetul ''​ro.pub.cs.aipi.lab10.main'', ​se va apela metoda statică ''​initTableReducerJob()'' ​a clasei ​''​TableMapReduceUtil''​ ce primeşte ca parametrii denumirea tabelei unde se doresc a fie redirectate ​datele de ieşire, numele clasei care implementează sarcina ​de tip ''​Reduce'' ​şi numele obiectului de tip ''​Job''​. De asemenea, va trebui indicat şi numărul sarcinilor de tip ''​Reduce''​.+De remarcat faptul că pentru citirea datelor de intrare în cazul sarcinii ​''​userExpenses'', ​a fost folosită o clasă specială, definită de utilizator ​(''​CustomFileInputFormat''​), în care datele ​au forma (cheie, valoare), iar separatorul dintre aceste entităţi este TAB-ul. Întrucât cheia este reprezentată ​de numele ​şi prenumele utilizatorilor, iar valoarea ​de suma unei facturi, tipurile de date procesate în clasa ''​CustomFileInputFormatRecordReader'' ​vor fi ''​Text'', ​respectiv ​''​DoubleWritable''​. O astfel de soluţie a fost adoptată datorită faptului că nu au fost definite tipuri de fişiere de intrare care să aibă această structură.
  
-**b)** În clasa ''​UserExpensesTableReducer''​ din pachetul ''​ro.pub.cs.aipi.lab10.reducer'',​ ulterior determinării sumei totale achitate de client, să se creeze un obiect de tip ''​Put''​ având drept cheie numele şi prenumele utilizatorului,​ adăugându-se (prin metoda ''​add()''​),​ ca valoare a celulei identificată de coordonatele ''​expense:​value'',​ suma tuturor facturilor, corespunzând produselor achiziţionate.+**6.** Să se rezolve problema anterioară,​ stocând rezultatele nu într-un fişier ci în tabela ''​statistics''​ a bazei de date HBase, care are o singură familie de coloane, ''​expense'',​ în care o posibilă coloană ar putea fi valoare. 
 + 
 +**a)** În clasa ''​BookStore''​ din pachetul ''​ro.pub.cs.aipi.lab08.main'',​ se va apela metoda statică ''​initTableReducerJob()''​ a clasei ''​TableMapReduceUtil''​ ce primeşte ca parametrii denumirea tabelei unde se doresc a fie redirectate datele de ieşire, numele clasei care implementează sarcina de tip ''​Reduce''​ şi numele obiectului de tip ''​Job''​. De asemenea, va trebui indicat şi numărul sarcinilor de tip ''​Reduce''​. 
 + 
 +**b)** În clasa ''​UserExpensesTableReducer''​ din pachetul ''​ro.pub.cs.aipi.lab08.reducer'',​ ulterior determinării sumei totale achitate de client, să se creeze un obiect de tip ''​Put''​ având drept cheie numele şi prenumele utilizatorului,​ adăugându-se (prin metoda ''​addColumn()''​),​ ca valoare a celulei identificată de coordonatele ''​expense:​value'',​ suma tuturor facturilor, corespunzând produselor achiziţionate. 
 + 
 +**7**. Să se verifice rezultatele obținute. 
 + 
 +<​spoiler|Indicații de Rezolvare>​ 
 +**a)** în situația în care rezultatele au fost stocate în sistemul de fișiere HDFS, se poate folosi plugin-ul pentru mediul integrat de execuție Eclipse, care conferă un navigator pentru acest sistem de fișiere;\\  
 +**b)** în situația în care rezultatele au fost stocate în tabela ''​statistics''​ din cadrul sistemului de gestiune pentru baze de date distribuite ''​HBase'',​ se poate verifica conținutul acesteia: <​code>​ 
 +student@aipi2015:​~$ hbase shell 
 +hbase> scan '​statistics'​ 
 +</​code>​ 
 +</​spoiler>​
  
-**7.** Înainte de a închide ​maşina virtuală, să se oprească instanţa ​bazei de date distribuită ​HBase precum şi a sistemului de gestiune a resurselor YARN, respectiv al sistemului de fişiere distribuite HDFS.+**8.** Înainte de a opri maşina virtuală, să se oprească instanţa ​sistemului de gestiune pentru baze de date distribuite ​HBase precum şi a sistemului de gestiune a resurselor YARN, respectiv al sistemului de fişiere distribuite HDFS.
  
 <​code>​ <​code>​
Line 734: Line 752:
 ===== Soluții ===== ===== Soluții =====
  
-TODO+[[https://​github.com/​aipi2015/​Laborator08/​tree/​master/​solutions|Proiect Eclipse]]
laboratoare/laborator08.1449798661.txt.gz · Last modified: 2015/12/11 03:51 by Andrei Roșu-Cojocaru
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0