Replicazione 2 In un sistema distribuito, essendoci più di un
Transcript
Replicazione 2 In un sistema distribuito, essendoci più di un
Replicazione 2 In un sistema distribuito, essendoci più di un processore, avremo in linea di massima un comportamento migliore che nel concentrato, in cui vi è un unico processore e se questi si guastasse tipicamente nessuno ci viene in aiuto. In un sistema distribuito, la presenza di un insieme di processori partecipanti permette quindi, la replicazione delle risorse che ci servono e che utilizziamo: più copie delle risorse su nodi diversi in modo tale che se cade un nodo ve n'è un altro pronto ad essere utilizzato. Ciò allunga il tempo di vita dell'applicazione stessa. In generale, parlare di replicazione vuol dire parlare di fault-tollerance. Si parla pertanto di guasto, che in realtà è ascrivibile ad una serie di termini inglesi molto usati, che non sono considerati equivalenti: failure/fallimento qualunque comportamento diverso da quello previsto dai requisiti. Ad esempio, dato un conto in banca, se questi sia stato realizzato senza tener conto che prelievi e depositi possano venir effettuati contemporaneamente: presenza di conflitti: failure che non sono segnalate dal sistema. error difetto che genera una failure fault/guasto comportamento nel sistema che può causare errori (scrittura contemporanea non prevista su di un conto in banca). Pertanto, il fault rappresenta la causa a monte, l'errore la causa concreta, e l'effetto visibile è la failure. Quello che si vuole, quindi, è non incappare in situazioni di failure, e che guasti e fault siano in qualche modo tollerati. Pertanto la replicazione vuol dire per l'appunto questo: introdurre risorse per non favorire la creazione di failure, quindi di mancato servizio non in accordo ai requisiti richiesti. Fault di due tipi: Bohrbug: fault più facili da correggere, un po' più transitori come ad esempio una locazione di memoria in cui in certi momenti scriviamo ed in altri leggiamo; sono errori ripetibili, sicuri e facili da correggere. Eisenbug: fault pesanti, poco ripetibili, difficili da risolvere e da riprodurre. NOTA: A volte è meglio avere dei fault più permanenti che transitori perché facili da studiare e magari da poter correggere in futuro. 3 Dalla figura sottostante si vede quali sono le tipiche failure che si possono riscontrate e per la quali vi è, quindi, un blocco del sistema. In alcuni casi vi sono situazioni di disastro, in altri la causa è l'uomo mentre in altri l'hardware, in Reti di Calcolatori LM 29 altri ancora cause software. Chiaramente, quando capita una situazione di questo genere, comunque il servizio deve essere continuamente fornito, il ché prevede che, e questo vale per chi fornisce il servizio, si debba capire che in quel dato momento vi è un guasto, si deve poterlo notificare e poi fare recovery per tornare alla situazione normale di esecuzione. 4 Come si nota dal grafico in figura, la maggior parte delle failure è data alla presenza di problemi software: i downtime di un sistema sono causati per quasi il 50% da problemi riguardanti errori software e delle applicazioni. 5–6 I tempi di non disponibilità di un sistema si misurano, si dice, in downtime, mentre il tempo di disponibilità in uptime. In alcuni casi potremmo avere un'approssimazione molto vicina, ad esempio al 99% (ciò vuol dire che quel sistema lavora per il 99% del tempo in uptime), in molti casi, in realtà, la percentuale di non funzionamento deve diventare molto piccola, come ad esempio nei servizi bancari, finanziari, medici e soprattutto nei sistemi militari. 7 Ovviamente avere un sistema che non funziona vuol dire avere delle perdite. In alcuni casi, i sistemi che non funzionano, come sistemi ospedalieri, possono portare anche a perdite di vite con costi 30 Stefano Di Monte difficilmente stimabili. Restano comunque in cima alla classifica in quanto ad ammontare di perdite, i sistemi finanziari e quelli militari. 8 Ora un po' di terminologia: Dependability (fault tolerance) -confidenzaSi intende un sistema in cui, il comportamento del sistema stesso, fosse in grado di continuare ad operare anche in caso di fault. Si parla di confidenza per ogni aspetto progettuale, sia in senso hardware, che software ed in generale. Reliability - affidabilitàUn sistema che sia reliable, è un sistema che è affidabile, ossia che a fronte di certe specifiche e certi requisiti si comporta correttamente. Risponde ai requisiti, in caso di presenza di risposte da dare, in maniera corretta. Un sistema reliable dà particolare importanza alla correttezza della risposta e non al tempo. Quindi basa il suo operato sulla presenza di un supporto molto forte che tiene le risposta per poi consegnarla a chi di dovere: pertanto non è un sistema reattivo. Availability -disponibilitàContrasta la reliability, significa continuità e prevede che un sistema risponda entro certi limiti temporali. Particolarmente importante per un sistema reattivo, non di sistemi real-time ma semplicemente di sistemi che devono dare una certa risposta entro un certo tempo (anche se la risposta fosse: “non posso dare una risposta” o addirittura una risposta scorretta in quanto segue questa metodica: meglio dare una risposta scorretta che non darla proprio). Recoverability Un sistema che a fronte di guasto sia in grado di produrre un nuovo stato corretto quando il guasto è stato capito, e “recuperato” nel modo giusto. 9 I sistemi c/s, ci interessano perché composti da un'interazione molto sincrona, e i due ruoli consentono anche una capacità di controllo reciproco: Il cliente fa la richiesta sincrona bloccante e attende la risposta, e nel frattempo sta anche controllando che il servitore sia funzionante e riesca a dare una risposta nei tempi giusti. Dalla parte del servitore, questi riceve riceve una richiesta e quindi deve dare una risposta, ma controlla anche che il cliente sia pronto per riceverla. Pertanto il cliente ed il servitore si controllano a vicenda! In sostanza, tutti gli schemi a forte coordinamento, quelli sincroni bloccanti, sono schemi in cui è facile introdurre il discorso del controllo dei guasti e prevenire situazioni di failure. In un sistema vi sono molte circostanze di failure che possono avvenire, e per ognuna di queste sarebbe opportuno introdurre delle strategie indirizzate ad identificarle, capirne l'errore presente e riuscire a correggerlo. Il modo più semplice di fare del recovery dell'errore è quello di usare “ripetizione”: un cliente fa la richiesta, non riceve la risposta in un certo tempo e quindi ripete la richiesta; se siamo nel Reti di Calcolatori LM 31 distribuito, potrei rivolgermi ad un altro servitore, effettuando una replicazione non in tempo come quella appena descritta, bensì in spazio. In generale, per procedere nell'identificazione e, poi conseguentemente effettuare il recupero dei guasti, quello che si fa è fare delle ipotesi sui fault, e capire come lavorare nei diversi casi. 10 Un ipotesi che si fa molto spesso è l'ipotesi di guasto singolo: si assume che quando si manifesta un comportamento che porta ad un errore, non deve manifestarsi più nessun altro comportamento simile finché quest'ultimo non è stato risolto. Quindi durante la fase di recovery, si assume che non si presenti più nessun errore. Tale ipotesi, si fa molto facilmente e viene applicata nel concentrato e nel distribuito, perché molto semplificativa: se non potessimo assumerla, vorrebbe dire che durante il recovery potrebbero verificarsi situazioni di failure e che quindi l'algoritmo per il recovery si complicherebbe molto. Terminologia: TimeToRapair (TTR): tempo che intercorre dal momento dell'errore fino al recovery completo (meglio se più piccolo possibile). TimeBetweenFailure (TBF): più interessante perché rappresenta l'intervallo che intercorre in media (MTBF) tra due guasti nel sistema (meglio se più grande possibile). Supponiamo di essere ricchi e di avere delle risorse da poter dedicare all' applicazione; supponiamo ancora di prenderne una (risorsa) e consideriamo di poterla replicare; se facciamo due copie della risorsa, possiamo controllarne lo stato di ambedue e finché è lo stesso in tutte e due, allora sicuramente non si sono presentati problemi. Ma se vi si presenta un guasto, quindi le due risorse producono due risultati diversi perché han stato differente, possiamo dire con certezza che si è presentato una failure, ma non in quale risorsa essa si è presentata. Se invece avessimo 3 risorse che lavorano in maniera sincronizzata invece riusciremmo a capire, dato il caso precedente, quale è stata la risorsa interessata dal guasto, in quanto avremmo due risorse con lo stesso stato e la terza con stato differente. In realtà le considerazioni fatte non valgono per tutte le situazioni: se le risorse fossero tre persone che si mettono d'accordo e che possano parlare tra loro, pertanto se due persone si mettessero d'accordo su di un risultato e sul fatto di darlo sbagliato, avremmo solo una risorsa che darebbe il risultato giusto ma che per noi risulterebbe l'unica ad avere un guasto: situazioni maliziose. Senza le ipotesi di guasto, i ragionamenti che si fanno a volte sono intuitivi ma non sempre corretti (come quello appena citato). Le ipotesi ci aiutano quindi, a farci capire cosa sta succedendo nel sistema. Bisogna farle! 11 Tre ipotesi di guasto: fail-stop molto importante perché adottata in molti sistemi distribuiti! É l'ipotesi che ragiona sui processori e dice che: io ho una risorsa che lavora correttamente, appena 32 Stefano Di Monte fa qualcosa che devia da quelli che sono i requisiti, la risorsa si ferma (halt) e tutti possono verificarne lo stato. fail-safe ipotesi di crash: un po' più lasca di fail-stop: dato un processore che lavora correttamente, quando sta per causare una failure si ferma, però nessuno dall'esterno sa che quel processore è fermo, è lento o è congestionato, non ne conoscono lo stato. Ad esempio, abbiamo due processori (quindi replicazione hardware) che lavorano allo stesso modo e si controllano lo stato, quando uno dei due stati differisce dall'altro: fail safe! Tutto si ferma! In particolare se ci trovassimo in un modello a fail-stop, ci sarebbe bisogno di un gestore. failure bizantine Sono il comportamento più complesso che ci può essere in un sistema distribuito. Esempio: dati due eserciti A e B, di norma quello più numeroso vince. Ma se immaginiamo un esercito, magari quello più numeroso A, in una posizione tale da poter essere accerchiato, e se l'altro esercito avesse deciso di attaccare dividendosi in due parti B1 e B2 (ciascuna meno numerose di A), allora se gli eserciti B1 e B2 attaccassero in tempi diversi l'esercito A (se quindi mancassero di coordinazione), verrebbero distrutti da quest'ultimo perché più numeroso. Se invece, gli eserciti B1 e B2 accerchiassero l'esercito A e attaccassero contemporaneamente, vincerebbero la battaglia. Ma all'epoca dei bizantini l'unico modo per coordinarsi era inviare un messaggero. Ma se l'esercito A uccidesse il messaggero, o peggio ancora lo sostituisse con uno dei loro avente indicazioni sbagliate sul tempo di attacco dei due eserciti B1 e B2, vincerebbe sicuramente la battaglia. (ed eventuali altre strategie...) In generale, lavorare in tale modo, in cui i messaggi si perdono o vengono sostituiti o creati degli altri, significa lavorare nel peggior modo possibile in cui può succedere di tutto. Concludendo, facendo delle buone ipotesi, quali fail-stop e fail-safe., i processori possono difendersi in maniera relativamente accettabile. Inoltre, fare delle ipotesi sensate di guasto, permette di avere delle architetture molto semplici. 12 Le ipotesi di fail-safe e fail-stop sono state le prime ipotesi fatte e sono nate in ambiente singolo (a singolo processore). In realtà vi sono altre situazioni che vale la pena mappare, almeno in alcuni casi, perché permettono di semplificare molto bene le architetture nel distribuito. In generale, nel distribuito vi potrebbero essere dei processori che lavorano e scambiano dei messaggi, quindi, focalizzando solo la parte di comunicazione, parlando quindi di scambio di messaggi, un ipotesi che è stata fatta è la send & receive omission, che assume che le operazioni siano delle send e delle receive. In tale contesto si parla di fallimento di un processore, quando quest'ultimo non manda tutti i messaggi che avrebbe dovuto mandare o non riceve tutti i messaggi che avrebbe dovuto ricevere. Dal nome stesso ci sono quindi delle omissioni! Le soluzioni a tali omissioni sono quindi: replicazione in tempo (rinvio del messaggio dopo un certo time out) o replicazione in spazio. Altra ipotesi fatta è la general omission che mette insieme la send&receive omission con l'ipotesi di Reti di Calcolatori LM 33 crash. In sostanza dice che un processore fallisce o per lo stesso motivo dell'ipotesi fatta precedentemente o perché va in errore e si ferma. Dal punto di vista dei protocolli, la general omission, è quella più usata in quanto consente di progettare architetture sufficientemente semplici. La network failure dice che il sistema di comunicazione non si comporta come si dovrebbe comportare generando, ad esempio, lui stesso dei messaggi che non sono a carico dei processi ma del sotto sistema di comunicazione. Nella network partition viene tenuto in conto invece, l'idea del partizionamento della rete, in cui una parte della rete non riesce a comunicare con l'altra parte della rete. Naturalmente ciò può avvenire per più di due parti. Tale ipotesi la si fa quando abbiamo un sistema disconnesso in cui vogliamo lavorare. Tutte queste ipotesi di base sono state pensate per semplificare i protocolli di gestione. 13 Alcuni indicatori: MeanTimeBetweenFailure (MTBF): intervallo di tempo medio tra due guasti, quindi rappresenta quanto spesso si manifesta una failure nel sistema. Di conseguenza più grande è tale valore meglio è. MeanTimeToRepair (MTTR): per quanto tempo non funziona il sistema, quindi quanto tempo in media, ci mettiamo per farlo nuovamente funzionare in situazione normale. L'obiettivo è sicuramente quello di tenere basso il valore di tale indicatore. Availaibility: stima la disponibilità del sistema che deve rispondere entro tempi limitati. Rappresenta quindi, quanto bene e correttamente funziona il sistema ed è uguale a A = MTBF/(MTBF + MTTR). Reliability: affidabilità, dice che il comportamento di un sistema deve correttamente essere fornito secondo quello che c'aspettiamo. Spesso è stata messa in relazione col tempo, in quanto rappresenta la probabilità di servizio disponibile in delta(t). NOTA: A questo livello siamo ancora e comunque molto generali ed astratti; e questi indicatori vanno, poi nel caso particolare, utilizzati e potrebbero differenziare per ciascun servizio. 14 Questi ultimi due aspetti, sono due aspetti peculiari e diversi, entrambi dipendenti da ciò che facciamo nel sistema, e spesso, a livello hardware o software, sono stati determinati in modo diverso. Da una parte, si parla molto di safety, ossia di correttezza. Un linguaggio safe è un linguaggio che è corretto, come dice la parola stessa, cioè che mi impedisce di fare cose scorrette. A volte, per non farci correre dei rischi, tale tipo di linguaggio ci toglie visibilità, ci impedisce di eseguire determinate operazioni. 34 Stefano Di Monte Molto importante è anche la vitalità, liveness. Un sistema vitale è un sistema che procede verso il risultato che ci aspettiamo, verso il successo, entro certi tempi limitati. Quindi, dovendo mappare questi due ultimi aspetti, potremmo benissimo dire che la safety è l' availability mentre la liveness rappresenta la reliability. Se un sistema è sia safety che liveness, è un sistema ideale che raggiunge il successo entro i tempi che vogliamo. I sistemi peggiori sono quelli che non hanno nessuna di queste due caratteristiche. In generale, quando lavoriamo col fault tolerance, tipicamente tendiamo a stressare una di queste due proprietà: volgiamo magari che sia safety a scapito della vitalità, cioè vogliamo che sia corretto ma può succedere che il risultato non arrivi; in altri casi vogliamo che sia vitale ma possiamo non interessarci della correttezza. Molto spesso si cerca di soddisfare uno delle due proprietà non entrambi, anche se non mancano i casi in cui sono indispensabili entrambe le due caratteristiche. In conclusione, una soluzione per entrambe queste caratteristiche si ottiene, molto spesso, adottando la replicazione! Questa non è altro che una forma di ridondanza, la quale può essere in tempo (se vi è rinvio di messaggi) o in spazio (se replichiamo le risorse). La ridondanza è effettivamente la chiave per avere dei buoni risultati! La ridondanza però, comporta dei costi! 15 Sicuramente, quando abbiamo replicazione, tendiamo ad avere ridondanza di risorse, quindi più di una risorsa. <<Come coordiniamo quindi le varie architetture?>> • Una soluzione potrebbe essere, avere due (o più) risorse disponibile a fornire il servizio, ma solo una di queste lavora (master) e le altre (slave) che si attivano in caso di guasto. • Per evitare di avere tutti i tempi di repair necessari, si lavora con un modello in cui tutte le risorse lavorano in maniera attiva: l'operazione eseguita su di una risorsa viene eseguita su tutte le altre risorse in maniera assolutamente identica (algoritmo uguale! Si tenga però presente che utilizzare algoritmi diversi porta ad avere una massima garanzia di correttezza), il ché vuol dire lavorare a copie attive. Tale modello spreca risorse, ma ha il vantaggio di avere una copia continuamente aggiornata delle risorse stesse, e quindi la possibilità di ritrovare la risorsa che ci interessa è elevata, proprio perché le macchine lavorano in sincrono, tutte allo stesso modo, e ciò porta ad avere una ridondanza in spazio delle risorse. • Altra situazione, meno interessante, è quella in cui tutti i componenti sono uguali eseguono e producono risultati diversi. Ad esempio, un server web molto molto frequentato in cui le richieste vengono smistate tra le possibili macchine che eseguono operazioni diverse, con l'obbiettivo di avere un massimo throughput. In qualunque caso, potrebbe succedere che una copia si guasti... Pertanto, ad esempio nel caso di copie attive, l'architettura di replicazione deve prevedere ed accorgersi che la copia stia andando male, che squindi sia guasta, isolarla dalle altre e partire con il Reti di Calcolatori LM 35 recupero della stessa, ed infine reinserirla nel gruppo delle copie attive. Ci vuole quindi un'infrastruttura di gestione, un'infrastruttura di metalivello. 16 Un esempio è la memoria stabile: una memoria cioè, che garantisce letture e scritture corrette, una memoria quindi reliable. Tipicamente la memoria stabile è anche una memoria persistente. In generale questa è una memoria corretta perché c'è ridondanza ed una funzione di controllo che controlla se la memoria è corretta o meno e quindi permette la lettura/scrittura. L'idea è che ciò che è salvato in memoria sia sempre rispettoso della correttezza a scapito del tempo di attesa del risultato (che potrebbe essere lungo a piacere), per tale motivo l'implementazione è fatta su disco. 17 L'algoritmo utilizzato dalla memoria stabile è stato adottato da molti sistemi su disco, proprio perché quest'ultimi non garantiscono i tempi di risposta. In realtà si possono pensare delle realizzazioni di memoria stabile basate su copie, in memoria non permanente quindi ad accesso più veloce, mantenendo tutte le copie attive, ma in generale tutte le realizzazioni sono state fatte su disco. Il funzionamento di una memoria stabile è il seguente: • • • ogni lettura da un blocco errato viene trasformata in failure di omissione ogni scrittura procede su una delle copie e poi sull'altra se una delle copie fallisce si tenta il recovery, ossia si attiva un protocollo che ripristina uno stato consistente, pertanto: se le copie sono uguali: nessuna azione. Se una sola copia scorretta: viene copiato in questa il valore corretto se le copie sono diverse e corrette entrambe: si ripristina la consistenza (vale la versione più recente delle copie) Pertanto una memoria stabile presenta un costo di realizzazione elevato! 18 Tutte le volte che abbiamo dei sistemi con reliability, quindi nei quali riusciamo a tollerare dei guasti, sicuramente dobbiamo avere delle architetture di supporto. Quest' ultime richiedono di avere progettato degli algoritmi per gestire le situazioni (ad esempio: algoritmi per la memoria stabile, per processori fail-safe o fail-stop), comportando un elevato costo del progetto stesso. La parte di gestione dovrebbe, pertanto, essere ancora più affidabile, più dependable di quella di servizio! Basti pensare ad un sistema special-purpose, dal quale dipende ad esempio, il corretto funzionamento di una centrale nucleare, questi sicuramente ha delle risorse (software e hardware) ad hoc per la gestione dell'intera infrastruttura. Nella maggior parte dei casi, però, non abbiamo a che fare con dei sistemi special-purpose, e le risorse sono limitate, ovvero la mia rete di processori è limitata. Quindi lo scopo, è quello di creare dei modelli che rendano affidabile, dependable quella rete: le stesse risorse a disposizione debbono essere utilizzate per la comunicazione, per l'istruzione ed anche per la parte di controllo dell'intera 36 Stefano Di Monte applicazione: non abbiamo come per i sistemi special-purpose risorse ad hoc per la parte di gestione! In questo caso si adotta quello che si chiama “principio di minima intrusione” il quale stabilisce che ogni volta che lavoriamo col supporto, bisogna limitare al massimo l'uso delle risorse per la parte di infrastruttura: così facendo l' overhead introdotto dal sistema di gestione è minimo. Tale principio si può applicare a qualsiasi tipo di supporto e qualunque livello di sistema! <<Quanto overhead siamo disposti a pagare?>> Sicuramente non il 50%! In generale, non possiamo dedicare il 50% delle risorse alla gestione. Per un sistema che non ha replicazione, ma che ha confidenza nella parte di gestione sarà intorno al 1015% con conseguente costo del supporto estremamente limitato! 19 La replicazione, come già detto, può essere in spazio (risorse) ed in tempo (rinvio di richiesta/risposta). Due proposte, lontane (nel tempo) ma significative, sono: 20 Tandem Sistemi degli anni '80, commerciale e special-purpose. Vi è replicazione doppia del tutto: in sostanza abbiamo due bus, due processori e due memorie (stabili) distinte per i processori i quali lavorano (in coppia?!?!?). Questo sistema, proprio per la presenza dei due bus, aveva l'obbiettivo di individuare il guasto: quando uno dei due processori dava un risultato diverso dall'altro, il sistema individuava che c'era un guasto e si fermava, salvando lo stato sulla memoria stabile. Una volta recuperato il guasto ripartiva da ciò che aveva salvato sulla memoria stabile. Il costo del sistema è (quasi) il doppio di uno singolo: pertanto elevato! 21 Modello stand-by a copie fredde: E' un sistema con replicazione in cui vi è una risorsa che sta lavorando (master), e se tale risorsa fallisce, c'è qualcuno che se ne accorge, che quindi ne verifica lo stato, capisce che la risorsa non è più disponibile e a questo punto cerca una risorsa momentaneamente in stand-by (slave) e la colloca al posto di quella caduta, chi fa ciò è un manager di configurazione. La risorsa in stand-by, quindi la copia fredda, non ha uno stato, se non quello iniziale, ed è assolutamente diverso da quello della risorsa attiva: il suo stato quindi, non tiene conto dell'esecuzione precedente della risorsa correntemente attiva. In una applicazione di questo genere è quindi, importante che gli slave si accorgano che il master non è più attivo: dovranno quindi, identificare il guasto e cercare di fare recovery. Questo è un modello molto usato. Reti di Calcolatori LM 37 22 Modello stand-by a copie calde: Un oggetto consiste di almeno due istanze: un’istanza esegue ed è attiva, l’altra è invece passiva e quindi viene aggiornata. Se fallisce la copia attiva, la passiva viene promossa ad attiva. Se fallisce la copia passiva, si usano copie passive di stand-by per fare una nuova copia passiva che ottiene lo stato dell’oggetto attivo (copia calda con stato) <<Qual'è il numero di copie slave introdotte nei sistemi?>> Sicuramente dipende dal numero di guasti, e sarà un numero basso (molto spesso 2) perché ciò limita i costi. 23-24-25 RAID È l’acronimo di Redundant Array of Inexpensive Disk. È un sistema general purpose, utilizzato per reti di dimensioni estese, basato su replicazione di memoria di massa diventata comune, infatti è, in pratica, un insieme di dischi a basso costo e coordinati in azioni comuni per ottenere diversi standard di tolleranza ai guasti. I dischi RAID nascono in principio per lo striping, ossia per velocizzare l’accesso ai file memorizzati su più di un disco e poi, successivamente, vennero estesi a considerare la replicazione. La tecnologia RAID ha un costo limitato e può essere implementata in diversi modi, detti livelli, di cui ve ne sono 5: 38 Stefano Di Monte Livello 0 • • • • Si dedica solamente allo striping Presenta un’elevata velocità con l’ I/O parallelo ma nessuna ridondanza Presenta il peggior MTBF È adatto per applicazioni con I/O intensivo Livello 1 • • • Si basa sul mirroring o specularizzazione dei dischi: presenza di due dischi e tutti i dati scritti sul primo disco vengono copiati direttamente sul secondo, con un’operazione di backup in tempo reale; se un disco si guasta, il secondo contiene un’esatta replica delle informazioni, per cui nulla va perduto. Il mirroring è relativamente poco costoso e può essere implementato via software. Presenta: 1. Massima ridondanza 2. Alta availability 3. Buone performance in lettura, meno buone in scrittura. Livello 3 e 4 Reti di Calcolatori LM 39 Si basano su un insieme di n dischi di cui n-1 disponibili come spazio di memorizzazione utente e l'ultimo utilizzato come disco di parità: i dati sono distribuiti allora, byte per byte, su tutti i drive, scrivendo i dati di parità sul disco dedicato. L'hardware e il software che governano quest'architettura sono in grado di continuare a lavorare anche in caso di un guasto a un disco dell'insieme sfruttando le informazioni residue che, grazie alla parità, permettono di ricostruire per intero ciascun byte. Al momento della sostituzione dell'unità guasta con una funzionante, sarà possibile ripristinare la parità utilizzando le informazioni contenute sui dischi superstiti. Per il ripristino delle informazioni sul disco sostituito basterà riapplicare l'algoritmo di parità (normalmente un "or esclusivo" detta anche parità dispari) indifferentemente ai dati e/o al byte di parità superstiti per ottenere il byte da scrivere. Presenta inoltre, un’alta velocità per blocchi di grandi dimensioni e permette una operazione di I/O alla volta per la contesa sul disco di parità. Livello 5 In un RAID di livello 5, i dati sono distribuiti, un settore alla volta, su tutti i drive dell' array, con i dati di parità inframmezzati in modo da evitare l'uso di un disco separato (la parità viene disseminata usando un algoritmo, detto, di striping). La parità distribuita consente una buona velocità anche per molte letture di piccoli blocchi; sono comunque da preferire, in termini di efficienza, scritture di grossi blocchi. NOTA: Nei RAID, molto spesso, il controllore è unico, se si guasta lui, non si può accedere a nessuna copia! 40 Stefano Di Monte 26 - 27 Più interessante è un discorso di replicazione e gestione delle risorse. 29 Modello a copie attive, introduzione: E' una situazione in cui tutti lavorano, quindi dobbiamo garantire che tutti lavorino correttamente. In generale, la prima cosa che viene in mente è che avendo un'architettura in cui tutte le copie lavorano contemporaneamente, sarà quindi necessario una qualche forma di distribuzione della richiesta su tutte le foglie e di recupero della risposta e successivo trasporto al cliente: tutti devono lavorare e produrre il risultato. Pertanto oltre alla parte di risorse che eseguono, vi è tutta la parte di infrastruttura e di gestione che è molto importante e che è da tener conto. Difatti se quest'ultima dovesse fallire, nessuna risorsa potrebbe raggiungere un'altra risorsa! Quindi un nodo potrebbe occuparsi della distribuzione del risultato, ma anche questo sarebbe sicuramente soggetto a guasti... Sicuramente non è il cliente che deve affibbiarsi la responsabilità della gestione della distribuzione. Un esempio è la Triple Modular Redundancy (TMR): usata per i viaggi spaziali, in cui le risorse erano tutte triplicate (se un errore da una copia e le altre due invece uguali ---> nessun errore, guasto di una sola risorsa). Per i primi viaggi tutto andò bene, poi ci si accorse che le copie erano fortemente dipendenti l'una dall'altra e quindi molto soggette alla creazione di errore congiunto. Affinché la probabilità di errore congiunto fosse molto bassa, tendente a zero, le risorse a copie attive vennero dotate tipicamente di algoritmi diversi in modo da essere fortemente indipendenti l'una dall'altra. 30 Modello a copie passive (master-slave) (master-backup) E' il modello più usato. C'è una copia che esegue ed una serie di altre copie (magari non molte), che sono delle risorse di riserva e che aspettano passivamente: il master (che rappresenta il front-end per le richieste dei diversi clienti) riceve le informazioni, le esegue, e dietro vi sono le copie passive che non eseguono per niente, ma aspettano che il master vada giù a causa di guasto, per sostituirlo e rendere sempre disponibile la risorsa. Reti di Calcolatori LM 41 In questo modello non si lavora a copie fredde, e tipicamente gli slave sono dedicati per lavorare per quella risorsa, quindi è normale che ci sia una operazione di checkpoint, con la quale il master aggiorna lo stato degli slave. Questa operazione è particolarmente importante perché in caso si presenza di guasto, se lo stato dello slave è aggiornato, i tempi di recovery si accorciano. L'operazione di checkpoint è un operazione molto costosa: di solito gli slave non sono vicini al master (per evitare che una situazione di disastro che coinvolge il master interessi anche gli slave) e quindi tale operazione prevede un costo di comunicazione elevato. Tipicamente il funzionamento senza replicazione è il seguente: • il cliente fa una richiesta • il master esegue • il master invia la risposta al cliente Con la replicazione il funzionamento potrebbe essere: • il cliente fa una richiesta • il master esegue • il master invia la risposta al cliente • il master esegue il checkpoint Così facendo si inserisce poco ritardo, il tutto funziona come se non ci fosse replicazione, ma se ci fosse un guasto prima del checkpoint, la risposta appena inviata non sarebbe salvata da alcuna parte: velocità di risposta a discapito della tolleranza ai guasti. Variante nel verso della safety, inversione dei punti 3) e 4): • il cliente fa una richiesta • il master esegue • il master esegue il checkpoint • il master invia la risposta al cliente. Meno veloci, ma più sicuri nel senso della correttezza. Vi sono quindi molte possibilità di utilizzo dei checkpoint: un modo potrebbe essere non aggiornare tutte le copie bensì solo la prima, e poi do la risposta. Difatti in questo modo ci sarà un algoritmo di propagazione dell'aggiornamento dello stato tra le copie che limita i tempi di attesa della risposta al cliente. Si potrebbe pensare che il checkpoint, essendo una comunicazione, possa esser fatto con RMI: scelta sbagliata perché molto pesante, dobbiamo basarci più su qualcosa di basso livello! 32 E' possibile eseguire il checkpoint con azioni periodiche, ossia time driven: dato un certo intervallo, in questo intervallo potrebbero avvenire più di un cambiamento, ma il checkpoint vien fatto una sola volta. Ciò potrebbe comportare situazioni sgradevoli, in cui ad esempio lo stato degli slave sia lontano da quello del master, introducendo quindi una politica meno corretta ma che costerebbe meno che fare checkpoint ogni qual volta avvenga un cambiamento (si pensi ad esempio a sistemi che cambiano continuamente). Ovviamente se non ci sono stati cambiamenti non avverrà nessun checkpoint. In generale, si ragiona più correttamente se si ragiona ad eventi, quindi event driven: ogni volta che 42 Stefano Di Monte c'è un evento che cambia lo stato, viene eseguito il checkpoint. In tal modo, un' oggetto molto sollecitato effettuerà molto spesso il checkpoint: il costo potrebbe essere molto elevato. A volte potrebbe comunque essere idoneo effettuare il salvataggio dello stato sugli slave solo in occasioni particolari e più significativi, come ad esempio sulle eccezioni, o meglio ancora, ragionando a grana grossa, si potrebbe salvare quando inizio a lavorare, quindi, ad esempio, quando sono stato estratto dalla coda delle richieste e posso cominciare ad eseguire. In caso di risorsa sequenziale, lo stato è evidente e facile da identificare e instaurare. In caso di risorsa parallela, le cose si complicano un po' di più, in quanto ci potrebbero essere più risorse che stanno lavorando sullo stesso stato, complicando la gestione del tutto. 33 In un architettura in cui ci sono degli slave, abbiam detto che questi non eseguono, e quindi ciò che fanno e fare del controllo: controllano se il master sia vivo e che continui ad eseguire per dare il risultato a chi ne ha fatto richiesta; devono inoltre accorgersi, nel caso, che il master sia andato giù per un guasto/failure (se lavora con fail-safe o fail-stop), ed essere capaci di rimpiazzarlo per dare una certa continuità nella disponibilità del servizio. Quest'ultima operazione richiede del tempo, e potrebbe comportare determinati problemi: il cliente conosceva il master, ora il master è stato rimpiazzato da uno slave, e sarebbe opportuno che il cliente continui a sapere a chi fare richieste ora. <<Supponendo che ci siano più copie slave , chi è la copia che deve sostituire il master?>> In caso di guasto singolo, se c'è un ordine tra le copie, e se vi è una gerarchia, magari sarà la prima a sostituirlo, o comunque si seguirà la gerarchia. Altrimenti vi saranno dei protocolli per decidere dinamicamente quale sarà la copia che prenderà il posto del master (protocolli di elezioni). <<Come fa il cliente a capire se il master non funziona più?>> I clienti con le richieste in atto potrebbero trovarsi in una situazione di stallo.... 1) Ma se il recovery avviene in tempi brevi, i clienti potrebbero non accorgersi del cambio tra lo slave ed il master (ma di solito i tempi di sostituzione avvengono nell'ordine delle decine di minuti...). 2) Lo slave destinato alla sostituzione del master potrebbe inviare un avviso al/i cliente/i che dice che da questo momento in poi deve rivolgersi a lui per l'erogazione del servizio. 3) Per i clienti che sanno che devono rivolgersi al master (perché scritto nel loro codice), fatta richiesta non riceveranno nessuna risposta....sarebbe quindi opportuno avere un sistema di nomi, cosicché tutti saprebbero a chi rivolgersi. Di conseguenza, i sistemi di nomi sono fondamentali se lavoriamo in dinamico, dove non abbiamo certezza assoluta di ciò che succederà nel futuro. <<Cosa succederebbe se invece il master tornasse su dopo essere stato sostituito?>> 1) Potrebbe diventare uno slave, perturbando poco la situazione creatasi dopo il guasto. Reti di Calcolatori LM 43 2) Essendo stato progettato per essere un master, è comprensibile che potrebbe avere una logica più complessa degli slave, quindi sarebbe più opportuno pagare il costo della perturbazione e rendergli il lavoro che merita e che meglio sa fare. Ciò che ci viene in contro è sempre un buon sistema di nomi! 34 Modello a copie attive In questo modello tutte le copie, tutti server, eseguono. In questi sistemi, quindi, i clienti potrebbero dover avere conoscenza della molteplicità delle cose, quindi del grado di replicazione N della risorsa ed inviare una richiesta a tutte le copie: tale cosa è ASSOLUTAMENTE inaccettabile! 35 Una soluzione potrebbe essere quindi avere un front-end che raccoglie le richieste e le smista alle copie: soluzione molto centralizzata, rappresenta quindi un punto unico di guasto. Tale idea di conseguenza non è molto usata nella realtà, perché intrinsecamente introduce un punto di centralizzazione. (è usata nei sistemi in cui si fanno ipotesi di guasto in cui il front-end non si guasta mai.) Quindi per ogni singola richiesta potrebbe esserci una copia (ad esempio C1 su S1, C2 su S2, e così via...), ed sarà suo compito smistarla verso tutti gli altri: schema migliore nel senso della non centralizzazione, ma che introduce alcuni problemi: se ad esempio S1 diventa gestore della richiesta C1 ed SN diventa gestore della richiesta CN, questi potrebbero entrare in conflitto ed interferire con le operazioni che richiedono, dove con interferire si intende ad esempio che l'operazione di C1 che doveva avvenire prima di CN, viene eseguita dopo, e se entrambe agissero sullo stato, potrebbero provocare situazioni di inconsistenza: per evitare ciò ci vuole sincronizzazione (la quale richiede della comunicazione!). Se le richieste fossero però tutte indipendenti tra loro, si risolverebbe l'ultimo problema in quanto si avrebbe meno sincronizzazione e non vi sarebbe il problema dell'invertibilità delle operazioni, le quali agirebbero pertanto in ordine corretto. 36 Venendo da sistemi concentrati, si potrebbe pensare che il modello giusto sia il modello a perfetta sincronia, ossia un modello in cui l'ordine delle operazioni, tra le copie presenti, avviene in un perfetto ordine prestabilito, ed inoltre, che le operazioni non avvengano tutte contemporaneamente bensì una alla volta per tutte le copie (la prima per tutti gli slave, poi la seconda per tutti gli salve...). Garantire tutto ciò non è facile. Nei sistemi distribuiti non ragioniamo in tal modo: si ragiona a “togliere”, ossia tutto ciò che non vale la pena di fare può non esser fatto per limitarne i costi: ad esempio, se due operazioni sono 44 Stefano Di Monte indipendenti allora sarà bene che non avvengano in ordine perché introdurrebbe dell' overhead non necessario. Nel distribuito bisogna introdurre solo i vincoli che sono necessari al fine di ridurre l' overhead! Si potrebbe avere dell' approssimazione alla sincronia, ossia le copie non sono continuamente tutte nello stesso stato, ma tenderanno a questo in un certo intervallo (o in generale al limite). Queste strategie meno sincrone sono meno costose: -) in realizzabilità del protocollo -) in tempo di risposta per il cliente Un sistema a copie attive è comunque stato molto usato. 37 - 38 - 39 In un modello a copie attive: Se facciamo operazioni di lettura, queste potrebbero avvenire in modo indipendente sulle diverse copie in parallelo. Le operazioni di scrittura sono ovviamente un po' più strette dal punto di vista semantico, in quanto richiedono un maggior coordinamento tra le copie. Ci sono comunque, sempre, delle operazioni poco safety, ovvero delle operazioni di cambiamento di stato: un esempio è l'operazione di lettura di un direttorio Unix mentre questo sta per essere cambiato da qualcun' altro.... Quindi anche nel concentrato si assume che vi sono alcune operazioni che non avvengono in perfetta sincronia, e questo vale a maggior ragione nel distribuito. Ovviamente, anche in un modello a copie attive, si parla di guasto. La copia che si guasta fa parte del gruppo, pertanto, se il grado di replicazione era N ora sarà N-1. É molto importante quindi che il sistema si accorga della copia in meno, cosicché tutti sappiano che le copie disponibili non sono più N bensì N-1. Stesso discorso va fatto quando si è effettuato il recovery della copia guasta e si torna nuovamente ad avere N copie. Tutto ciò deve avvenire mentre il servizio è continuamente attivo, mentre quindi, si sta rispondendo al cliente. Come si può capire, il modello a copia attiva è più complicato del modello a copie passive. Anche in termini di coordinamento. Ad esempio, in presenza di un guasto in una rete di 5 copie, si potrebbe aspettare che il guasto sia riparato e poi inviare la risposta al cliente.....sarebbe più opportuno invece che date le 4 copie ancora attive, siano queste ad inviare la risposta al cliente, si raggiunga quindi un quorum. 40 Quello che deve essere ben presente, in generale, è che il numero di copie attive e di slave, rispettivamente nel modello a copie attive e nel modello a copie passive, deve essere limitato! Bisogna tenere basso il grado di replicazione per tenere basso il grado di complessità dell'intero sistema. 41 Reti di Calcolatori LM 45 Le fasi della risposta al cliente in un modello a copie attive (in realtà funziona anche per un modello master/slave) sono 5, non sono sempre presenti, non sempre nella stesso ordine, ma comunque significative (soprattutto la fase centrale quella di esecuzione, quella in cui tutte le copie eseguono). Fase 1: Nella prima fase,la richiesta viene manifestata all'insieme delle copie: arriva a tutte le copie! Fase 2: In realtà potrebbe arrivare solo ad una sola copia: in questo caso sarebbe necessaria una fase di coordinamento per garantire che la richiesta sia propagata a tutte le copie del sistema e questa rappresenta la seconda fase. Fase 3: tutti eseguono! Fase 4: ora vi è un risultato con conseguente accordo tra i server. Fase 5: Ed infine invio del risultato al cliente. La risposta è una sola, quindi al cliente viene nascosto il grado di replicazione. 42 Fase 1 Fase di arrivo della richiesta: tipicamente arriva ad una sola copia. Quest'ultima copia deve quindi coordinare il tutto e cominciar a lavorare correttamente. 43 Fase 2 Il coordinamento avviene tramite un gestore della richiesta che prende la richiesta stessa e la porta a tutte le altre copie: mandando ad esempio un messaggio contenente la richiesta a tutti server presenti nel sistema. La fase id coordinamento potrebbe essere costituita da un protocollo molto complesso. 44 46 Stefano Di Monte Fase 3 Fase di esecuzione: tutti eseguono, non necessariamente in perfetta sincronia ma si deve eseguire! 45 Fase 4 Fase di coordinamento ulteriore, in cui le copie hanno tutte eseguito con i loro tempi, quindi ora devono coordinarsi sulla risposta, facendo controllo implicito che tutto sta funzionando correttamente e che tutti hanno prodotto lo stesso risultato. Questa fase è molto importante perché, nel caso sia presente, prevede di individuare un guasto (una copia devia rispetto alle altre). 46 Fase 5 Fase in cui si invia un unico risultato al cliente. Questo è uno schema safety: prima di dare la risposta al richiedente del servizio si effettua il controllo di ciò che è stato eseguito, ritardato di conseguenza l'invio al cliente stesso. 48 In un modello a copie passive è molto facile individuare chi è il master, il quale riceve le richieste dei clienti (il che NON prevede nessuna fase di coordinamento iniziale con le copie passive) ed è l'unico che esegue, quindi quando il suo stato cambia, deve fare checkpoint, ossia deve aggiornare lo stato di tutte le copie passive. Quando è stato instaurato il checkpoint, quindi quando tutti hanno ricevuto il cambiamento, il master è disponibile ad inviare la risposta. Questo è uno schema molto centralizzato in cui tutto è deciso dal master, che esegue, aggiorna ed invia la risposta: i protocolli sono più semplici rispetto al modello a copie attive ed i costi più limitati. Reti di Calcolatori LM 47 49 In caso di replicazione di risorse (dati) vi sono due proprietà fondamentali: -) Il ruolo di chi decide gli aggiornamenti: copia primaria o tutte? -) La prontezza di propagazione degli aggiornamenti: possiamo essere più rispettosi della correttezza e ciò prevede di salvare lo stato e poi inviare la risposta, oppure possiamo favorire il cliente dandogli risposte il prima possibile anche a scapito della correttezza. Ovviamente, tali due posizioni permettono di lavorare eager nei confronti di qualcosa e lazy nei confronti dell'altra. In particolare, se favoriamo la correttezza siamo eager nei confronti della propagazione del cambiamento, ma siamo lazy nei confronti del tempo di risposta e viceversa se favoriamo la prontezza nel rispondere. 51 Circa il modello master-slave: Two phase commit Assumiamo di avere uno schema master-slave (in cui quindi non vi è la fase di coordinamento iniziale -fase 2-), in cui la copia primaria riceve le richieste e si occupa delle operazioni da svolgere. Quando in questa, avviene un cambiamento di stato, bisogna che anche le altre copie vengano avvisate di ciò, instaurando lo stato cambiato su quest' altre copie. Se le cose vanno bene allora ciò che avviene è un chekpoint puro e niente più. In realtà potrebbe succedere che in contemporanea, un'altra copia avrebbe potuto aver effettuato altre variazioni, quindi la fase di coordinamento per ottenere uno stato comune potrebbe avere delle problematiche. Per questo viene indicato come two phase commit l'operazione con la quale io chiedo agli altri di fare un cambiamento, ma lascio a quest'ultimi la libertà di negare il cambiamento stesso perché magari ciò renderebbe inconsistente lo stato del sistema. Quindi quando si fa un cambiamento, se c'è il two phase commit, si chiede anche il parere di tutti gli altri nel fare tale cambiamento. Pertanto gli altri (magari non tutti) potrebbero negare la propagazione dell'operazione che voglio eseguire, cosicché sarò costretto ad eseguire un undo dell'operazione, ciò vuol dire disfare l' operazione stessa (o anche di più se ne volevo eseguire altre) non accettate da tutti (o in parte) gli altri. NOTA: nella two phase commit pertanto si garantisce che il gruppo abbia uno stato consistente, altrimenti si effettuerà UNDO! 48 Stefano Di Monte 52 Reconciliation Con la two phase commit pertanto, potremmo incappare in una situazione in cui ogni qual volta che si propone un cambiamento a tutte le altre copie, potrebbe succedere che non tutte tali copie mi rispondano con un OK (si ritenta finché non ritornano tutti pareri positivi!), obbligando il sistema a ritardare continuamente la risposta al cliente (situazione di stallo). Pertanto, ciò che si può decidere di fare è rispondere al cliente prima; in questo modo si crea un contratto con il cliente, e quindi si deve garantire che tutte le copie siano corrette, sarà necessaria una fase simile a quella di two phase commit ma che si chiama fase di riconciliazione delle copie: si garantisce che lo stato delle copie sia lo stesso su tutte le copie. Pertanto quest'ultima operazione potrebbe richiedere un tempo piuttosto elevato, perché se una copia si guasta ovviamente, prima di poterci instaurare uno stato, si deve aspettare che la copia interessata dal guasto sia identificata, venga fatto il recovery, e poi si installi il nuovo stato. La riconciliazione è un operazione tipica, quando si considera che molti sistemi spesso, guidati da mobile, siano sistemi disconnessi su cui lavoriamo quando non siamo in una situazione in cui non siamo in grado di poter valutare lo stato delle altre copie. 53 Circa il modello a copie attive: Two phase commit Le due fasi di coordinamento sono molto importanti perché son viste come le fasi che comportano overhead. Supponendo di avere le copie tutte attive, tipicamente quando un cliente fa una richiesta, la fa su una certa copia e si aspetta che la risposta arrivi da questa stessa copia; questo però non toglie che, in mezzo, sia necessario fare tutto ciò che garantisce che l'esecuzione delle copie producano un buon coordinamento. Supponendo sempre che la propagazione dello stato sia eager (correttezza a scapito del tempismo), Reti di Calcolatori LM 49 il coordinatore di quella richiesta deve coordinarsi con le altre copie mandando un'operazione di stato. A questo punto tali copie eseguono. Dopo l'esecuzione è necessaria la fase di coordinamento, che tipicamente avviene con un two phase commit (fase fondamentale e costosa in termini di coordinamento perché richiede una serie di scambi di messaggi tra tutte le copie) in cui si garantisce che tutte le copie che dovevano eseguire abbiano eseguito e l'abbiano fatto nel modo corretto e si capisce se ci sono copie guaste, quindi fuori dal gruppo, e che dovranno quindi in seguito essere reinserite nel gruppo stesso solamente quando il loro stato sarà uguale allo stato delle copie non cadute (in pratica la two phase commit garantisce la corretta propagazione dell'operazione e la presenza di uno stato consistente tra le copie). Il two phase commit è un protocollo molto pesante ma molto usato. Infine si invierà la risposta (corretta) al cliente. 54 In realtà esiste un'altra possibilità che non ha la fase di coordinamento finale: tutte le copie eseguono e poi, banalmente, il gestore dell'operazione invia direttamente la risposta sicuro che sia la stessa per tutte le copie quindi corretta. L'operazione che consente di fare questo si chiama Atomic Broadcast (o Atomic Multicast -stiam parlando con una definizione di principio-): operazione di coordinamento che garantisce che le richieste inviate dai clienti arrivino a tutte le copie in un certo ugual ordine. Le copie comunque potrebbero eseguire in tempi diversi, con i loro tempi, ma l'ordine di consegna delle operazioni a tutte le copie è lo stesso per tutte le copie. La risposta al cliente quindi può essere inviata dalla copia principale senza attendere le altre copie che invieranno poi a lavoro terminato: se qualche copia si guastasse semplicemente non invierà la risposta al cliente finale, in quanto si ferma, ovvero si comporta in modo fail-stop. Tale protocollo ha un suo costo ma consente di evitare la two phase commit, pertanto non verranno mai eseguite delle undo risparmiando a livello di semantica alcune operazioni che sarebbero difficili da gestire. 50 Stefano Di Monte NOTA: non c'è controllo sulle risposte delle copie al cliente: si suppone che siano corrette. In generale in un sistema in cui abbiamo replicazione abbiamo bisogno di parecchie fasi di coordinamento, tipicamente una iniziale (difficilmente rinunciabile) ed una fase di coordinamento finale (non presente se si lavora con multicast atomic) che garantisce che l'ordine con cui le copie eseguono è sempre lo stesso per tutte le operazioni. 55 Riassumendo: Diverse forme di replicazione: Un caso importante è quello in cui si lavora con copie calde in cui vuol dire avere checkpoint, operazione molto costosa di fatto si preferisce avere delle copie tiepide, ad esempio time driven, e quindi salvare solo in certi intervalli, quindi non frequentemente. Mentre il modello attivo richiede ovviamente e come già ampiamente detto coordinamento. Sicuramente, nella replicazione software c'è SEMPRE da tener presente che bisogna soddisfare il principio della minima intrusione, dato che tutta la parte di coordinamento avviene con le stesso risorse che vengono usate per l'esecuzione e quindi per fornire il servizio. 56 - 57 I cluster sono una soluzione in cui si hanno più processori. High availability sta ad indicare che il servizio potrebbe essere molto più disponibile. In realtà il discorso molto spesso si sposta sull'avere un alto throughput. I cluster, molto spesso, vengono realizzati con un font-end che prende le richieste e smista ai vari processori: quindi se i processori son 4, l'obiettivo è quello di riuscire a smistare un traffico 4 volte rispetto al traffico che si riuscirebbe a smistare con un unico processore. In sostanza, con i cluster si cerca di aumentare le risorse disponibile per l'esecuzione delle operazioni: non ce la facciamo con un unico processore pertanto tendiamo ad avere più processori che coordinano tra loro. Pertanto i cluster che vengono venduti come high availability sono in realtà cluster high throughput! Differentemente i veri cluster high availability sono pertanto quei cluster, in cui le operazioni sono Reti di Calcolatori LM 51 tipicamente eseguite da più di un processore alla volta. Comunque sia, si tratta di buone approssimazioni di sistemi più disponibili. Difatti, l'alta disponibilità è data anche dal fatto che i cluster sono in grado di controllarsi durante l'esecuzione: se un processore si guasta durante l'esecuzione, sono in grado di capire che quel determinato processore non è più disponibile e così smistare il suo traffico sugli altri rimanenti. Tipicamente i cluster lavorano in due forme: a bilanciamento di carico: appena citata e che garantisce che le richieste possano essere smistate in modo automatico sulla macchina più scarica tra quelle disponibili. L'obbiettivo quindi, al fine di tenere alta l'efficienza, è bilanciare tutte le macchine. A copie attive: le operazioni sono svolte da più processori contemporaneamente. Nota1: I cluster sono soluzioni chiavi in mano: all'utente è nascosto tutto sul come lavorano le macchine. Nota2: Se lo schema dei cluster è quello costituito da un front end, quindi a farm centralizzata, avremo un grande problema di scalabilità dovuta alla ricezione unica delle richieste: quando il processore centrale, quello che cioè prende le richieste si congestiona, non potrà prendere ulteriori richieste. 58 Di base, nei cluster, vi sono tre meccanismi fondamentali, necessari per garantire una corretta operatività: (1) monitoraggio: se l'architettura è variabile c'è la necessità di capire cosa succede (magari se vi è un guasto) e quando succede qualcosa, intervenire in maniera opportuna. <<Come si fa a capire se c'è un guasto?>> Tipicamente, si usa una strategia che si chiama (2) heartbeat (battito del cuore). Per capire se una macchina è disponibile, un modo è quello quindi, di inviare un messaggio di bassissimo livello (quindi di bassissimo costo): ad esempio, un battito di cuore, un segnale che chiede all'altro se sia disponibile o meno. Ovviamente nel caso di presenza di guasto, sarà necessario effettuare un (3) failover, ossia tutto il compito della macchina che è fallita, che è quindi interessata dal guasto, viene dato a qualcun'altra macchina. Ciò potrebbe portare ad un cambiamento totale delle strategie sin a quel punto adottate (se le macchine diminuiscono in numero sicuramente la strategia cambierà). 59 Tipicamente, il failover avviene con strategie molto reattive: Supponiamo che una copia stia lavorando su di un certo stato (in figura è il disco). Situazione attiva-passiva: in generale, se un processore lavora ed esegue una certa operazione, nel caso in cui il guasto interessi tale processore, ci potrebbe essere, ora (e non prima), che qualcun' 52 Stefano Di Monte altro carichi l'applicazione corrispondente e cominci a lavorare sullo stato corrente, salvato sul disco in qualche modo (recovery lento). Situazione attiva-attiva: si carica direttamente ed in contemporanea, l'intera applicazione su di un nodo vicino in modo tale che in caso di guasto, ci sarà sicuramente un'applicazione subito pronta a lavorare. Quindi si potrebbe pensare che, dall'inizio, tutti carichino tutte le applicazione con conseguente tempo di recovery molto limitato. 60 L' Heartbeat deve essere un meccanismo di comunicazione molto di basso livello (che quindi produca pochissimo overhead), deve quindi essere molto poco intrusivo e molto poco costoso. 61 - 62 Di cluster ce ne sono di molti tipi, anche commerciali i quali prevedono un certo numero di macchine organizzate in una certa architettura cluster e quindi lavorare con alto throughtput. Ovviamente, un cluster non può avere un numero di macchine partecipanti che vada oltre un certo livello (non può scalare senza limite). In certi casi, potremmo trovarci in una situazione in cui si ha una serie di informazioni che viene messa a disposizione, con caratteristiche diverse, a tutti gli utilizzatori del sistema: si potrebbe avere una rete locale o anche una rete non locale. Storage Area Network (SAN): si può avere a disposizione in rete un'organizzazione che ha i dati strutturati in gerarchia. Organizzazione basata ad esempio su RAID (dischi replicati), o per aumentare la capacità si potrebbe avere un' organizzazione basata su Type o anche una soluzione con dischi ottici. Questa idea di avere a disposizione, sempre più, clienti differenziati, con sistemi operativi Reti di Calcolatori LM 53 differenziati, con rappresentazione dei dati differenziati viene risolta con sistemi di questo genere. 63 Queste organizzazioni, fino a qualche tempo fa, erano disponibili per implementazioni ad alto costo. Queste soluzioni sono soluzioni fortemente basate su architetture ad-hoc, e sempre più disponibili in termini di costi (costi molto limitati). Inoltre, tali organizzazioni sono da considerarsi come componenti off-the-shelf (sono disponibili, già esistenti) di conseguenza i clienti possono utilizzarla per ottenere un miglioramento del tipo di servizio. Si ricordi comunque, che ciò che interessa sempre, è avere soluzioni multi-architetturali, in cui l'eterogeneità è sempre tenuta in conto. 64 – 65 – 66 A livelli di ateneo è disponibile un servizio web services, ossia con programmi disponibili tramite web, il che risulta essere molto richiesto. Questo servizio era più o meno organizzato con: -) una serie di clienti con la necessità di usare questi web services -) un web server, l'interfaccia che rendeva disponibile il servizio stesso (nel caso dell'ateneo è Apache). Questi è un contenitore del servizio. -) Tomcat che rappresenta il contenuto di Apache Se failure, tutto si blocca! Soluzione: due contenitori, quindi bilanciamento di carico sui due web server (in maniera Round Robin -in realtà è un po' più complicato di così-). Due architetture hanno un throughtput più alto rispetto ad una sola architettura, ed inoltre in fase di controllo devono controllarsi reciprocamente in modo tale che, se dovesse capitare un guasto (quindi si sta facendo l'ipotesi di guasto singolo), tali architetture sarebbero capaci di fare failover (attivoattivo). Soluzione di replicazione a basso costo e molto semplice. 54 Stefano Di Monte 67 Questa presente qui e nelle slide successive è una soluzione più complessa e più coordinata: progetto per determinare l'architettura che sta alla base del controllo del traffico aereo a livello europeo (a tale livello, non vi sono degli standard): COFLIGHT. Reti di Calcolatori LM 55