2010-01-19 12 views
40

Nel mondo di oggi in cui molti computer, dispositivi mobili o servizi Web condividono dati o agiscono come hub, la sincronizzazione diventa più importante. Come tutti sappiamo, le soluzioni che la sincronizzazione non sono le più comode ed è meglio non sincronizzarle affatto.Qual è l'approccio più intelligente e facile per sincronizzare i dati tra più entità?

Sono ancora curioso di sapere come implementare una soluzione di sincronizzazione per la sincronizzazione tra più entità. Esistono già molti approcci diversi, come confrontare un campo data modificato o un hash e utilizzare i dati più recenti o lasciare che l'utente scelga ciò che vuole utilizzare in caso di conflitto. Un altro approccio è quello di provare ad unire automaticamente i dati in conflitto (che a mio avviso non è così intelligente, perché una macchina non può indovinare cosa volesse dire l'utente).

In ogni caso, qui ci sono un paio di domande relative alla sincronizzazione che dobbiamo rispondere prima di iniziare a implementare la sincronizzazione:

  • Quali sono i dati più recenti? Come voglio rappresentarlo?
  • Cosa faccio in caso di conflitto? Unire? Chiedo e chiedo all'utente cosa deve fare?
  • Cosa faccio quando arrivo in uno stato incoerente (ad esempio una disconnessione dovuta a una connessione di rete mobile di tipo "flakey")?
  • Cosa devo fare quando non voglio entrare in uno stato incoerente?
  • Come si ripristina una sincronizzazione corrente interrotta?
  • Come gestisco l'archiviazione dei dati (ad esempio database MySQL su un servizio Web, dati di base su un iPhone e come faccio a unire/sincronizzare i dati senza un sacco di codice di colla)?
  • Come devo gestire le modifiche da parte dell'utente che si verificano durante la sincronizzazione (che viene eseguita in background, quindi l'interfaccia utente non è bloccata)?
  • Come e in quale direzione propagare le modifiche (ad esempio, un utente crea una voce "Foo" sul suo computer e non si sincronizza, quindi è in movimento e crea un'altra voce "Foo", cosa succede quando prova a sincronizzare entrambi i dispositivi)? L'utente avrà due voci "Foo" con ID univoci diversi? L'utente avrà solo una voce, ma quale?
  • Come devo gestire la sincronizzazione quando ho dati gerarchici? Dall'alto al basso? Dal basso verso l'alto? Tratto ogni voce atomicamente o guardo solo un supernodo? Quanto è grande il trade-off tra semplificare le cose e investire troppo tempo nell'implementazione?
  • ...

Ci sono un sacco di altre domande e spero che ho potuto ispirare abbastanza. La sincronizzazione è un problema abbastanza generale. Una volta trovato un buon e versatile approccio di sincronizzazione, dovrebbe essere più semplice applicarlo a un'applicazione concreta, piuttosto che iniziare a pensare da zero. Mi rendo conto che esistono già molte applicazioni che tentano di risolvere (o risolvere con successo) la sincronizzazione, ma sono già abbastanza specifiche e non forniscono risposte sufficienti agli approcci di sincronizzazione in generale.

risposta

44

Dove lavoro abbiamo sviluppato una versione "offline" della nostra applicazione principale (web) per consentire agli utenti di lavorare sui loro laptop in luoghi in cui non dispongono di accesso a Internet (non sono sicuro di quanti questi posti in realtà esistono in questi giorni, ma mi è stato detto che lo fanno;)). Quando l'utente torna al sito principale, deve sincronizzare i dati inseriti offline con la nostra applicazione principale.

Quindi, per rispondere alle vostre domande:

  • Quali sono i dati più recenti? Come voglio rappresentarlo?

Abbiamo una colonna LAST_UPDATED_DATE su ogni tavolo. Il server tiene traccia di quando le sincronizzazioni hanno luogo, quindi quando l'applicazione offline richiede una sincronizzazione il server dice "hey, dammi solo i dati modificati da questa data".

  • Cosa devo fare in caso di conflitto? Unire? Chiedo e chiedo allo all'utente cosa deve fare?

Nel nostro caso l'applicazione non in linea è in grado di aggiornare un relativamente piccolo sottoinsieme di tutti i dati solo. Poiché ogni record è sincronizzato, controlliamo se si tratta di uno di questi casi e, in tal caso, confrontiamo il LAST_UPDATED_DATE per il record sia online che offline. Se le date sono diverse, controlliamo anche i valori (perché non è un conflitto se sono entrambi aggiornati allo stesso valore). Se c'è un conflitto registriamo la differenza, impostiamo un flag per dire che c'è almeno un conflitto e continuiamo a controllare il resto dei dettagli. Una volta che il processo è finito, se il flag "isConflict" è impostato, l'utente può andare in una pagina speciale che mostra le differenze e decidere quali dati sono la versione "corretta". Questa versione viene quindi salvata sull'host e il flag "isConflict" viene ripristinato.

  • Che cosa devo fare quando io non voglio entrare in un incoerente Stato?
  • Come si ripristina una sincronizzazione corrente interrotta?

Beh, cerchiamo di evitare di entrare in uno stato incoerente, in primo luogo.Se una sincronizzazione viene interrotta per qualsiasi motivo, l'ultimo_sincronizzazione_data non viene aggiornata e quindi la prossima volta che viene avviata una sincronizzazione inizierà dalla stessa data della data di inizio della sincronizzazione precedente (interfusa).

  • Come posso gestire la memorizzazione dei dati (ad esempio database MySQL su un servizio web, Core dati su un iPhone, e come faccio a fusione/sincronizzare i dati senza un sacco di codice di colla)?

Usiamo database standard su entrambe le applicazioni, e gli oggetti Java in mezzo. Gli oggetti vengono serializzati in XML (e compressi con gzip per accelerare il trasferimento) per il processo di sincronizzazione effettivo, quindi decompresso/deserializzato a ciascuna estremità.

  • Come devo gestire le modifiche da parte dell'utente che si verificano durante la sincronizzazione (che viene eseguito in background, in modo da l'interfaccia utente non sia bloccata)?

Queste modifiche potrebbero avere luogo dopo la data di inizio di sincronizzazione, e quindi non sarebbero raccolti sull'altro lato fino alla prossima sincronizzazione.

  • Come e in quale direzione faccio a propagare le modifiche (ad esempio, un utente crea una voce “Foo” sul suo computer e non si sincronizza, poi si è in viaggio e crea un altro “Pippo” entrata: cosa succede quando si tenta di sincronizzare entrambi i dispositivi )? L'utente ha due voci "Foo" con ID univoci diversi? L'utente ha solo una voce, ma quale?

Questo sta a voi decidere come si desidera gestire questo particolare Foo ... vale a dire a seconda di ciò che la chiave primaria di Foo è e come si determina se uno Foo è uguale a un'altra.

  • Come devo gestire la sincronizzazione quando ho dati gerarchici? Dall'alto al basso? Bottom-up? Tratto ogni voce atomicamente o guardo solo un supernodo ?

La sincronizzazione è atomico, quindi se un record fallisce, allora l'intero processo viene contrassegnato come incompleto, simile ad un sovvertimento commit transazione.

  • Quanto è grande il trade-off tra semplificare eccessivamente le cose e investendo troppo tempo nella realizzazione?

io non sono sicuro di quello che vuoi dire, ma direi che tutto dipende dalla vostra situazione e il tipo/quantità di dati che si desidera sincronizzare. Potrebbe volerci molto tempo per progettare e implementare il processo, ma è possibile.

Spero che ti aiuti o almeno ti dia qualche idea! :)

+0

Si prega di aiutare a introdurre alcuni algoritmi di sincronizzazione, grazie! – Charles0429

+0

Sì, si prega di condividere qualsiasi algoritmo per facilitare questo. –

+0

Penso che No1 dovrebbe essere al contrario, il client dovrebbe determinare i candidati per la sincronizzazione e non il server. ad esempio sul mio dispositivo LAST_UPDATED_DATE sono le 2:00 pm, quindi ho apportato modifiche alle 14:10 mentre offline, ma un mio collega ha aggiornato lo stesso record @ 2:30 pm e si è salvato, LAST_UPDATED_DATE sul server è ora alle 2:30 del pomeriggio, vorrei perdere le modifiche apportate alle 14:10 se il server deve determinare i candidati alla sincronizzazione. –

4

Probabilmente "Non è un vero problema", qui non è una vera risposta:

Penso che i sistemi di controllo di versione distribuito (come Mercurial o Git) ho capito una grande parte di questo. Tuttavia, richiedono che le persone accettino che può esserci più di una versione "più recente" e che a volte gli aggiornamenti in conflitto richiedono una risoluzione manuale da risolvere. Inoltre, se non sei interessato a mantenere l'intera cronologia dei cambiamenti, c'è un po 'di overhead in questi sistemi (ma ovviamente la storia recente è necessaria per trovare antenati comuni per determinare il modo in cui le due versioni si riferiscono).

Ma concordo con te sul fatto che in un mondo in cui tutti i dati sono distribuiti su più dispositivi e servizi, la necessità di tenere traccia e distribuire automaticamente gli aggiornamenti diventerà così urgente che i formati di file comuni utilizzati dalle applicazioni includeranno abbastanza meta-dati per facilitare un qualche tipo di comportamento di fusione intelligente. Ma questo comportamento dovrà probabilmente accadere a livello di applicazione, perché non esiste un modo generico per risolvere aggiornamenti in conflitto.

Nel frattempo, l'approccio iTunes-iPod è il più semplice: hai solo una biblioteca principale e ogni dispositivo tira da lì. Ovviamente, single-master-sync non è molto soddisfacente in tutti gli scenari (specialmente quando è coinvolto più di un utente), ma comunque lo apprezzerei se più applicazioni offrissero l'opzione di lavorare in questo modo (pet peeve: I have three Macs , con tre installazioni iPhoto. Se si sincronizzano automaticamente da un master dedicato, proprio come le foto si sincronizzano con il mio iPod, sarebbe un miglioramento).

0

Grazie per la risposta dettagliata GaZ. Ho un paio di domande di follow-up:

Se si utilizzano indicatori di data e ora come si gestiscono impostazioni di tempo imprecise (piccole differenze, ad esempio 1-5 secondi)? Quanto spesso appaiono? Non è un controllo delle versioni (come SVN lo fa) migliore per gestire diversi cambiamenti di dati?

Capisco che si recuperino solo i dati tra due timestamp, l'ultimo_sincronizzazione_data (per client) e ora?

Cosa fai quando un utente non risolve i conflitti? Non sincronizzi i dati contrassegnati con il flag isConflict o aggiungi un altro conflitto, in modo che l'utente possa scegliere tra più di due versioni di un'entità quando decide di risolvere tutti i conflitti? O non si sincronizza affatto se vi sono dati contrassegnati come in conflitto?

+0

Le date utilizzate sono tutte sul server, quindi finché l'orologio non cambia sul server non ci saranno differenze. Non sai cosa intendi per il controllo delle versioni, scusa? Se un utente non risolve un conflitto, i dati per quella particolare entità non vengono nuovamente sincronizzati. Altre entità possono comunque sincronizzarsi. – GaZ

+0

Con versioning intendo solo un valore intero come proprietà per ogni oggetto. Due valori incrementali, uno per la versione corrente e uno per l'ultima versione sincronizzata, vengono confrontati durante una sincronizzazione e in base alle differenze nei numeri di versione che si propagano alle modifiche o contrassegnano i dati come in conflitto. –

Problemi correlati