Synchronizácia rubrika: Návrh

2 Juraj Mlich
položil/-a 27.3.2016

Zdravím,

pracujeme na projekte, kde riešime jeden problém a to konkrétne synchronizáciu. Robíme totižto na aplikácií, ktorá funguje aj offline a ktorá sa zosynchronizuje hneď po pripojení k internetu. Zmeny v dátach sú reprezentované sync eventom, ktorý obsahuje konkrétne informácie o zmene dát. Problém ale nastáva v takomto prípade:

User 1 zmení text položky (vygeneruje to sync event), ale je offline.
User 2 následne zmení text položky (vygeneruje to ďalší sync event), ten je ale pripojený, čiže zmena sa hneď prejaví v dátach.
User 1 sa pripojí. Server dostane tento sync event, ale ako bude server vedieť, že ten text položky už bol upravený po tom, ako ho upravil tento user a že má zmenu zahodiť?
(nepočítame so žiadnymi konfliktami, posedná zmena sa vždy aplikuje)

Aké sú spôsoby zariadenia tohoto chovania? Čo doporučujete?

Ďakujem a prajem pekný zvyšok víkendu!

Komentáře

  • harrison314 : Co sa ma stat, ak user 1 (offline) zmeni text prv ako User 2? 29.3.2016
  • Juraj Mlich : prv myslené neskoršie? :) lebo ak je to myslené skoršie, tak je to napísané v otázke... ale ak neskoršie, tak sa zmena samozrejme aplikuje do DB 29.3.2016
  • Honza Břešťan : "Dřív" nebo "později" z pohledu koho, když je User 1 od serveru odpojený? Je to trochu kontraintuitivní, ale tohle není objektivní ani v "analogovém" vesmíru, natož ve virtuálním distribuovaném systému. Tady může jako heuristika posloužit ten "reálný" čas, ale nejde spoléhat na to, že bude přesný. I v rámci jednoho datacentra můžou být stroje rozjeté o minuty, natož nejaký uživatelský stroj. Jediný opravdový bod synchronizace je, když na server dorazí sync event s daty - jedině tam bych rešil, jestli se něco stalo před ním a nebo po něm. Případně nechat uživatele rozhodnout, co má být novější - nikdo nemá rád manuální merge, ale lidská kontrola správnosti výsledných dat není k zahození. 29.3.2016
  • harrison314 : Prv bolo myslene "skoršie", a v tomto pripade to bude dalej generovat problemi, na cas sa spoliehat neda, najme nie offline. Dalsia vec, je konzitencia dát, pretoze pri automatickom mergovani, jednotlivych stlpcov je mozne dojst k nekonzistenym datam, preto sa castejsie pouziva uzamkanie na urovni riadkov alebo logickej entity (moze byt tvorena aj viacerimi tabulkami previazanymi). 29.3.2016
odkaz
9 Honza Břešťan
odpověděl/-a 27.3.2016
 
upravil/-a 29.3.2016

Tohle se dá nejsnáz řešit třeba CAS tokenem (Compare-and-Swap), který si každý client přečte spolu s daty a taky ho spolu s updatem pošle - server si pak určí, jestli se mu token libí a podle toho vyhodnotí výsledek syncu.

TL/DR: Doporučená literatura je Leslie Lamport - Time, Clocks and the Ordering of Events in a Distributed System.

Trochu ukecaně rozvedené:

V momentě, kdy si User 1 přečte data, dostane k nim i jejich verzi, onen CAS token. Může to byt jednoduchý inkrementujicí čítač, ale pak je potřeba zařídit, aby inkrementace byla atomická spolu s úpravou dat a prováděl ji ten, kdo má (zdroj "pravdy", autoritativní zdroj dat, zpravidla server, nebo přesneji storage, ale může to být taky čiste distribuovaná věc). Pro náš příklad dostane User 1 od serveru CAS token s hodnotou 13. Poté přejde do offline módu, ale token si pamatuje, protože ho bude potřebovat při sync eventu.

User 2 si taky přečte data a protože se mezitím verze nezměnila, dostane s nimi taky CAS token 13. Provede úpravu, spolu s tokenem ji pošle na server a ten si řekne "token odpovidá, tak já zmením data a inkrementuju CAS token na 14". Od té doby už bude přijímat jen data s tokenem 14 (nebo vyšším, záleží na přesném návrhu toho systému a významu toho tokenu).

User 1 změní data a někdy potom přejde do online módu a pošle sync event se svým CAS tokenem 13. Server se podívá na CAS token, zjistí, že je menší než očekávaná hodnota 14, a sync event zamítne. Pokud s konflikty nepočítáte a má se aplikovat jen poslední změna, tak stačí ten starý event na serveru ignorovat a sync je vyřešený.
V jiném systému může treba upozornit Usera 1 a nabídnout mu řešení konfliktu, nebo se může sám pokusit o nejaký merge (to používají třeba Conflict-free Replicated Data Types, kde při mergi nemůže dojít ke konfliktu).

Inkrementálni CAS token v tomhle případě slouží jako virtuální hodiny, které centrálně spravuje server. Na realné hodiny v tomhle případě ze spousty důvodů nelze spoléhat, i když to často láká.

Tenhle přístup se hodí pro víc případu než jen řešení podobných synchronizací. Je to časté řešení pro optimistic concurrency obecně. Dokumentové a key/value databáze to často umí přímo jako atomickou operaci nad jedním dokumentem (my to tak pouzivame třeba v Couchbase). I třeba SQL Server ma rowversion datový typ, který se při změně dat inkrementuje sám. Ten se posledni dobou doporučuje mít u všech řádků, kde se často řeší concurrent updaty. Používání rowversion se sice lockům úplně nevyhne, ale dokáže být mnohem vic lightweight než libovolný transaction level, pokud by měl updatující celou dobu být v transakci. Na druhou stranu je u podobných systémů větší prostor pro chybu a ztrátu konzistence dat, takže je potřeba si hlídat požadavky i implementaci - hranice mezi správným a chybným řešením je pak mnohem mlhavější.

Komentáře

  • Juraj Mlich : CAS token môže byť fajn riešenie, ale obávam sa, že nepôjde použiť. Ono ten user 1 môže zmeniť nielen text, ale pokojne aj nejakú ďalšiu položku, kde by tento sync event zahodený nebol. Poprípade by mohol len zmeniť inú vlastnosť toho objektu, v ktorom zmenil ten text. Dalo by sa to nejako aplikovať aj s takouto požiadavkou? Ďakujem za dlhú odpoveď :) 28.3.2016
  • harrison314 : Pouzit CAS len ne tie polozky, ktore treba. 28.3.2016
  • Honza Břešťan : Da se to rozumne pouzit jenom v pripadech, kdy je stejna granularita zmen a tokenu. V tomhle pripade by to znamenalo bud mit zvlast verzovani kazde polozky, coz zni silene (ale muze to byt presne to, co chces), nebo povolit zmeny jen celeho objektu, coz zase vylouci tenhle pripad (ale muze to byt bliz tomu, co uzivatel ceka - treba ze jeden v adrese nezmeni mesto a druhy PSC na jine mesto). 28.3.2016
  • Juraj Mlich : Verzovanie každej jednej položky je zrejme presne to, čo potrebujeme. Ako by si to riešil po technickej stránke? :) 28.3.2016
  • Juraj Mlich : No len ono CAS bude potreba na strašne veľa položiek, rádovo v 100kách :) 28.3.2016
  • harrison314 : To mas aku velku tabulku (aj pocet slpcov aj pocet riadkov) ? 28.3.2016
  • Juraj Mlich : Počet riadkov je relatívny... Tých tabuliek je viacero, je to komplexná aplikácia. Napríklad len tabuľka entry má 30 stĺpcov :) 28.3.2016

Pro zobrazení všech 3 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.