Ugrás a tartalomhoz

Konfliktusmentes replikált adattípus

Ellenőrzött
A Wikipédiából, a szabad enciklopédiából
(CRDT szócikkből átirányítva)

A konfliktusmentes replikált adattípus (CRDT) az elosztott számítástechnikában egy olyan adatszerkezet, amely egy hálózat több számítógépén replikálódik, és a következők jellemzik:[1][2][3][4][5][6][7][8]

  • az alkalmazás bármelyik replikát önállóan, egyidejűleg és a többi replikával való egyeztetés nélkül frissítheti;
  • egy algoritmus (amely maga is az adattípus része) automatikusan feloldja az esetlegesen előforduló ellentmondásokat;
  • bár a replikák állapota egy adott időpontban eltérő lehet, garantáltan egy közös állapothoz konvergálnak.

A CRDT koncepciót hivatalosan 2011-ben definiálta Marc Shapiro, Nuno Preguiça, Carlos Baquero és Marek Zawirski[9]. A fejlesztést kezdetben a kollaboratív szövegszerkesztés és a mobil számítástechnika motiválta. CRDT-ket használnak az online chatrendszerekben, az online szerencsejátékokban és a SoundCloud hangterjesztő platformon is. A Redis, a Riak és a Cosmos DB NoSQL elosztott adatbázisok is rendelkeznek CRDT adattípusokkal.

Háttér

[szerkesztés]

Ugyanazon adatok több replikájának egyidejű frissítése a replikákat tároló számítógépek közötti koordináció nélkül a replikák közötti ellentmondásokat eredményezhetnek, amelyek általános esetben nem feltétlenül oldhatók fel. A frissítések közötti konfliktusok esetén a konzisztencia és az adatintegritás helyreállítása megkövetelheti a frissítések egy részének vagy egészének teljes vagy részleges visszavonását.

Ennek megfelelően az elosztott számítástechnika nagy része arra a problémára összpontosít, hogy hogyan lehet megakadályozni a replikált adatok egyidejű frissítését.

Egy másik lehetséges megközelítés azonban az optimista replikáció, ahol az összes egyidejű frissítést átengedik, esetleg ellentmondások keletkeznek, és az eredményeket később összevonják vagy „feloldják”. Ebben a megközelítésben a replikák közötti konzisztencia végül az eltérő replikák „összevonásával” áll helyre. Míg az optimista replikáció általános esetben nem feltétlenül működik, az adatszerkezeteknek van egy jelentős és gyakorlatban hasznos osztálya, a CRDT-k, ahol ez jól működik: mindig lehetséges az adatszerkezet különböző replikáinak egyidejű frissítéseit konfliktusok nélkül összevonni vagy feloldani. Ez ideálissá teszi a CRDT-ket az optimista replikációhoz.

Példaként egy egyirányú Boolean eseményjelző (event flag) egy triviális CRDT: egy bit, igaz vagy hamis értékkel. Az igaz azt jelenti, hogy egy adott esemény legalább egyszer bekövetkezett. A hamis azt jelenti, hogy az esemény nem következett be. Ha egyszer igazra állítottuk, a jelző nem állítható vissza hamisra (egy már bekövetkezett eseményt nem lehet meg nem történtté tenni). A feloldási módszer a „true wins” (az Igaz nyer): amikor egy olyan replikát egyesítünk, ahol a jelző igaz (az adott replika megfigyelte az eseményt), és egy másikat, ahol a jelző hamis (az adott replika nem figyelte meg az eseményt), a feloldás eredménye igaz: az eseményt megfigyeltük.

A CRDT-k típusai

[szerkesztés]

A CRDT-knek két megközelítése van, mindkettő erős konzisztenciát biztosíthat: az állapotalapú CRDT-k[10][11] és a műveletalapú CRDT-k.[12][13]

Állapotalapú CRDT-k

[szerkesztés]

Az állapotalapú CRDT-ket (más néven konvergens replikált adattípusok, vagy CvRDT-k) két eljárás határozza meg: a helyi állapotokhoz és egy az állapotokon végzett műveletekhez tartozik; valamint három függvénnyel (állapotváltozás): egy függvény egy kezdeti állapot előállítására, egy állapotok egyesítésére szolgáló függvény, és egy függvény egy állapot frissítésére szolgáló művelet alkalmazására. Az állapotalapú CRDT-k minden frissítéskor egyszerűen elküldik a teljes helyi állapotukat a többi replikának, ahol a kapott új állapotokat beolvasztják a helyi állapotba.

A végső konvergencia biztosítása érdekében a függvényeknek a következő tulajdonságoknak kell megfelelniük: Az egyesítési függvénynek ki kell számítania az egyesülést a replikák bármelyik állapotpárjára, és egy félrácsot kell alkotnia, amelynek semleges eleme a kezdeti állapot. Ez különösen azt jelenti, hogy az egyesítő függvénynek kommutatívnak, asszociatívnak és idempotensnek kell lennie. A kommutativitás, asszociativitás és idempotencia mögött az az intuíció áll, hogy ezek a tulajdonságok arra szolgálnak, hogy a CRDT változatlan legyen a csomagok átrendeződése és duplikációja esetén. Továbbá, a frissítési függvénynek monotonnak kell lennie az említett félrács által meghatározott részleges sorrend tekintetében.

A delta állapotú CRDT-k[11][14] (vagy egyszerűen csak delta CRDT-k) olyan optimalizált állapotalapú CRDT-k, amelyekben a teljes állapot helyett csak a közelmúltban alkalmazott állapotváltozásokat terjesztik.

Műveletalapú CRDT-k

[szerkesztés]

A műveletalapú CRDT-k (más néven kommutatív replikált adattípusok, vagy CmRDT-k) egyesítési függvény nélkül definiálhatók. Az állapotok továbbítása helyett a frissítési műveletek kerülnek közvetlenül a replikákhoz továbbításra és alkalmazásra. Például egy egyetlen egész szám művelet alapú CRDT-je a (+10) vagy (-20) műveleteket továbbíthatja. A műveletek alkalmazásának továbbra is kommutatívnak és asszociatívnak kell lennie. Ahelyett azonban, hogy megkövetelnénk, hogy a műveletek alkalmazása idempotens legyen, a kommunikációs infrastruktúrával szemben erősebbek az elvárások: minden műveletet duplikáció nélkül és keletkezési sorrendben kell eljuttatni a többi replikához.

A tisztán műveletalapú CRDT-k[13] a műveletalapú CRDT-k egy olyan változata, amely csökkenti a metaadatok méretét.

Összehasonlítás

[szerkesztés]

A két alternatíva elméletileg egyenértékű, mivel mindkettő képes emulálni a másikat.[1] A gyakorlatban azonban vannak különbségek. Az állapotalapú CRDT-ket gyakran egyszerűbb megtervezni és megvalósítani; egyetlen követelményük a kommunikációs hordozóval szemben valamilyen pletyka protokoll. Hátrányuk, hogy minden CRDT teljes állapotát végül minden más replikának továbbítani kell, ami költséges lehet. Ezzel szemben a műveletalapú CRDT-k csak a frissítési műveleteket továbbítják, amelyek jellemzően kis méretűek. A művelet-alapú CRDT-k azonban garanciákat igényelnek a kommunikációs middleware-től; hogy a műveletek nem esnek ki vagy duplikálódnak a többi replikának való továbbításkor, és hogy azok ok-okozati sorrendben kerülnek átadásra.[1]

Bár a műveletalapú CRDT-k több követelményt támasztanak a replikák közötti műveletek továbbításának protokolljával szemben, kevesebb sávszélességet használnak, mint az állapotalapú CRDT-k, ha a tranzakciók száma a belső állapot méretéhez képest kicsi. Mivel azonban az állapotalapú CRDT egyesítési függvény asszociatív, az egyesítés valamely replika állapotával az adott replika összes korábbi frissítésének eredményét adja. A pletyka protokollok jól működnek az állapotalapú CRDT állapot más replikák felé történő továbbítására, miközben csökkentik a hálózathasználatot és kezelik a topológiaváltozásokat.

Az állapotalapú CRDT-k tárolási komplexitására vonatkozóan ismert néhány alsó korlát[15].

Ismert CRDT-k

[szerkesztés]

G-Számláló (G-Counter, Grow-only Counter)

[szerkesztés]
payload integer[n] P
    initial [0,0,...,0]
update increment()
    let g = myId()
    P[g] := P[g] + 1
query value() : integer v
    let v = Σi P[i]
compare (X, Y) : boolean b
    let b = (∀i  [0, n - 1] : X.P[i]  Y.P[i])
merge (X, Y) : payload Z
    let ∀i  [0, n - 1] : Z.P[i] = max(X.P[i], Y.P[i])

Ez az állapotalapú CRDT egy n csomópontból álló csoport számlálóját valósítja meg. A csoport minden egyes csomópontjához egy 0 és n – 1 közötti azonosítót rendelünk, amelyet a myId() hívásával kapunk meg. Így minden csomópontnak saját slotja van a P tömbben, amely helyileg növekszik. A frissítések a háttérben terjednek, és a P minden elemének max() értékét figyelembe véve egyesülnek. A compare függvényt az állapotok részleges sorrendjének szemléltetésére használjuk. Az egyesítő függvény kommutatív, asszociatív és idempotens. A frissítő függvény monoton módon növeli a belső állapotot az összehasonlító függvénynek megfelelően. Ez tehát egy helyesen definiált állapotalapú CRDT, és erős végső konzisztenciát biztosít. A műveleteken alapuló CRDT növelő műveleteket küld, amikor azok keletkeznek[2].

PN-Számláló (Positive-Negative Counter)

[szerkesztés]
payload integer[n] P, integer[n] N
    initial [0,0,...,0], [0,0,...,0]
update increment()
    let g = myId()
    P[g] := P[g] + 1
update decrement()
    let g = myId()
    N[g] := N[g] + 1
query value() : integer v
    let v = Σi P[i] - Σi N[i]
compare (X, Y) : boolean b
    let b = (∀i  [0, n - 1] : X.P[i]  Y.P[i]  ∀i  [0, n - 1] : X.N[i]  Y.N[i])
merge (X, Y) : payload Z
    let ∀i  [0, n - 1] : Z.P[i] = max(X.P[i], Y.P[i])
    let ∀i  [0, n - 1] : Z.N[i] = max(X.N[i], Y.N[i])

A CRDT-fejlesztés során gyakori stratégia több CRDT kombinálása, hogy egy összetettebb CRDT-t hozzanak létre. Ebben az esetben két G-számlálót kombinálunk, hogy létrehozzunk egy olyan adattípust, amely mind a növelő, mind a csökkentő műveleteket támogatja. A „P” G-számláló növekményeket számol, az „N” G-számláló pedig csökkenéseket. A PN-számláló értéke a P-számláló értéke mínusz az N-számláló értéke. Az egyesítés ugyanúgy történik, ahogy két P G-számláló egyesítése, és hasonlóan az N számlálók esetében. Figyeljük meg, hogy a CRDT belső állapotának monoton módon kell növekednie, még akkor is, ha a lekérdezésben visszaadott állapota visszatérhet a korábbi értékekhez[2].

G-Halmaz (Grow-only Set)

[szerkesztés]
payload set A
    initial 
update add(element e)
    A := A  {e}
query lookup(element e) : boolean b
    let b = (e  A)
compare (S, T) : boolean b
    let b = (S.A  T.A)
merge (S, T) : payload U
    let U.A = S.A  T.A

A G-készlet (grow-only set) egy olyan halmaz, amely csak hozzáadásokat engedélyez. Egy egyszer hozzáadott elemet nem lehet eltávolítani. Két G-halmaz egyesülése az uniójuk[2].

2P-Halmaz (Two-Phase Set)

[szerkesztés]
payload set A, set R
    initial , 
query lookup(element e) : boolean b
    let b = (e  A  e  R)
update add(element e)
    A := A  {e}
update remove(element e)
    pre lookup(e)
    R := R  {e}
compare (S, T) : boolean b
    let b = (S.A  T.A  S.R  T.R)
merge (S, T) : payload U
    let U.A = S.A  T.A
    let U.R = S.R  T.R

Két G-halmazt (csak növekvő készlet) kombinálunk a 2P-halmaz létrehozásához. Egy eltávolító halmaz (az úgynevezett „sírkő” (tombstone) halmaz) hozzáadásával elemek adhatók hozzá és el is távolíthatók. Ha egy elemet egyszer eltávolítottunk, nem lehet újra hozzáadni; vagyis ha egy e elem egyszer bekerült a sírkőhalmazba, a lekérdezés soha többé nem ad vissza Igaz értéket erre az elemre. A 2P-halmaz „remove-wins” (az eltávolítás nyer) szemantikát használ, tehát a remove(e) elsőbbséget élvez az add(e) előtt.[2]

LWW-Elemhalmaz (Last-Write-Wins-Element-Set)

[szerkesztés]

Az LWW-Elemhalmaz hasonlít a 2P-készlethez abban, hogy egy „hozzáadási készletből” és egy „eltávolítási készletből” áll, és minden elemhez tartozik egy időbélyegző. Az elemek hozzáadása az LWW-Elemhalmaz úgy történik, hogy az elemet beillesztjük az add set-be, egy időbélyegzővel együtt. Az elemek eltávolítása az LWW-Elemhalmazból az eltávolítási készletbe való felvétellel történik, szintén időbélyeggel. Egy elem akkor tagja az LWW-Elemhalmaznak, ha szerepel az add-halmazban, és vagy nem szerepel a remove-halmazban, vagy szerepel a remove-halmazban, de korábbi időbélyeggel, mint az add-halmazban lévő legutolsó időbélyeg. Az LWW-Elemhalmaz két másolatának egyesítése az add halmazok és az remove halmazok egyesítéséből áll. Ha az időbélyegek megegyeznek, az LWW- Elemkészlet " elfogultsága" lép működésbe. Az LWW-Elemhalmaz lehet a hozzáadások vagy az eltávolítások irányába elfogult. Az LWW-Elemhalmaz előnye a 2P-készlettel szemben az, hogy a 2P-készlettel ellentétben az LWW-Elemhalmaz lehetővé teszi, hogy egy elemet eltávolítás után újra be lehessen illeszteni[2].

OR-Halmaz (Observed-Remove Set)

[szerkesztés]

Az OR-Set hasonlít az LWW-Elemhalmazhoz, de időbélyegek helyett egyedi címkéket használ. A halmaz minden egyes eleméhez egy listát vezetünk az add-címkékről és egy listát a remove-címkékről. Egy elemet úgy illesztünk be az OR-Set-be, hogy egy új egyedi címkét generálunk és hozzáadjuk az adott elem add-tag listájához. Az elemek eltávolítása az OR-halmazból úgy történik, hogy az elem add-tag listájában szereplő összes tag hozzáadódik az elem remove-tag (tombstone) listájához. Két OR-halmaz egyesítéséhez minden elem add-tag listája legyen a két add-tag lista egyesítése, és ugyanígy a két remove-tag lista is. Egy elem akkor és csak akkor tagja a halmaznak, ha az add-tag-lista mínusz a remove-tag-lista nem üres.[2] Lehetséges egy olyan optimalizálás, amely kiküszöböli a tombstone-halmaz fenntartásának szükségességét; ezzel elkerülhető a tombstone-halmaz potenciálisan korlátlan növekedése. Az optimalizálás úgy érhető el, hogy minden egyes replikához egy időbélyegző vektort tartunk fenn[16].

Szekvenciális CRDT-k

[szerkesztés]

Egy szekvencia, lista vagy rendezett halmaz CRDT használható egy együttműködő valós idejű szövegszerkesztő felépítésére, az operatív transzformáció (OT) alternatívájaként.

Néhány ismert szekvencia CRDT a Treedoc[5], RGA[17], Woot[4], Logoot[18], és az LSEQ[19]. A CRATE[20] egy decentralizált valós idejű szerkesztő, amely az LSEQSplit (az LSEQ kiterjesztése) alapjaira épül, és a WebRTC segítségével böngészők hálózatán futtatható. A LogootSplit[21] a Logoot kiterjesztéseként a szekvencia CRDT-k metaadatainak csökkentése érdekében született javaslat. A MUTE[22][23] a LogootSplit algoritmusra támaszkodó online webalapú peer-to-peer valós idejű kollaboratív szerkesztő.

Az ipari szekvencia CRDT-k, beleértve a nyílt forráskódúakat is, az optimalizálásoknak és a reálisabb tesztelési módszertannak köszönhetően közismerten felülmúlják az akadémiai implementációkat[24] A legfőbb népszerű példa az Yjs CRDT, amely úttörő volt a fa helyett plainlistát használó (ala Kleppmann automerge)[24].

Alkalmazásuk

[szerkesztés]
  • Zed egy nyílt forráskódú, kollaboratív IDE, amelyet a zed-industries épített, és amely CRDT-ket használ a „pufferekben” a konfliktusok kezelésére, amikor közös szerkesztést végeznek ugyanazon a fájlon.
  • A Fluid Framework a Microsoft által épített nyílt forráskódú kollaboratív platform, amely mind szerverreferencia implementációkat, mind kliensoldali SDK-kat biztosít a CRDT-ket használó modern, valós idejű webes alkalmazások létrehozásához.
  • A Nimbus Note egy kollaboratív jegyzetelő alkalmazás, amely az Yjs CRDT-t használja a kollaboratív szerkesztéshez.[25]
  • A Redis egy elosztott, nagy rendelkezésre állású és skálázható, memórián belüli adatbázis, amely rendelkezik „CRDT-kompatibilis adatbázis” funkcióval.[26]
  • SoundCloud nyílt forráskódú Roshi, egy LWW-elemkészletű CRDT a SoundCloud streamhez, amelyet a Redis tetején valósítottak meg.[27]
  • A Riak egy elosztott NoSQL kulcs-érték adattároló, amely CRDT-ken alapul.[28] League of Legends' a Riak CRDT implementációját használja a játékon belüli chat rendszeréhez, amely 7,5 millió egyidejű felhasználót és 11 000 üzenetet kezel másodpercenként.[29]
  • A Bet365 több száz megabájtnyi adatot tárol az OR-Set Riak implementációjában.[30]
  • A TomTom CRDT-ket használ a navigációs adatok szinkronizálására a felhasználó készülékei között.[31]
  • A Phoenix, egy Elixir nyelven írt webes keretrendszer az 1.2.[32] verzióban CRDT-ket használ a valós idejű, több csomópontból álló információmegosztás támogatására.
  • A Facebook a CRDT-ket az Apollo alacsony késleltetésű „konzisztencia méretarányos” adatbázisában valósítja meg.[33]
  • A Facebook CRDT-ket használ a FlightTracker rendszerében a Facebook gráf belső kezelésére.[34]
  • A Atom Teletype a CRDT-ket alkalmazza, hogy a fejlesztők megoszthassák a munkaterületüket a csapattagokkal, és valós időben dolgozhassanak együtt a kódon.[35]
  • A Haja Networks OrbitDB-je műveletalapú CRDT-ket használ az alapvető adatszerkezetében, az IPFS-Logban.[36]
  • Apple a CRDT-ket a Notes alkalmazásban valósítja meg az offline szerkesztések több eszköz közötti szinkronizálására.[37]
  • A Swim egy platform elosztott valós idejű streaming alkalmazások futtatására, amelyek folyamatos intelligenciát biztosítanak. Olyan streaming szereplőket használ, amelyek tisztán op-alapú CRDT állapotfrissítéseket streamelnek más szereplőkhöz egy DAG-ban, amely egy streaming adatcsatornát valósít meg.
  • RxDB egy kliensoldali NoSQL adatbázis elosztott valós idejű streaming alkalmazásokhoz. Van egy CRDT plugin, amely lehetővé teszi egy dokumentum frissítését NoSQL alapú CRDT delták tárolásával és ezek replikálásával más kliensekkel vagy egy backend szerverrel.
  • A PGD egy PostgreSQL alapú, több mesterrel rendelkező replikációs megoldás. Támogatja a CRDT oszloptípusokat.

Lásd még

[szerkesztés]

Jegyzetek

[szerkesztés]
  1. a b c Conflict-Free Replicated Data Types, Stabilization, Safety, and Security of Distributed Systems, Lecture Notes in Computer Science. Grenoble, France: Springer Berlin Heidelberg, 386–400. o.. DOI: 10.1007/978-3-642-24550-3_29 (2011). ISBN 978-3-642-24549-7 
  2. a b c d e f g (2011. január 13.) „A Comprehensive Study of Convergent and Commutative Replicated Data Types”. Rr-7506. 
  3. Shapiro, Marc; Preguiça, Nuno (2007). "Designing a Commutative Replicated Data Type". arXiv:0710.1784 [cs.DC].
  4. a b Proceedings of the 2006 20th anniversary conference on Computer supported cooperative work - CSCW '06, 259. o.. DOI: 10.1145/1180875.1180916 (2006). ISBN 978-1595932495 
  5. a b (2009) „CRDTs: Consistency without Concurrency Control”. Computing Research Repository. 
  6. Preguiça, Nuno; Marques, Joan Manuel & Shapiro, Marc et al. (June 2009), "A Commutative Replicated Data Type for Cooperative Editing", Proc 29th IEEE International Conference on Distributed Computing Systems, Montreal, Quebec, Canada: IEEE Computer Society, pp. 395–403, ISBN 978-0-7695-3659-0, doi:10.1109/ICDCS.2009.20
  7. Baquero, Carlos & Moura, Francisco (1997), Specification of Convergent Abstract Data Types for Autonomous Mobile Computing, Universidade do Minho
  8. Schneider, Fred (1990. december 1.). „Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial”. ACM Computing Surveys 22 (4), 299–319. o. DOI:10.1145/98163.98167. 
  9. Conflict-free Replicated Data Types. inria.fr, 2011. július 19.
  10. (1999. október 1.) „Using Structural Characteristics for Autonomous Operation”. SIGOPS Oper. Syst. Rev. 33 (4), 90–96. o. DOI:10.1145/334598.334614. 
  11. a b Efficient State-Based CRDTS by Delta-Mutation, Networked Systems, Lecture Notes in Computer Science (angol nyelven). Springer International Publishing, 62–76. o.. DOI: 10.1007/978-3-319-26850-7_5 (2015. május 13.). ISBN 9783319268491 
  12. (2010. április 1.) „Consistency without Concurrency Control in Large, Dynamic Systems”. SIGOPS Oper. Syst. Rev. 44 (2), 29–34. o. DOI:10.1145/1773912.1773921. 
  13. a b Making Operation-Based CRDTS Operation-Based, Distributed Applications and Interoperable Systems, Lecture Notes in Computer Science (angol nyelven). Springer Berlin Heidelberg, 126–140. o.. DOI: 10.1007/978-3-662-43352-2_11 (2014. június 3.). ISBN 9783662433515 
  14. (2016. március 4.) „Delta State Replicated Data Types”. Journal of Parallel and Distributed Computing 111, 162–173. o. DOI:10.1016/j.jpdc.2017.08.003. 
  15. Replicated Data Types: Specification, Verification, Optimality, Proceedings of the 41st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, 271–284. o.. DOI: 10.1145/2535838.2535848 (2014. január 23.). ISBN 9781450325448 
  16. Bieniusa, Annette; Zawirski, Marek; Preguiça, Nuno; Shapiro, Marc; Baquero, Carlos; Balegas, Valter; Duarte, Sérgio (2012). "An optimized conflict-free replicated set". arXiv:1210.3368 [cs.DC].
  17. (2011) „Replicated Abstract Data Types: Building Blocks for Collaborative Applications”. Journal of Parallel and Distributed Computing 71 (2), 354–368. o. DOI:10.1016/j.jpdc.2010.12.006. 
  18. (2010) „Logoot-Undo: Distributed Collaborative Editing System on P2P Networks”. IEEE Transactions on Parallel and Distributed Systems 21 (8), 1162–1174. o. DOI:10.1109/TPDS.2009.173. ISSN 1045-9219. 
  19. LSEQ: An adaptive structure for sequences in distributed collaborative editing, Proceedings of the 2013 ACM symposium on Document engineering, 37–46. o.. DOI: 10.1145/2494266.2494278 (2013). ISBN 9781450317894 
  20. CRATE: Writing Stories Together with our Browsers, Proceedings of the 25th International Conference Companion on World Wide Web, 231. o.. DOI: 10.1145/2872518.2890539 (2016) 
  21. Supporting Adaptable Granularity of Changes for Massive-scale Collaborative Editing, Proceedings of the International Conference on Collaborative Computing: Networking, Applications and Worksharing – CollaborateCom 2013, 50–59. o.. DOI: 10.4108/icst.collaboratecom.2013.254123 (2013). ISBN 978-1-936968-92-3 
  22. MUTE. Coast Team, 2016. március 24.
  23. MUTE: A Peer-to-Peer Web-based Real-time Collaborative Editor, Proceedings of ECSCW Panels, Demos and Posters 2017. DOI: 10.18420/ecscw2017_p5 (2017) 
  24. yjs/yjs: Shared data types for building collaborative software (angol nyelven). GitHub
  25. About CRDTs. (Hozzáférés: 2020. június 18.)
  26. Diving into CRDTs. Redis , 2022. március 17. (Hozzáférés: 2024. május 22.)
  27. Roshi: a CRDT system for timestamped events. SoundCloud, 2014. május 9.
  28. Introducing Riak 2.0: Data Types, Strong Consistency, Full-Text Search, and Much More. Basho Technologies, Inc., 2013. október 29.
  29. How League of Legends Scaled Chat to 70 Million Players - It Takes Lots of Minions. High Scalability , 2014. október 13.
  30. bet365: Why bet365 chose Riak. Basho
  31. Practical Demystification of CRDTs
  32. What makes Phoenix Presence Special, 2016. március 25.
  33. Facebook Announces Apollo at QCon NY 2014
  34. FlightTracker: Consistency across Read-Optimized Online Stores at Facebook. research.facebook.com. (Hozzáférés: 2022. december 8.)
  35. Code together in real time with Teletype for Atom. Atom.io, 2017. november 15.
  36. OrbitDB/ipfs-log on Github. GitHub . (Hozzáférés: 2018. szeptember 7.)
  37. IOS Objective-C fejlécek a futásidejű introspection alapján: NST/IOS-Runtime-Headers. GitHub , 2019. július 25.

Fordítás

[szerkesztés]
  • Ez a szócikk részben vagy egészben a CRDT című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.