Conflitti
Nei database distribuiti, le copie dei dati possono essere memorizzate in più di una posizione. Le caratteristiche naturali della rete e del sistema possono significare che le modifiche apportate a un documento memorizzato in una posizione documento memorizzato in una posizione non possono essere aggiornate o replicate istantaneamente in altre parti del database.
In altre parole, aggiornamenti indipendenti possono essere effettuati su copie diverse di documenti. L'effetto di questi aggiornamenti potrebbe essere quello di introdurre disaccordi o "conflitti" su quale sia il contenuto corretto e definitivo del documento.
IBM® Cloudant® for IBM Cloud® cerca di aiutarti ad evitare i conflitti avvertendoti di potenziali problemi. Ti avvisa restituendo una risposta di tipo “ 409 ” a una richiesta di aggiornamento problematica. Tuttavia, potrebbe non essere ricevuta una risposta " 409 " se l'aggiornamento del database viene richiesto su un sistema che al momento non è connesso alla rete. Ad esempio,
il database potrebbe trovarsi su un dispositivo mobile temporaneamente scollegato da Internet, il che rende impossibile verificare se siano stati effettuati altri aggiornamenti potenzialmente in conflitto .
Se si richiede un documento che si trova in una situazione di conflitto, IBM Cloudant restituisce il documento come previsto. Tuttavia, un algoritmo interno considera una serie di fattori prima di determinare quale versione del documento restituire. Non si deve dare per scontato che il documento restituito sia la versione più recente.
Ad esempio, se non si controllano i conflitti, o non li si affronta, il database {{site.data.keyword.cloudant_short_notm} il database {{site.data.keyword.cloudant_short_notm}} può presentare i seguenti comportamenti:
- Aumento delle incoerenze nel contenuto dei documenti, perché si verifica un numero maggiore di documenti in conflitto tra loro.
- Aumento delle dimensioni del database, poiché tutti i documenti in conflitto devono essere conservati fino alla risoluzione del conflitto.
- Prestazioni in calo perché IBM Cloudant deve lavorare di più in risposta a ogni richiesta, nel tentativo di identificare la versione “migliore possibile” di un documento oggetto di conflitto.
Le seguenti procedure consigliate potrebbero aiutarti a decidere quando controllare e risolvere i conflitti:
| Caratteristica dell'applicazione | Frequenza di aggiornamento del documento | Controllo dei conflitti durante il recupero | Controllo dei conflitti durante l'aggiornamento |
|---|---|---|---|
| Sempre connesso alla rete, ad esempio un server. | Spesso | Y |
|
| Sempre connesso alla rete. | Occasionalmente |
|
Y |
| Spesso, ma non sempre, connesso alla rete, ad esempio un portatile. | Spesso |
|
Y |
| Spesso ma non sempre connesso alla rete. | Occasionalmente |
|
Y |
| Dispositivo connesso alla rete solo occasionalmente, ad esempio un tablet. | Spesso |
|
Y |
Ricerca di conflitti
Per individuare eventuali conflitti che potrebbero influire su un documento, aggiungi il parametro di query conflicts=true quando recuperi un documento. Una volta restituito, il documento risultante contiene un array di tipo _conflicts,
che include un elenco di tutte le revisioni in conflitto.
Vedere il seguente esempio di funzione mappa per trovare i conflitti tra documenti:
function (doc) {
if (doc._conflicts) {
emit(null, [doc._rev].concat(doc._conflicts));
}
}
Per trovare conflitti per più documenti in un database, scrivi una vista. Utilizzando una funzione di mappa come nell'esempio fornito, puoi trovare tutte le revisioni per ogni documento con un conflitto.
Quando hai tale vista, puoi usarla per trovare e risolvere i conflitti secondo necessità. In alternativa, puoi eseguire una query nella vista dopo ogni replica per identificare e risolvere immediatamente i conflitti.
Come risolvere i conflitti
Una volta individuato un conflitto, è possibile risolverlo seguendo le quattro fasi descritte di seguito.
- Get
- Unisci
- Carica
- Elimina
Si veda il seguente esempio di documento della prima versione:
{
"_id": "74b2be56045bed0c8c9d24b939000dbe",
"_rev": "1-7438df87b632b312c53a08361a7c3299",
"name": "Samsung Galaxy S4",
"description": "",
"price": 650
}
Consideriamo uno scenario per questo esempio. Supponi di avere un database di prodotti per un negozio online. La prima versione di un documento potrebbe essere simile all'esempio fornito.
Si veda la seguente seconda versione (prima revisione) del documento che aggiunge una descrizione:
{
"_id": "74b2be56045bed0c8c9d24b939000dbe",
"_rev": "2-61ae00e029d4f5edd2981841243ded13",
"name": "Samsung Galaxy S4",
"description": "Latest smartphone from Samsung",
"price": 650
}
Il documento non ha ancora una descrizione, pertanto qualcuno potrebbe aggiungerne una.
Si veda la seguente seconda versione alternativa, che introduce una modifica relativa alla riduzione dei prezzi rispetto alla prima versione del documento:
{
"_id": "74b2be56045bed0c8c9d24b939000dbe",
"_rev": "2-f796915a291b37254f6df8f6f3389121",
"name": "Samsung Galaxy S4",
"description": "",
"price": 600
}
Allo stesso tempo, qualcun altro, che lavora con un database replicato, abbassa il prezzo. Questa modifica viene apportata alla prima versione del documento. Pertanto, la modifica relativa alla riduzione di prezzo non "tiene conto" della modifica alla descrizione.
Successivamente, quando i due database vengono replicati, potrebbe non essere chiaro quale delle due versioni alternative del documento sia corretta. Questo esempio rappresenta uno scenario di conflitto.
Ottieni le revisioni in conflitto
Per trovare eventuali revisioni in conflitto per un documento recupera tale documento come al solito, ma includi il parametro conflicts=true come nel seguente esempio:
https://ACCOUNT.cloudant.com/products/$_ID?conflicts=true
Si veda il seguente esempio di risposta al recupero di un documento che mostra revisioni contrastanti:
{
"_id":"74b2be56045bed0c8c9d24b939000dbe",
"_rev":"2-f796915a291b37254f6df8f6f3389121",
"name":"Samsung Galaxy S4",
"description":"",
"price":600,
"_conflicts":["2-61ae00e029d4f5edd2981841243ded13"]
}
Se il documento presenta dei conflitti, potresti ottenere una risposta simile all'esempio fornito, che si basa sul problema della descrizione modificata o del prezzo modificato.
La versione con il prezzo modificato è stata scelta arbitrariamente come versione più recente del documento. Non dare per scontato che la versione del documento aggiornata più di recente sia quella più recente ai fini della risoluzione dei conflitti.
In questo esempio, si consideri un conflitto tra il documento recuperato, il cui valore di " _rev " è 2-f796915a291b37254f6df8f6f3389121, e un altro documento, il cui valore di " _rev "
è 2-61ae00e029d4f5edd2981841243ded13. I dettagli del documento in conflitto sono indicati nell'array _conflicts.
Spesso, si può scoprire che l'array ha un solo elemento, ma è possibile che ci siano molte revisioni in conflitto. Ogni revisione è elencata nell'array.
Unisci le modifiche
La tua applicazione deve identificare tutte le potenziali modifiche e riconciliarle, unendo in modo efficace gli aggiornamenti corretti e validi per produrre una versione singola e non in conflitto del documento.
Per confrontare le revisioni e individuare le modifiche apportate, l'applicazione deve recuperare tutte le versioni dal database. Si inizia recuperando un documento e i dettagli di eventuali versioni in conflitto. Per avviare il recupero,
utilizzare un comando simile al seguente, che richiede anche l'array _conflicts:
https://$ACCOUNT.cloudant.com/products/$_ID?conflicts=true
Questo recupero fornisce una versione aggiornata del documento che si sta archiviando,
nonché un elenco di tutti gli altri documenti in conflitto che devono essere recuperati a loro volta, ad esempio ...rev=2-61ae00e029d4f5edd2981841243ded13 e ...rev=1-7438df87b632b312c53a08361a7c3299. Ognuna
di queste altre versioni in conflitto viene anche recuperata e memorizzata, ad esempio:
https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-61ae00e029d4f5edd2981841243ded13
https://$ACCOUNT.cloudant.com/products/$_ID?rev=1-7438df87b632b312c53a08361a7c3299
Una volta che tutte le revisioni in conflitto di un documento sono disponibili, è possibile risolvere i conflitti.
In uno scenario precedente, le differenze tra le versioni del documento riguardavano campi diversi all'interno del documento stesso, rendendone più agevole l'unione.
È probabile che i conflitti più complicati richiedano di conseguenza più analisi. Per aiutare, si può scegliere tra varie strategie di risoluzione dei conflitti, come ad esempio:
- In base al tempo: utilizza un semplice criterio che tiene conto della prima modifica o di quella più recente.
- Valutazione da parte degli utenti: i conflitti vengono segnalati agli utenti, che decidono poi quale sia la soluzione migliore.
- Sofisticati algoritmi di fusione, spesso utilizzati con i sistemi di controllo delle versioni. Un esempio è l'unione a tre fasi.
Per un esempio pratico di come implementare queste modifiche, vedi questo progetto con il codice di esempio.
Carica la nuova revisione
Vedere le seguenti revisioni finali dopo aver risolto e unito le modifiche delle precedenti revisioni in conflitto:
{
"_id": "74b2be56045bed0c8c9d24b939000dbe",
"_rev": "3-daaecd7213301a1ad5493186d6916755",
"name": "Samsung Galaxy S4",
"description": "Latest smartphone from Samsung",
"price": 600
}
Dopo aver valutato e risolto i conflitti, creare un documento che includa i dati attuali e quelli definitivi. Questo nuovo documento viene caricato nel database.
Elimina le vecchie revisioni
Vedere le seguenti richieste di esempio per eliminare le vecchie revisioni:
DELETE https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-61ae00e029d4f5edd2981841243ded13
DELETE https://$ACCOUNT.cloudant.com/products/$_ID?rev=2-f796915a291b37254f6df8f6f3389121
Nella fase finale, si eliminano le vecchie revisioni. Per eliminare le vecchie revisioni si invia una richiesta DELETE, specificando le revisioni da eliminare.
Quando le versioni precedenti di un documento vengono eliminate, i conflitti associati a quel documento vengono contrassegnati come risolti. È possibile verificare che non vi siano conflitti richiedendo nuovamente il documento. Impostare il
parametro conflicts su true e usare
trovare i conflitti come prima.