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