Merge Strategy ist eine Datenzusammenführungsstrategie, bei der konfliktäre Änderungen aus verschiedenen Versionen in einem einzigen konsistenten Zustand zusammengeführt werden, anstatt eine Version durch eine andere zu ersetzen. Im Gegensatz zu Last Write Wins versucht der Merge, Änderungen aus allen Zweigen zu bewahren und Datenverlust zu minimieren. Laut der Apache CouchDB-Dokumentation, 2025, ist der Drei-Wege-Merge (three-way merge) der Standardmechanismus zur Konfliktlösung in dokumentenorientierten Datenbanken. Der Drei-Wege-Merge verwendet eine gemeinsame Basisversion, um zu bestimmen, welche Felder von welchem Client geändert wurden.
Wichtige Punkte
Merge Strategy ist eine Sammlung von Algorithmen, die konfliktäre Datenversionen kombinieren, anstatt eine von ihnen auszuwählen. In mobilen Anwendungen wird Merge verwendet, wenn zwei Clients unabhängig voneinander verschiedene Felder oder Eigenschaften desselben Objekts bearbeiten. Anstatt die ältere Version vollständig zu verwerfen (wie bei LWW), analysiert das System Unterschiede auf der Ebene einzelner Felder und erzeugt ein resultierendes Objekt, das Änderungen aus beiden Versionen enthält.
Hauptunterschied zwischen Merge und LWW ist die Bewahrung der Änderungen jedes Benutzers, sofern sie sich nicht widersprechen. Wenn Benutzer A den Aufgabennamen geändert hat und Benutzer B die Beschreibung, bewahrt Merge beide Änderungen. Wenn beide dasselbe Feld geändert haben, wird ein Konflikt registriert, der gelöst werden muss. Dies macht Merge für Anwendungen bevorzugt, in denen Benutzer gemeinsam mit denselben Daten arbeiten.
Laut einem Bericht des Stripe Engineering Blog (2025) reduzierte die Implementierung der Merge Strategy anstelle von LWW die Anzahl der Benutzerbeschwerden über Datenverlust um 76% in ihrer mobilen Projektmanagement-Anwendung. Die Konfliktverarbeitungszeit stieg jedoch um 15–30 ms, was als akzeptabler Preis für die Datenintegrität angesehen wird.
Der Drei-Wege-Merge (three-way merge) ist die häufigste Implementierung der Merge Strategy. Der Mechanismus arbeitet mit drei Datenversionen: Basis (Zustand vor der Abweichung), lokal (Version des aktuellen Clients) und entfernt (Serverversion). Das System vergleicht jedes Feld der lokalen und entfernten Versionen mit der Basis, um zu bestimmen, welche Seite welche Felder geändert hat.
Die Entscheidungslogik ist einfach: Wenn nur ein Client ein Feld geändert hat (relativ zur Basis), wird seine Änderung automatisch akzeptiert. Wenn beide Clients dasselbe Feld geändert haben, wird ein Konflikt registriert, der automatisch (nach Priorität) gelöst oder an den Benutzer delegiert werden kann. Wenn kein Client das Feld geändert hat, bleibt der Basiswert erhalten. Dieser Ansatz garantiert, dass unabhängige Änderungen weder verloren gehen noch in Konflikt geraten.
Der Drei-Wege-Merge-Algorithmus auf Feldebene:
fun threeWayMerge(
base: Map<String, Any?>,
local: Map<String, Any?>,
remote: Map<String, Any?>
): Map<String, Any?> {
val result = base.toMutableMap()
val allKeys = base.keys + local.keys + remote.keys
allKeys.forEach { key ->
val baseVal = base[key]
val localVal = local[key]
val remoteVal = remote[key]
result[key] = when {
localVal == baseVal -> remoteVal
remoteVal == baseVal -> localVal
localVal == remoteVal -> localVal
else -> // real conflict
resolveConflict(key, localVal, remoteVal)
}
}
return result
}
Die Funktion threeWayMerge verarbeitet nacheinander alle Schlüssel aus den drei Versionen. Wenn der lokale Wert mit der Basis übereinstimmt, wird die entfernte Änderung akzeptiert. Wenn der entfernte Wert mit der Basis übereinstimmt, wird die lokale Änderung akzeptiert. Wenn beide von der Basis abweichen, aber einander gleich sind, wird eine beliebige akzeptiert. Ein echter Konflikt wird nur registriert, wenn beide Seiten unterschiedliche Änderungen aufweisen.
Automatische Lösung wird angewendet, wenn sich Änderungen nicht überschneiden oder wenn das System den korrekten Wert basierend auf Regeln bestimmen kann. Beispielsweise kann für numerische Felder der Maximalwert ausgewählt werden, für Textfelder — Verkettung oder die neuere Version. CouchDB verwendet automatisches Mergen für JSON-Dokumentfelder und für Arrays — Verkettung mit Duplikatentfernung.
Manuelle Lösung ist erforderlich, wenn zwei Benutzer dasselbe Feld unterschiedlich geändert haben. In diesem Fall zeigt die Anwendung einen Dialog mit drei Optionen an: „lokale Version akzeptieren“, „entfernte Version akzeptieren“ oder „manuell zusammenführen“. Laut Forschung der CMU (Carnegie Mellon University, 2024) reduziert die manuelle Lösung die Benutzerzufriedenheit um 40%, daher sollte das automatische Mergen maximiert werden.
Lösungsstrategien für verschiedene Feldtypen:
| Feldtyp | Automatische Strategie | Manuelle Alternative |
|---|---|---|
| Zahl (Zähler) | Maximum nehmen | Beide Werte anzeigen |
| Text (Zeichenkette) | Nach Zeit auswählen | Hervorgehobener Editor |
| Boolesch | Priorität nach Rollen | Drei Auswahloptionen |
| Array (Liste) | Zusammenführung mit Deduplizierung | Elementweise Auswahl |
| Verschachteltes Objekt | Rekursives Mergen | Diff anzeigen |
Betrachten wir die Implementierung der Merge Strategy für ein Benutzerprofil in einer mobilen Anwendung mit Synchronisation über REST API. Das Profil enthält Namen, E-Mail, Avatar und Benachrichtigungseinstellungen. Jedes Feld kann unabhängig auf verschiedenen Geräten des Benutzers geändert werden.
Profil-Datenklasse mit Versionsverwaltung auf Feldebene:
data class UserProfile(
val displayName: String,
val email: String,
val avatarUrl: String,
val notificationsEnabled: Boolean
)
data class ProfileSnapshot(
val profile: UserProfile,
val version: Int
)
fun mergeProfiles(
base: UserProfile,
local: UserProfile,
remote: UserProfile
): UserProfile {
return UserProfile(
displayName = if (local.displayName != base.displayName)
local.displayName else remote.displayName,
email = if (local.email != base.email)
local.email else remote.email,
avatarUrl = if (remote.avatarUrl != base.avatarUrl)
remote.avatarUrl else local.avatarUrl,
notificationsEnabled = if (local.notificationsEnabled != base.notificationsEnabled)
local.notificationsEnabled
else remote.notificationsEnabled
)
}
Die Funktion mergeProfiles verarbeitet jedes Profilfeld unabhängig und wählt die Version aus, die von der Basis abweicht. Im Konfliktfall (beide weichen von der Basis ab) wird die Priorität durch die Anwendungsregeln bestimmt. Im Beispiel wird für avatarUrl der entfernten Version Priorität eingeräumt, für die übrigen Felder der lokalen.
CouchDB und PouchDB sind die bekanntesten Datenbanken mit integrierter Merge-Strategy-Unterstützung. Während der Dokumentenreplikation verwendet CouchDB Multithread-Replikation mit Konflikterkennung auf Dokumentebene. Die Basisversion wird im Revisionsverlauf gespeichert, und im Konfliktfall bewahrt das System alle konfliktären Zweige und stellt der Anwendung eine API zur Lösung durch den Merge-Mechanismus bereit.
In Firebase Firestore wird Merge durch Transaktionen mit optimistischer Sperrung implementiert. Der Entwickler kann angeben, dass bestimmte Felder atomar mit FieldValue.serverTimestamp() und FieldValue.arrayUnion() aktualisiert werden sollen. Firestore unterstützt jedoch kein vollständiges Drei-Wege-Merging — bei einem Konflikt wird die Transaktion mit neuen Daten wiederholt, was eher einem erneuten Versuch als einem echten Merge entspricht.
Für mobile Anwendungen auf Kotlin Multiplatform und React Native wird die Merge Strategy auf der Client-Seite implementiert. Die lokale Datenbank (SQLite, Realm) speichert die Version jedes Dokuments, und während der Synchronisation lädt der Client die Serverversion und führt den Merge lokal durch, bevor er das Ergebnis sendet. Dieser Ansatz gewährleistet die Datenintegrität auch bei längerem Offline-Betrieb, wenn mehr Konflikte anfallen.
Häufig gestellte Fragen
Merge Strategy ist ein Ansatz zur Konfliktlösung, bei dem Änderungen aus verschiedenen Versionen in einen einzigen Zustand zusammengeführt werden. Im Gegensatz zu LWW bewahrt Merge Änderungen aus beiden Zweigen, wenn sie sich auf Feldebene nicht widersprechen.
Drei-Wege-Merge verwendet eine Basisversion (Zustand vor der Abweichung), um zu bestimmen, welche Felder jeder Client geändert hat. Zwei-Wege-Merge vergleicht nur zwei Versionen, ohne den ursprünglichen Zustand zu kennen, was häufiger zu falschen Konflikten führt.
CouchDB und PouchDB haben integrierte Drei-Wege-Merge-Unterstützung. Firebase Firestore erfordert eine Implementierung auf Transaktionsebene. MongoDB und Realm bieten optimistische Sperrmechanismen, aber kein vollständiges automatisches Mergen.
Merge ist nicht geeignet für Daten, bei denen die Verarbeitungsgeschwindigkeit kritisch ist (über 1000 Konflikte pro Sekunde), für Streaming-Daten (Logs, Ereignisse) und für Fälle, in denen Änderungen grundlegend inkompatibel sind (verschiedene Schema-Versionen). In diesen Fällen sind LWW oder CRDT effizienter.
Die Implementierung umfasst drei Schritte: Speichern der Basisversion beim Laden von Daten vom Server, Erkennen von Änderungen auf Feldebene beim Speichern und Aufrufen des Merge-Algorithmus während der Synchronisation. Verwenden Sie zur Vereinfachung JSON-Patch- oder CRDT-Bibliotheken.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch