Heim >Web-Frontend >js-Tutorial >Replicache Big Picture

Replicache Big Picture

Patricia Arquette
Patricia ArquetteOriginal
2025-01-02 20:23:39909Durchsuche

Replicache

Dies ist ein Framework, das bei der Implementierung von Local First Software hilft. Git hilft in ähnlicher Weise bei der Organisation synchronisierter Aufgaben durch Push und Pull.

Replicache synchronisiert Serverdaten asynchron hinter den Kulissen, wodurch Server-Roundtrips vermieden und sofortige Änderungen an der Benutzeroberfläche ermöglicht werden.

Replika-Teile

Replicache besteht aus mehreren Elementen.

Replicache

Replicache kann als browserinterner Schlüsselwertspeicher betrachtet werden, der intern Git-ähnliche Vorgänge enthält. Zuerst in den Speicher schreiben und später synchronisieren.

Ihre Bewerbung

Dies ist eine von uns erstellte Anwendung, ähnlich einer Webanwendung. Es ist die Entität, die den Zustand in Replicache speichert. Mutator und Abonnement werden implementiert, um den Status zu ändern und darauf zu reagieren

Ihr Server

Es dient dazu, die zuverlässigsten Daten zu speichern. Der in der mit dem Server verbundenen Datenbank gespeicherte Status hat Vorrang vor dem Status in der Anwendung.

Der Server muss Push (Upstream) und Pull (Downstream) implementieren, um mit dem Replicache des Clients zu kommunizieren.

  • push(upstream): Replicache sendet Änderungen an den Push-Endpunkt. Mutatoren werden sowohl auf Servern als auch in Anwendungen implementiert, und dieser Push-Endpunkt führt diesen Mutator aus, um den Status der Datenbank zu ändern.

  • pull(downstream): Bei regelmäßiger oder expliziter Anforderung sendet Replicache eine Pull-Anfrage an den Server. Der Server gibt die Änderungen zurück, die erforderlich sind, damit der Client mit dem Status des Servers übereinstimmt.

  • Poke: Obwohl der Client regelmäßig eine Pull-Anfrage sendet, um diese in Echtzeit anzuzeigen, ist es bei einer Änderung auf dem Server ein Signal, dass der Server dem Client einen Hinweis darauf gibt Stellen Sie eine Pull-Anfrage. Es werden keine Daten übertragen.

Synchronisieren

Die Anwendung und der Server werden auf den neuesten Stand synchronisiert. Das Bild unten zeigt diesen Vorgang deutlich. Es zeigt den Prozess des regelmäßigen Abrufens von Statusänderungen vom Server und der Aktualisierung der Benutzeroberfläche sowie wie Statusänderungen auf dem Client zunächst die Benutzeroberfläche aktualisieren und dann an den Server übertragen werden

Replicache Big Picture Quelle

Clients, ClientGruppen, Caches

Der Replikat-Cache im Speicher wird als Client bezeichnet.


import {Replicache} from "replicache";

const rep = new Replicache({
  name: userID,
  ...
});

console.log(rep.clientID);
Normalerweise gibt es einen Client pro Tap. Der Client ist volatil und folgt dem Lebenszyklus der Registerkarte. Hat eine eindeutige Client-ID.

Client-Gruppe ist eine Gruppe von Clients, die lokale Daten teilen. Clients innerhalb dieser Clientgruppe teilen ihren Status auch dann, wenn sie offline sind.

Client Group verwendet einen persistenten Cache auf der Festplatte, der durch den Namensparameter des Replicache-Konstruktors unterschieden wird. Alle Clients, die zu einer Clientgruppe mit demselben Namen gehören, teilen sich denselben Cache.

Die Client-Ansicht

Der Client verfügt über eine geordnete Karte von Schlüssel-Wert-Paaren im persistenten Cache, die als Client-Ansicht bezeichnet wird. Die Clientansicht enthält Anwendungsdaten und wird mit Serverdaten synchronisiert. Der Grund für den Namen „Client View“ liegt darin, dass verschiedene Clients möglicherweise Serverdaten in unterschiedlichen Client Views haben. Dies bedeutet, dass jeder Client den Status des Servers anders sieht.

Der Zugriff auf die Client-Ansicht erfolgt sehr schnell. Die Leselatenz beträgt weniger als 1 ms und die meisten Geräte haben einen Durchsatz von 500 MB/s.

Es wird empfohlen, dass Sie es direkt aus der Client-Ansicht lesen und verwenden, anstatt die Client-Ansicht separat mit useState von einem Ort wie React zu kopieren und in den Speicher hochzuladen. Wenn der Mutator die Client-Ansicht ändert, wird das Abonnement ausgelöst, sodass die Benutzeroberfläche aktualisiert wird

Abonnements

Die Subscribe-Funktion empfängt das ReadTransaction-Argument und implementiert das Lesen aus Replicache. Immer wenn dieses Abonnement aufgrund einer Änderung der Replikache-Daten nicht mehr aktuell ist, wird die Abonnementfunktion erneut ausgeführt. Wenn sich dieses Ergebnis ändert, wird der Wert aktualisiert und die Benutzeroberfläche wird ebenfalls aktualisiert.

Wenn Sie die Benutzeroberfläche über ein Abonnement konfigurieren, können Sie sie immer auf dem neuesten Stand halten.

import {Replicache} from "replicache";

const rep = new Replicache({
  name: userID,
  ...
});

console.log(rep.clientID);

Mutationen

Mutation bezieht sich auf die Aufgabe, Replicache-Daten zu ändern. Das Subjekt, das Mutationen empfängt und tatsächlich Daten ändert, wird Mutator genannt.

Beim Start werden mehrere Mutatoren in Replicache registriert, aber es handelt sich eigentlich nur um benannte Funktionen. Sowohl createTodo als auch markTodoComplete unten sind Mutatoren, die Replicache-Daten über WriteTransaction ändern.

const todos = useSubscribe(rep, async tx => {
  return await tx.scan({prefix: 'todo/'}).toArray();
});
return (
  <ul>
    {todos.map(todo => (
      <li key={todo.id}>{todo.text}</li>
    ))}
  </ul>
);

Mutator funktioniert wie folgt. Wenn der Mutator ausgeführt wird, ändern sich die Daten und die damit verbundenen Abonnements werden ausgelöst, und auch die Benutzeroberfläche ändert sich.

const rep = new Replicache({
  ...
  mutators: {
    createTodo,
    markTodoComplete,
  },
});

async function createTodo(tx: WriteTransaction, todo: Todo) {
  await tx.set(`/todo/${todo.id}`, todo);
}

async function markTodoComplete(tx: WriteTransaction,
    {id, complete}: {id: string, complete: boolean}) {
  const key = `/todo/${id}`;
  const todo = await tx.get(key);
  if (!todo) {
    return;
  }
  todo.complete = complete;
  await tx.set(key, todo);
}

Intern erzeugt Mutator etwas namens Mutation. Es ist wie ein Ausführungsdatensatz, aber Replicache erstellt die folgende Mutation.

await rep.mutate.createTodo({id: nanoid(), text: "take out the trash"});

Diese Mutationen werden als ausstehend markiert, bis sie auf den Server übertragen und vollständig synchronisiert werden.

Details synchronisieren

Hier sind nun die Details von Sync, das als Kern von Replicache bezeichnet werden kann. Die Synchronisierung erfolgt auf dem Server.

Das Replikat-Synchronisierungsmodell

(Von nun an bezieht sich der Ausdruck „Zustand“ auf den Zustand von Daten (Schlüssel-Wert-Raum), die aus mehreren Schlüssel-Wert-Paaren bestehen.)

Das Synchronisierungsproblem, das Replicache zu lösen versucht, tritt auf, wenn mehrere Clients gleichzeitig denselben Status ändern und die folgenden Bedingungen vorliegen.

  1. Der Zustand, den der Server hat, ist die Quelle der Wahrheit. Es wird als kanonisch ausgedrückt.
  2. Änderungen im lokalen Bundesstaat des Kunden werden sofort berücksichtigt. Dies nennt man spekulativ.
  3. Der Server muss Änderungen genau einmal anwenden und die Ergebnisse müssen vorhersehbar sein. Auf dem Server vorgenommene Änderungen müssen sinnvoll mit lokalen Änderungen auf dem Client zusammengeführt werden können.

Der letzte Punkt davon ist die „vernünftige Zusammenführung“ von Serveränderungen mit dem lokalen Status, was ein interessantes Thema ist. Für eine „rationale Fusion“ müssen die folgenden Situationen berücksichtigt werden.

  • Wenn lokale Änderungen noch nicht auf den Server angewendet wurden. In diesem Fall müssen Sie sicherstellen, dass lokale Änderungen nicht von der Benutzeroberfläche der App verschwinden, selbst wenn ein neuer Status vom Server abgerufen wird. Nach Erhalt des neuen Status vom Server müssen alle vorhandenen lokalen Änderungen zusätzlich zum Serverstatus erneut ausgeführt werden.

  • Wenn lokale Änderungen, die auf dem Client vorgenommen wurden, bereits an den Server gesendet und im Serverstatus widergespiegelt wurden. Achten Sie in diesem Fall darauf, lokale Änderungen nicht zweimal anzuwenden. Lokale Änderungen sollten nicht erneut angewendet werden

  • Wenn es andere Clients gibt, die den Serverstatus in denselben Status geändert haben. In diesem Fall müssen wie im ersten Fall lokale Änderungen basierend auf dem vom Server empfangenen Status erneut vorgenommen werden. Da jedoch Konflikte über dieselbe Ressource auftreten können, muss die Zusammenführungslogik sorgfältig geplant werden. Schreiben Sie diese Logik in den Mutator.

Lassen Sie uns den Betriebsablauf des Mutators verfolgen.

Lokale Ausführung

Der Mutator arbeitet lokal und der Wert des Replikache ändert sich entsprechend der Mutatorlogik. Gleichzeitig erstellt dieser Client eine Mutation mit einer mutationId, die sequenziell ansteigt. Mutationen werden als ausstehende Mutationen in die Warteschlange gestellt

Drücken

Ausstehende Mutationen werden an den auf dem Server implementierten Push-Endpunkt (Replicache-Push) gesendet.

Mutation ändert den kanonischen Zustand, indem sie den auf dem Server implementierten Mutator ausführt. Beim Anwenden der Mutation wird die letzte Mutations-ID dieses Clients aktualisiert und wird zu einem Wert, der es Ihnen ermöglicht, zu wissen, ab welcher Mutation dieser Client den nächsten Pull erneut anwenden soll

Eine ausstehende Mutation, die lokal angewendet wird, generiert ein spekulatives Ergebnis, und eine auf dem Server angewendete Mutation generiert ein kanonisches Ergebnis. Auf dem Server angewendete Mutationen werden bestätigt und nicht erneut lokal ausgeführt. Auch wenn dieselbe Mutation ein anderes Ergebnis zurückgibt, hat das kanonische Ergebnis des Servers Vorrang, sodass sich das Ergebnis des Clients ändert

Ziehen

Replicache sendet regelmäßig eine Anfrage an den Pull-Endpunkt (replicache-pull), um den neuesten Status abzurufen und die Benutzeroberfläche zu aktualisieren.

Pull-Anfrage enthält Cookie und clientGroupId und gibt neues Cookie, Patch und lastMutationIDChanges zurück.

Cookie wird verwendet, um den vom Client gehaltenen Serverstatus zu unterscheiden. Jeder Wert, der verfolgen kann, wie stark sich die Server- und Client-Zustände unterscheiden, ist ausreichend. Sie können es sich als eine globale „Version“ vorstellen, die sich jedes Mal ändert, wenn sich der Status der Datenbank ändert. Alternativ können Sie eine Cookie-Strategie verwenden, um einen spezifischeren Datenbereich zu verfolgen.

lastMutationIdChanges ist ein Wert, der die zuletzt vom Server für jeden Client angewendete Mutations-ID darstellt. Alle Mutationen mit einer Mutations-ID kleiner als dieser Wert sollten nicht mehr als ausstehend, sondern bestätigt betrachtet werden.

Rebase

Wenn ein Client einen Pull erhält, muss der Patch auf den lokalen Staat angewendet werden. Da sich die ausstehende Mutation jedoch auf den aktuellen lokalen Zustand ausgewirkt hätte, kann der Patch nicht direkt auf den lokalen Staat angewendet werden. Machen Sie stattdessen die lokal ausstehende Mutation rückgängig, wenden Sie zuerst den als Pull empfangenen Patch an und wenden Sie dann die lokal ausstehende Mutation erneut an.

Um diese Art des Rückgängigmachens und erneuten Anwendens zu ermöglichen, wurde Replicache ähnlich wie Git entwickelt. Sie können sich den Status des Servers als Hauptzweig vorstellen und den durch eine lokal anstehende Mutation geänderten Status als Entwicklungszweig, einen Pull vom Server zum Hauptzweig empfangen und die Entwicklung auf den Hauptzweig umbasieren.

Konflikte, die beim Rebase auftreten können, werden im Folgenden gesondert besprochen.

Sack

Poke ist, wie oben erläutert, eine Hinweisnachricht, die der Server dem Client zum Pullen auffordert.

Konfliktlösung

Merge-Konflikte sind in verteilten Systemen wie Replicache unvermeidbar. Während des Pull- und Push-Vorgangs ist eine Zusammenführung erforderlich. Das Zusammenführen sollte auf eine Weise erfolgen, die das Zusammenführungsergebnis vorhersehbar macht und zum Zweck der App passt.

Wenn es sich um eine Konferenzraum-Reservierungs-App handelt, sollte bei Auftreten eines Konflikts nur eine Anfrage genehmigt werden. Daher müssen Sie eine Zusammenführungsmethode anwenden, die nur Kunden genehmigt, die zuerst Reservierungen vorgenommen haben.

Wenn es sich hingegen um eine Todo-App handelt, besteht der Zweck der Todo-Liste darin, dass beide Änderungen genehmigt werden, auch wenn Ergänzungen gleichzeitig erfolgen.

Ein Zusammenführungskonflikt tritt in den folgenden zwei Situationen auf.

  1. Wenn lokale Änderungen auf den Server angewendet werden. Dies liegt daran, dass der Status bei lokaler Anwendung und der Status bei Anwendung auf dem Server unterschiedlich sein können.

  2. Beim Umbasieren. Dies liegt daran, dass der Status bei der Anwendung unterschiedlich sein kann.

Replicache erkennt, dass die Zusammenführungsmethode je nach Zweck der App unterschiedlich implementiert werden muss, sodass Entwickler sie implementieren können. Entwickler können diese Logik über Mutator implementieren.

Das obige ist der detaillierte Inhalt vonReplicache Big Picture. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn