Bezkonfliktowy zreplikowany typ danych

W przetwarzaniu rozproszonym bezkonfliktowy replikowany typ danych ( CRDT ) to struktura danych , która jest replikowana na wielu komputerach w sieci , z następującymi cechami:

  1. Aplikacja może aktualizować dowolną replikę niezależnie, równolegle i bez koordynacji z innymi replikami.
  2. Algorytm (sam będący częścią typu danych) automatycznie rozwiązuje wszelkie niespójności, które mogą wystąpić.
  3. Chociaż repliki mogą mieć różne stany w dowolnym momencie, gwarantowana jest ich zbieżność.

Koncepcja CRDT została formalnie zdefiniowana w 2011 roku przez Marca Shapiro, Nuno Preguiçę, Carlosa Baquero i Marka Zawirskiego. Rozwój był początkowo motywowany wspólną edycją tekstu i komputerami przenośnymi . CRDT były również używane w czatów online , grach hazardowych online oraz na platformie dystrybucji dźwięku SoundCloud . Rozproszone bazy danych NoSQL Redis , Riak i Cosmos DB mają typy danych CRDT.

Tło

Równoczesne aktualizacje wielu replik tych samych danych, bez koordynacji między komputerami hostującymi repliki, mogą powodować niespójności między replikami, które w ogólnym przypadku mogą być nie do rozwiązania. Przywracanie spójności i integralności danych w przypadku konfliktów między aktualizacjami może wymagać całkowitego lub częściowego usunięcia niektórych lub wszystkich aktualizacji.

W związku z tym duża część przetwarzania rozproszonego koncentruje się na problemie zapobiegania równoczesnym aktualizacjom replikowanych danych. Ale innym możliwym podejściem jest replikacja optymistyczna , w której wszystkie współbieżne aktualizacje mogą przejść, z możliwymi niespójnościami, a wyniki są później łączone lub „rozwiązywane”. W tym podejściu spójność między replikami jest ostatecznie przywracana poprzez „łączenie” różnych replik. Podczas gdy optymistyczna replikacja może nie działać w ogólnym przypadku, istnieje znacząca i praktycznie użyteczna klasa struktur danych, CRDT, w których działa — w przypadku których zawsze możliwe jest scalanie lub rozwiązywanie równoczesnych aktualizacji różnych replik struktury danych bez konfliktów . To sprawia, że ​​CRDT są idealne do replikacji optymistycznej.

Na przykład jednokierunkowa flaga zdarzenia boolowskiego to trywialna CRDT: jeden bit, z wartością prawda lub fałsz. Prawda oznacza, że ​​jakieś określone zdarzenie miało miejsce co najmniej raz. False oznacza, że ​​zdarzenie nie miało miejsca. Po ustawieniu flagi na wartość true flaga nie może zostać ponownie ustawiona na wartość false (wydarzenie, które wystąpiło, nie może zostać anulowane). Metodą rozstrzygania jest „prawda wygrywa”: podczas łączenia repliki, w której flaga jest prawdziwa (ta replika zaobserwowała zdarzenie) i innej, w której flaga jest fałszywa (ta replika nie zaobserwowała zdarzenia), rozstrzygnięty wynik to true — zdarzenie zostało zaobserwowane.

Rodzaje CRDT

Istnieją dwa podejścia do CRDT, z których oba mogą zapewnić silną ostateczną spójność : CRDT oparte na operacjach i CRDT oparte na stanie.

Te dwie alternatywy są teoretycznie równoważne, ponieważ każda z nich może naśladować drugą. Istnieją jednak praktyczne różnice. Państwowe CRDT są często prostsze do zaprojektowania i wdrożenia; ich jedynym wymaganiem od podłoża komunikacyjnego jest jakiś rodzaj protokołu plotkarskiego . Ich wadą jest to, że cały stan każdego CRDT musi być przesłany ostatecznie do każdej innej repliki, co może być kosztowne. Natomiast CRDT oparte na operacjach przesyłają tylko operacje aktualizacji, które zazwyczaj są niewielkie. Jednak CRDT oparte na operacjach wymagają gwarancji ze strony oprogramowania pośredniczącego komunikacji ; że operacje nie są odrzucane ani powielane podczas przesyłania do innych replik oraz że są one dostarczane w kolejności przyczynowej.

CRDT oparte na operacjach

CRDT oparte na operacjach są również nazywane przemiennymi replikowanymi typami danych lub CmRDT . Repliki CmRDT propagują stan, przesyłając tylko operację aktualizacji. Na przykład CmRDT pojedynczej liczby całkowitej może rozgłaszać operacje (+10) lub (-20). Repliki odbierają aktualizacje i stosują je lokalnie. Operacje są przemienne . Jednak niekoniecznie są one idempotentne . Infrastruktura komunikacyjna musi zatem gwarantować, że wszystkie operacje na replice są dostarczane do innych replik bez powielania, ale w dowolnej kolejności.

wyłącznie na operacjach to odmiana CRDT opartych na operacjach, która zmniejsza rozmiar metadanych.

Państwowe CRDT

CRDT oparte na stanie są nazywane zbieżnymi replikowanymi typami danych lub CvRDT . W przeciwieństwie do CmRDT, CvRDT wysyłają swój pełny stan lokalny do innych replik, gdzie stany są łączone przez funkcję, która musi być przemienna , asocjacyjna i idempotentna . Funkcja scalania zapewnia łączenie dla dowolnej pary stanów repliki, więc zbiór wszystkich stanów tworzy półsieć . Funkcja aktualizacji musi monotonicznie zwiększać stan wewnętrzny, zgodnie z tymi samymi regułami porządku częściowego , co półsieć.

stanu Delta (lub po prostu Delta CRDT) to zoptymalizowane CRDT oparte na stanie, w których rozpowszechniane są tylko ostatnio zastosowane zmiany w stanie zamiast całego stanu.

Porównanie

Chociaż CmRDT nakładają większe wymagania na protokół przesyłania operacji między replikami, zużywają mniej pasma niż CvRDT, gdy liczba transakcji jest niewielka w porównaniu z rozmiarem stanu wewnętrznego. Ponieważ jednak funkcja scalania CvRDT jest asocjacyjna, scalanie ze stanem pewnej repliki daje wszystkie poprzednie aktualizacje tej repliki. Protokoły Gossip dobrze sprawdzają się przy propagowaniu stanu CvRDT do innych replik, jednocześnie zmniejszając wykorzystanie sieci i obsługując zmiany topologii.

Znane są pewne dolne granice złożoności przechowywania CRDT opartych na stanie.

Znane CRDT

G-Counter (licznik tylko do wzrostu)

 ładunek integer[n] P początkowy [0,0,...,0]  przyrost aktualizacji   () niech g =  myId  () P[g] := P[g] + 1  wartość zapytania   () : liczba całkowita v niech v = Σ  i  P[i] porównaj (X, Y) : boolean b niech b = (∀i ∈ [0, n - 1] : XP[i] ≤ YP[i]) połącz (X, Y) : ładunek Z niech ∀i ∈ [0, n - 1] : ZP[i] =  max  (XP[i], YP[i]) 

Ten CvRDT implementuje licznik dla klastra n węzłów. Każdemu węzłowi w klastrze przypisany jest identyfikator od 0 do n - 1, który jest pobierany za pomocą wywołania metody myId (). W ten sposób każdemu węzłowi przypisuje się własne miejsce w tablicy P , którą lokalnie zwiększa. Aktualizacje są propagowane w tle i łączone przez pobranie max () każdego elementu w P . Funkcja porównania jest dołączona, aby zilustrować częściowy porządek w stanach. Funkcja scalania jest przemienna, asocjacyjna i idempotentna. Funkcja aktualizacji monotonicznie zwiększa stan wewnętrzny zgodnie z funkcją porównania. Jest to zatem poprawnie zdefiniowany CvRDT i zapewni silną ostateczną spójność. Odpowiednik CmRDT rozgłasza operacje przyrostowe w miarę ich odbierania.

Licznik PN (licznik dodatnio-ujemny)

 payload integer[n] P, integer[n] N początkowe [0,0,...,0], [0,0,...,0]  przyrost aktualizacji   () niech g =  myId  () P[g] := P[g] + 1  zmniejszenie aktualizacji   () niech g =  myId  () N[g] := N[g] + 1  wartość zapytania   () : liczba całkowita v niech v = Σ  i  P[i] - Σ  i  N [i] porównaj (X, Y) : logiczny b niech b = (∀i ∈ [0, n - 1] : XP[i] ≤ YP[i] ∧ ∀i ∈ [0, n - 1] : XN[ i] ≤ YN[i]) scalanie (X, Y) : ładunek Z niech ∀i ∈ [0, n - 1] : ZP[i] = max (  XP  [i], YP[i]) niech ∀i ∈ [0, n - 1] : ZN[i] =  maks.  (XN[i], YN[i]) 

Powszechną strategią rozwoju CRDT jest łączenie wielu CRDT w celu stworzenia bardziej złożonego CRDT. W tym przypadku dwa liczniki G są łączone w celu utworzenia typu danych obsługującego zarówno operacje zwiększania, jak i zmniejszania. Licznik G „P” zlicza przyrosty; a licznik G „N” zlicza ubytki. Wartość licznika PN to wartość licznika P minus wartość licznika N. Scalanie jest obsługiwane przez pozwolenie połączonemu licznikowi P na połączenie dwóch liczników P G i podobnie dla liczników N. Należy zauważyć, że stan wewnętrzny CRDT musi rosnąć monotonicznie, nawet jeśli jego stan zewnętrzny ujawniony przez zapytanie może powrócić do poprzednich wartości.

G-Set (zestaw tylko do wzrostu)

 zestaw ładunku A początkowy ∅ aktualizacja  dodaj  (element e) A := A ∪ {e} wyszukiwanie zapytania  (  element e) : boolowskie b niech b = (e ∈ A) porównaj (S, T) : boolowskie b niech b = (SA ⊆ TA) scalanie (S, T) : ładunek U niech UA = SA ∪ TA 

G-Set (zestaw tylko do uprawy) to zestaw, który pozwala tylko na addy. Raz dodanego elementu nie można usunąć. Połączenie dwóch G-Zestawów jest ich związkiem.

Zestaw 2P (zestaw dwufazowy)

  zestaw ładunku A, zestaw R początkowy ∅, ∅  wyszukiwanie zapytania   (element e) : boolean b niech b = (e ∈ A ∧ e ∉ R) aktualizacja  dodaj  (element e) A := A ∪ {e} aktualizacja  usuń  (element e )  wyszukiwanie  wstępne  (e) R := R ∪ {e} porównaj (S, T) : boolean b niech b = (SA ⊆ TA ∧ SR ⊆ TR) połącz (S, T) : ładunek U niech UA = SA ∪ TA niech UR = SR ∪ TR 

Dwa zestawy G (zestawy tylko do wzrostu) są łączone w celu utworzenia zestawu 2P. Po dodaniu zestawu do usuwania (nazywanego zestawem „nagrobków”) elementy można dodawać, a także usuwać. Raz usuniętego elementu nie można ponownie dodać; to znaczy, gdy element e znajdzie się w zbiorze reliktów, zapytanie nigdy więcej nie zwróci wartości True dla tego elementu. Zestaw 2P wykorzystuje semantykę „usuń-zwycięża”, więc usuń ( e ) ma pierwszeństwo przed dodaniem ( e ).

LWW-Element-Set (Ostatni-Write-Wins-Element-Set)

LWW-Element-Set jest podobny do 2-P-Set, ponieważ składa się z zestawu „dodaj” i „zestawu usuń” ze znacznikiem czasu dla każdego elementu. Elementy są dodawane do LWW-Element-Set poprzez wstawienie elementu do zestawu dodawania ze znacznikiem czasu. Elementy są usuwane z LWW-Element-Set poprzez dodanie do zestawu usuwania, ponownie ze znacznikiem czasu. Element jest członkiem LWW-Element-Set, jeśli znajduje się w zestawie dodawania, a nie w zestawie do usuwania lub w zestawie do usuwania, ale z wcześniejszym znacznikiem czasu niż ostatni znacznik czasu w zestawie dodawania. Łączenie dwóch replik LWW-Element-Set polega na połączeniu zestawów dodawania i zestawieniu zestawów usuwanych. Gdy znaczniki czasu są równe, w grę wchodzi „odchylenie” zestawu elementów LWW. Zestaw elementów LWW może być ukierunkowany na dodawanie lub usuwanie. Zaletą LWW-Element-Set w porównaniu z 2P-Set jest to, że w przeciwieństwie do 2P-Set, LWW-Element-Set umożliwia ponowne włożenie elementu po jego wyjęciu.

OR-Set (zestaw zaobserwowany-usuń)

OR-Set przypomina LWW-Element-Set, ale używa unikalnych tagów zamiast znaczników czasu. Dla każdego elementu w zestawie utrzymywana jest lista tagów dodawania i lista tagów usuwania. Element jest wstawiany do zestawu LUB poprzez wygenerowanie nowego unikalnego znacznika i dodanie go do listy dodanych znaczników dla elementu. Elementy są usuwane z LUB-Zestawu poprzez dodanie wszystkich tagów z listy add-tag elementu do listy usuwania tagów (tombstone) elementu. Aby scalić dwa zestawy OR, dla każdego elementu niech jego lista dodawania znaczników będzie sumą dwóch list dodawania znaczników i podobnie dla dwóch list usuwania znaczników. Element jest członkiem zbioru wtedy i tylko wtedy, gdy lista dodanych znaczników pomniejszona o listę usuniętych znaczników nie jest pusta. Możliwa jest optymalizacja eliminująca konieczność utrzymywania zestawu nagrobków; pozwala to uniknąć potencjalnie nieograniczonego wzrostu zestawu nagrobków. Optymalizację uzyskuje się poprzez zachowanie wektora znaczników czasu dla każdej repliki.

CRDT sekwencji

Sekwencję, listę lub uporządkowany zestaw CRDT można wykorzystać do zbudowania współpracującego w czasie rzeczywistym edytora jako alternatywy dla transformacji operacyjnej (OT).

Niektóre znane sekwencje CRDT to Treedoc, RGA, Woot, Logoot i LSEQ. CRATE to zdecentralizowany edytor czasu rzeczywistego zbudowany na LSEQSplit (rozszerzenie LSEQ) i uruchamiany w sieci przeglądarek korzystających z WebRTC . LogootSplit został zaproponowany jako rozszerzenie Logoot w celu zmniejszenia metadanych dla sekwencji CRDT. MUTE to internetowy edytor współpracujący w czasie rzeczywistym peer-to-peer oparty na algorytmie LogootSplit.

CRDT z sekwencją przemysłową, w tym open-source, są znane z tego, że przewyższają implementacje akademickie dzięki optymalizacji i bardziej realistycznej metodologii testowania. Głównym popularnym przykładem jest Yjs CRDT, pionier w używaniu zwykłej listy zamiast drzewa (ala Kleppmann's automerge ).

Zastosowanie w przemyśle

  • Fluid Framework to platforma współpracy typu open source stworzona przez firmę Microsoft , która zapewnia zarówno implementacje referencyjne serwera, jak i zestawy SDK po stronie klienta do tworzenia nowoczesnych aplikacji internetowych czasu rzeczywistego przy użyciu CRDT.
  • Nimbus Note to aplikacja do wspólnego robienia notatek, która wykorzystuje Yjs CRDT do wspólnego edytowania.
  • Redis to rozproszona, wysoce dostępna i skalowalna baza danych w pamięci, która wykorzystuje CRDT do implementacji globalnie rozproszonych baz danych opartych na otwartym oprogramowaniu Redis i w pełni z nim kompatybilnym.
  • Roshi z otwartym kodem źródłowym SoundCloud , zestaw CRDT z elementami LWW dla strumienia SoundCloud zaimplementowany na Redis .
  • Riak to rozproszony magazyn danych klucz-wartość NoSQL oparty na CRDT. League of Legends wykorzystuje implementację Riak CRDT do swojego systemu czatu w grze, który obsługuje 7,5 miliona jednoczesnych użytkowników i 11 000 wiadomości na sekundę. Bet365 przechowuje setki megabajtów danych w implementacji OR-Set firmy Riak .
  • TomTom wykorzystuje CRDT do synchronizacji danych nawigacyjnych między urządzeniami użytkownika.
  • Phoenix , framework sieciowy napisany w Elixir , używa CRDT do obsługi wielowęzłowej wymiany informacji w czasie rzeczywistym w wersji 1.2.
  • Facebook implementuje CRDT w swojej bazie danych Apollo o niskim opóźnieniu „spójność na dużą skalę”.
  • Facebook używa CRDT w swoim systemie FlightTracker do wewnętrznego zarządzania wykresem Facebooka.
  • Teletype for Atom wykorzystuje CRDT, aby umożliwić programistom współdzielenie przestrzeni roboczej z członkami zespołu i współpracę nad kodem w czasie rzeczywistym.
  • OrbitDB firmy Haja Networks wykorzystuje CRDT oparte na operacjach w swojej podstawowej strukturze danych, IPFS-Log.
  • Firma Apple implementuje CRDT w aplikacji Notes w celu synchronizowania edycji w trybie offline między wieloma urządzeniami.
  • Swim to platforma do uruchamiania rozproszonych aplikacji do przesyłania strumieniowego w czasie rzeczywistym , które zapewniają ciągłą inteligencję. Wykorzystuje aktorów przesyłania strumieniowego, którzy przesyłają strumieniowo aktualizacje stanu CRDT oparte wyłącznie na operacjach do innych aktorów w DAG, który implementuje potok danych strumieniowych.
  • RxDB to baza danych NoSQL po stronie klienta dla rozproszonych aplikacji strumieniowych w czasie rzeczywistym . Posiada wtyczkę CRDT , która umożliwia aktualizację dokumentu poprzez przechowywanie delt CRDT opartych na NoSQL i replikowanie ich z innymi klientami lub serwerem zaplecza.
  1. ^ a b c    Shapiro, Marc; Preguiça, Nuno; Baquero, Carlos; Zawirski, Marek (2011). „Bezkonfliktowe replikowane typy danych” . Stabilizacja, bezpieczeństwo i ochrona systemów rozproszonych (PDF) . Notatki z wykładów z informatyki. Tom. 6976. Grenoble, Francja: Springer Berlin Heidelberg. s. 386–400. doi : 10.1007/978-3-642-24550-3_29 . ISBN 978-3-642-24549-7 . S2CID 51995307 .
  2. ^ a b c d e f g Shapiro, Marc; Preguiça, Nuno; Baquero, Carlos; Zawirski, Marek (13 stycznia 2011). „Kompleksowe badanie zbieżnych i przemiennych replikowanych typów danych”. Rr-7506 .
  3. ^ Shapiro, Marc; Preguiça, Nuno (2007). „Projektowanie przemiennego replikowanego typu danych”. arXiv : 0710.1784 [ cs.DC ].
  4. ^ a b     Oster, Gérald; Urso, Pascal; Molli, Pascal; Imine, Abdessamad (2006). Materiały z 20. rocznicy konferencji 2006 Praca spółdzielcza wspomagana komputerowo - CSCW '06 . P. 259. CiteSeerX 10.1.1.554.3168 . doi : 10.1145/1180875.1180916 . ISBN 978-1595932495 . S2CID 14596943 .
  5. ^ ab Letia , Mihai; Preguiça, Nuno; Shapiro, Marc (2009). „CRDT: spójność bez kontroli współbieżności”. Repozytorium badań komputerowych . ar Xiv : 0907.0929 .
  6. ^    Preguiça, Nuno; Marques, Joan Manuel; Shapiro, Marc; Letia, Mihai (czerwiec 2009), „A Commutative Replicated Data Type for Cooperative Editing” (PDF) , Proc 29th IEEE International Conference on Distributed Computing Systems , Montreal, Quebec, Kanada: IEEE Computer Society, s. 395–403, doi : 10.1109/ICDCS.2009.20 , ISBN 978-0-7695-3659-0 , S2CID 8956372
  7. ^ Baquero, Carlos; Moura, Francisco (1997), Specyfikacja zbieżnych abstrakcyjnych typów danych dla autonomicznych komputerów mobilnych , Universidade do Minho
  8. ^   Schneider, Fred (grudzień 1990). „Wdrażanie usług odpornych na błędy przy użyciu podejścia automatu stanowego: samouczek” . Ankiety komputerowe ACM . 22 (4): 299–319. doi : 10.1145/98163.98167 . S2CID 678818 .
  9. ^ „Bezkonfliktowe replikowane typy danych” (PDF) . inria.fr. 19 lipca 2011 r.
  10. ^   Letia, Mihai; Preguiça, Nuno; Shapiro, Marc (1 kwietnia 2010). „Spójność bez kontroli współbieżności w dużych, dynamicznych systemach” (PDF) . SIGOPS Oper. Syst. ks . 44 (2): 29–34. doi : 10.1145/1773912.1773921 . S2CID 6255174 .
  11. ^ ab Baquero    , Carlos; Almeida, Paulo Sérgio; Szoker, Ali (2014-06-03). Magoutis, Kostas; Pietzuch, Piotr (red.). Dokonywanie operacji CRDT opartych na operacjach na podstawie operacji . Notatki z wykładów z informatyki. Springer Berlin Heidelberg. s. 126–140. CiteSeerX 10.1.1.492.8742 . doi : 10.1007/978-3-662-43352-2_11 . ISBN 9783662433515 .
  12. ^   Baquero, Carlos; Moura, Francisco (1 października 1999). „Wykorzystanie cech konstrukcyjnych do pracy autonomicznej”. SIGOPS Oper. Syst. ks . 33 (4): 90–96. doi : 10.1145/334598.334614 . hdl : 1822/34984 . S2CID 13882850 .
  13. ^ ab ; Almeida, Paulo Sergio    Szoker, Ali; Baquero, Carlos (2015-05-13). Bouajjani, Ahmed; Fauconnier, Hugues (red.). Wydajne CRDT oparte na stanie przez mutację delta . Notatki z wykładów z informatyki. Międzynarodowe wydawnictwo Springera. s. 62–76. ar Xiv : 1410.2803 . doi : 10.1007/978-3-319-26850-7_5 . ISBN 9783319268491 . S2CID 7852769 .
  14. ^   Almeida, Paulo Sergio; Szoker, Ali; Baquero, Carlos (2016-03-04). „Typy danych replikowanych w stanie Delta” . Dziennik obliczeń równoległych i rozproszonych . 111 : 162–173. ar Xiv : 1603.01529 . doi : 10.1016/j.jpdc.2017.08.003 . S2CID 7990602 .
  15. Bibliografia    _ Gotsman, Aleksiej; Yang, Hongseok; Zawirski, Marek (23 stycznia 2014). „Replikowane typy danych: specyfikacja, weryfikacja, optymalność”. Materiały z 41. sympozjum ACM SIGPLAN-SIGACT na temat zasad języków programowania (PDF) . s. 271–284. doi : 10.1145/2535838.2535848 . ISBN 9781450325448 . S2CID 15023909 .
  16. ^ Bieniusa, Annette; Zawirski, Marek; Preguiça, Nuno; Shapiro, Marc; Baquero, Carlos; Balegas, Valter; Duarte, Sergio (2012). „Zoptymalizowany, wolny od konfliktów replikowany zestaw”. arXiv : 1210.3368 [ cs.DC ].
  17. ^ Roh, Huyn-Gul; Jeon, Myeongjae; Kim, Jin Soo; Lee, Joonwon (2011). „Replikowane abstrakcyjne typy danych: elementy składowe aplikacji do współpracy” . Dziennik obliczeń równoległych i rozproszonych . 71 (2): 354–368. doi : 10.1016/j.jpdc.2010.12.006 .
  18. Bibliografia    _ Urso, Pascal; Molli, Pascal (2010). „Logoot-Cofnij: rozproszony system edycji zespołowej w sieciach P2P” . Transakcje IEEE w systemach równoległych i rozproszonych . 21 (8): 1162–1174. doi : 10.1109/TPDS.2009.173 . ISSN 1045-9219 . S2CID 14172605 .
  19. ^    Nedelec, Brice; Molli, Pascal; Mostefaoui, Achour; Desmontils, Emmanuel (2013). „LSEQ”. LSEQ adaptacyjna struktura sekwencji w rozproszonej edycji zespołowej (PDF) . P. 37. doi : 10.1145/2494266.2494278 . ISBN 9781450317894 . S2CID 9215663 .
  20. ^   Nedelec, Brice; Molli, Pascal; Mostefaoui, Achour (2016). „CRATE: pisanie historii razem z naszymi przeglądarkami” . Materiały towarzyszące 25. Międzynarodowej Konferencji w sieci World Wide Web . P. 231. doi : 10.1145/2872518.2890539 . S2CID 5096789 . Zarchiwizowane od oryginału w dniu 2020-01-01 . Źródło 2020-01-01 .
  21. ^   Andrzej, Luc; Martin, Stéphane; Oster, Gerald; Ignat, Claudia-Lavinia (2013). „Wspieranie adaptowalnej szczegółowości zmian w przypadku edycji zespołowej na masową skalę” . Materiały z Międzynarodowej Konferencji na temat Collaborative Computing: Networking, Applications and Worksharing – CollaborateCom 2013 . s. 50–59. doi : 10.4108/icst.collaboratecom.2013.254123 . ISBN 978-1-936968-92-3 .
  22. Bibliografia _ _ Zespół Wybrzeża. 24 marca 2016 r.
  23. ^ Nicolas, Matthieu; Elvinger, Wiktoria; Oster, Gerald; Ignat, Claudia-Lavinia; Charoy, François (2017). „MUTE: oparty na sieci peer-to-peer edytor współpracujący w czasie rzeczywistym” . Obrady paneli ECSCW, pokazy i plakaty 2017 . doi : 10.18420/ecscw2017_p5 .
  24. ^ Delikatny, Seph. „Szybsze CRDT: przygoda z optymalizacją” . josephg.com . Źródło 1 sierpnia 2021 r .
  25. ^ "yjs/yjs: wspólne typy danych do tworzenia oprogramowania do współpracy" . GitHub .
  26. ^ „O CRDT” . Źródło 2020-06-18 .
  27. ^ Bourgon, Peter (9 maja 2014). „Roshi: system CRDT dla zdarzeń ze znacznikiem czasu” . SoundCloud.
  28. ^ „Przedstawiamy Riak 2.0: typy danych, silna spójność, wyszukiwanie pełnotekstowe i wiele więcej” . Basho Technologies, Inc. 29 października 2013 r.
  29. ^ Hoff, Todd (13 października 2014). „Jak League of Legends przeskalowało czat do 70 milionów graczy — potrzeba wielu stworów” . Wysoka skalowalność .
  30. Bibliografia _ "bet365: Dlaczego bet365 wybrał Riak" . Basho.
  31. ^ Iwanow, Dmitrij. „Praktyczna demistyfikacja CRDT” .
  32. Bibliografia _ „Co sprawia, że ​​obecność Phoenix jest wyjątkowa” .
  33. Bibliografia _ „Facebook ogłasza Apollo na QCon NY 2014” .
  34. ^ „FlightTracker: spójność w sklepach internetowych zoptymalizowanych pod kątem odczytu na Facebooku” . badania.facebook.com . Źródło 8 grudnia 2022 r .
  35. ^ „Koduj razem w czasie rzeczywistym za pomocą Teletype for Atom” . Atom.io. 15 listopada 2017 r.
  36. ^ "Logowanie OrbitDB/ipfs na Github" . GitHub . Źródło 2018-09-07 .
  37. ^ „Nagłówki IOS Objective-C pochodzące z introspekcji środowiska wykonawczego: NST / IOS-Runtime-Headers” . GitHub . 2019-07-25.

Linki zewnętrzne