MapReduce: do more with less...

Recentemente mi sono trovato a dover ristrutturare una applicazione parecchio datata; e con "datata" intendo che sono passato circa tre anni dalla sua prima implementazione (che nell'informatica sono equiparabili ad una era geologica). Diciamo anche che l'applicazione in oggetto ha sempre sofferto delle conseguenze della formula magica "il cliente ha fretta" e "ci metto una pezza".

Il prodotto che ne è uscito è la classica "palla di pezze", composta da una miriade di soluzioni cervellotiche, dove è evidente che non si è fatto un utilizzo adeguato della materia cerebrale in momenti di elevata pressione.

Tutto considerato, la soluzione soddisfa i requisiti: i risultati attesi dal cliente sono quelli sperati e non ci sono intoppi particolari; se non che si arriva al fatidico giorno dove l'utente di turno vuole processare un file con circa una "mezza milionata" di elementi. Il povero applicativo ce la mette tutta, ma non c'è nulla da fare: i tempi di elaborazioni sono "biblici".

Metterci mano per migliorare le performance generali del sistema vuole dire riscrivere buona parte dei flussi funzionali; e l'architettura con cui è nato il sistema non permette la separazione in modulo logici, scorporabili e sostituibili con poco sforzo.

Quindi mi son ricordato di un magnifico articolo che ho letto recentemente sulle tecniche che Google utilizza per eseguire ricerche e completare elaborazioni sui suoi petabyte di dati. Tra queste quella che è tema di questo post: "MapReduce".

MapReduce è un algoritmo che trae ispirazione dalla programmazione funzionale. Dico "trae ispirazione" perchè la sua implementazione e funzionalità non sono quelli originali, ma sono stati studiati e formalizzati da Google, che ha poi concesso il suo utilizzo libero a tutta la community. Il principio, nella sua semplicità, è letteralmente geniale; si basa sull'idea di sfruttare la "collaborazione" per portare a termine un compito lungo e gravoso. Cercherò di spiegarvelo con la metafora con cui è stato spiegato a me.

Immaginate di avere un palazzo di "X" piani di uffici; voi siete l'addetto alla sicurezza del palazzo e dovete sapere quante persone lavorano nel palazzo per poter essere sicuri di evacuare tutte le persone in caso di incendio del palazzo stesso. Adesso non ditemi che vi basta fare qualche telefonata, perchè vi ci mando, eh? ;)

Il vostro compito è piuttosto arduo: dovete salire su ogni piano, entrare in ogni ufficio e contare le persone che ci lavorano per poter sapere il numero totale degli "abitanti" del palazzo. La funzione "ContaPersoneNelPiano(x)" deve essere iterata dal piano "0" (il pianterreno) al piano N (l'attico).

Per poter conoscere il numero totale di persone è quindi necessario impiegare un tempo "T per X", dove "T" è il tempo necessario per contare le persone di un singolo piano, ed "X" è il numero di piani di cui è composto il palazzo. E' naturale quindi che l'intera elaborazione che dovete portare a termine è direttamente proporzionale all'altezza del palazzo (il numero di piani), e che più il palazzo è alto, maggiore sarà il tempo di attesa per ottenere l'output finale.

Immaginamo ora di avere "X" assistenti. Poichè ho anche "X" piani, il mio compito diventa più semplice: assegno un assistente ad ogni piano, impartisco a ciascuno l'ordine di contare il numero di persone per il piano assegnato, quindi riportare il conteggio direttamente a me. Il mio compito di chiude facendo la "somma" di tutti i conteggi che i miei assistenti hanno eseguito.

D'un tratto passo dall'essere un "esecutore" materiale dell'azione ad un "supervisore" del processo di elaborazione. Le mie uniche attività sono quelle definite dall'algoritmo in questione: "Map", quando assegno il piano "Z" all'assistente "Y", e "Reduce", quando prendo i conteggi parziali dei miei assistenti e li sommo ("riduco") per avere l'output voluto.

Chiaramente i miei "aiutanti" lavoreranno in maniera assolutamente parallela, evitando quindi la problematica della crescita proporzionale del tempo di elaborazione man mano che cresce il dominio dati (il numero di piani).

Finito di leggere mi sono detto: "FIGATA! Come posso sfruttare la cosa per le mie necessità di elaborazione quotidiane?". Volete saperlo? Lo scoprirete nella prossima puntata... ;)

Commenti

  1. L'esempio che hai fornito mi ha consentito di comprendere MapReduce, ti ringrazio!
    Ottima esposizione ed ottimo blog, complimenti per il tuo lavoro.

    RispondiElimina
    Risposte
    1. Ti ringrazio davvero; fa piacere ogni tanto essere utile a qualche collega...
      Alla prossima...
      M.

      Elimina

Posta un commento

Post popolari in questo blog

Cancellazione fisica vs cancellazione logica dei dati

Restore di un database SQL Server in un container Docker

Costruire una DataSession custom con Chakra.Core