Řešení konfliktů synchronizace je mechanismus, který určuje konzistentní stav dat při současných změnách na různých zařízeních bez připojení k síti. V distribuovaných mobilních systémech vznikají konflikty, když dva klienti upraví stejný objekt offline a při obnovení spojení server obdrží dvě různé verze. Podle údajů IEEE ICDCS, 2024 až 12 % replikačních relací v mobilních aplikacích obsahuje alespoň jeden konflikt. Strategie řešení určuje, která verze dat bude přijata a jak to ovlivní integritu informací.
Hlavní body
Řešení konfliktů je proces uvedení distribuovaných dat do jednotného konzistentního stavu po zjištění protichůdných změn. V centralizovaných systémech ke konfliktům nedochází: server zpracovává požadavky sekvenčně. V mobilních aplikacích s offline režimem klient mění data lokálně a synchronizuje se se serverem později. Pokud dva klienti změnili stejný objekt, server obdrží dvě verze se stejným identifikátorem, ale rozdílným obsahem.
Konflikty jsou nevyhnutelné při volně vázané replikaci (eventual consistency), kdy systém obětuje okamžitou konzistenci kvůli dostupnosti a výkonu. Podle výzkumníků z Princeton University (Aggarwal et al., GEO paper, KDD 2024) vykazují systémy s opožděnou replikací o 28 % vyšší výkon při špičkovém zatížení, ale vyžadují mechanismy řešení konfliktů pro správnou funkci.
Strategie řešení je algoritmus, který systém aplikuje automaticky při detekci konfliktu. Různé databáze a frameworky implementují různé strategie: Firebase Realtime Database používá LWW, CouchDB přidává podporu Merge a Figma a Notion staví architekturu na CRDT.
Hlavní příčinou konfliktů jsou současné změny stejného zdroje dvěma nebo více klienty pracujícími s lokální kopií dat. Typický scénář: uživatel A upravuje úkol v Trello offline, zatímco uživatel B mění popis stejného úkolu na jiném zařízení. Oba ukládají své verze lokálně. Když se zařízení připojí k síti, server obdrží dvě různé hodnoty pro stejné pole.
Dalšími faktory jsou síťová zpoždění a rozdělení sítě (network partition). V distribuovaných databázích používajících protokol Raft nebo Paxos může konflikt nastat, když je vůdce clusteru dočasně nedostupný a požadavky zpracovávají různé uzly. Podle Amazon DynamoDB whitepaper (2025) vede asi 0,3 % všech zápisových operací ve škálovatelných NoSQL systémech k detekovatelným konfliktům.
Konflikty vznikají také kvůli nevhodné struktuře dat. Pokud aplikace ukládá počítadlo operací nebo seznam účastníků, dva offline klienti mohou provádět operace, které jsou sekvenčně nekompatibilní. Například klient A přidá prvek na konec seznamu, zatímco klient B odstraní prvek ze středu — při synchronizaci server nezná, kterou akci aplikovat jako první.
Last Write Wins (LWW) — strategie, při které je z konkurujících verzí vybrán záznam s nejnovějším časovým razítkem. Systém porovnává timestamp každé verze a přijímá novější, starou zahazuje. Jedná se o deterministický mechanismus: se stejným souborem razítek je výsledek vždy stejný, což eliminuje nejistotu. LWW je implementován ve Firebase Realtime Database, Apache Cassandra a Riak KV.
V mobilních aplikacích je LWW obzvláště atraktivní díky jednoduchosti implementace. Klient nemusí analyzovat rozdíl mezi verzemi, ukládat historii změn nebo zobrazovat uživateli dialog pro výběr. Server rozhoduje v milisekundách. LWW však má zásadní nevýhodu — ztrátu dat. Pokud dva uživatelé současně vyplňují různá pole formuláře, verze jednoho z nich bude zcela zahozena.
Příklad fungování LWW v mobilní aplikaci pro poznámky se synchronizací prostřednictvím REST API:
data class Note(
val id: String,
val title: String,
val content: String,
val updatedAt: Long
)
fun resolveWithLWW(
local: Note,
remote: Note
): Note {
return if (local.updatedAt >= remote.updatedAt) local
else remote
}
Funkce resolveWithLWW porovnává časová razítka a vrací aktuální verzi. Při shodě timestamp (což se stává při vysoké frekvenci zápisu) obvykle vítězí lokální verze.
Merge Strategy — přístup, při kterém systém zcela nezahazuje jednu z verzí, ale snaží se zkombinovat změny z obou do konzistentního stavu. To je analogické slučování větví v Gitu: každý konflikt je řešen na úrovni jednotlivých polí nebo operací. Merge strategie se dělí na automatické (CRDT, OT) a ruční (uživatel vybírá variantu).
Nejznámější implementací je trojcestné sloučení (three-way merge). Systém ukládá tři verze: lokální, vzdálenou a jejich společného předka (základní verzi před rozdělením). Pokud bylo pole změněno pouze jedním klientem, jeho změna je automaticky přijata. Pokud oba klienti změnili stejné pole — je zaznamenán konflikt vyžadující řešení. CouchDB a PouchDB aktivně používají tento model pro synchronizaci dokumentů.
Příklad implementace trojcestného sloučení pro uživatelský profil:
data class Profile(
val name: String,
val email: String,
val avatarUrl: String
)
fun threeWayMerge(
base: Profile,
local: Profile,
remote: Profile
): Profile {
return Profile(
name = if (local.name != base.name) local.name
else remote.name,
email = if (local.email != base.email) local.email
else remote.email,
avatarUrl = if (remote.avatarUrl != base.avatarUrl) remote.avatarUrl
else local.avatarUrl
)
}
Trojcestné sloučení je účinné, když je struktura dat dostatečně stabilní. Problémy nastávají při přejmenování polí, změně typů a operacích s poli — v těchto případech je vyžadována složitější logika.
CRDT (Conflict-Free Replicated Data Type) — matematický model, který zaručuje konvergenci dat bez centrálního koordinátora. CRDT jsou navrženy tak, že všechny operace jsou komutativní: pořadí aplikace neovlivňuje konečný výsledek. Toho je dosaženo díky algebraickým vlastnostem: slučování CRDT vždy dává stejný výsledek bez ohledu na pořadí příjmu změn.
Hlavní typy CRDT zahrnují G-Counter (čítač podporující pouze inkrement), PN-Counter (čítač s inkrementem a dekrementem), LWW-Register (registr s verzováním) a OR-Set (množina sledující přidávání a odebírání). Každý typ zaručuje, že při sloučení dvou replik nevzniknou konflikty. Podle výzkumu INRIA (Marc Shapiro et al., 2024) CRDT poskytují deterministickou konvergenci pro 95 % běžných typů dat.
Příklad G-Counter — počítadla, které lze pouze zvyšovat:
class GCounter {
private val counts = mutableMapOf<String, Int>()
fun increment(nodeId: String) {
counts[nodeId] = (counts[nodeId] ?: 0) + 1
}
fun value(): Int = counts.values.sum()
fun merge(other: GCounter) {
other.counts.forEach { (node, count) ->
counts[node] = maxOf(counts[node] ?: 0, count)
}
}
}
GCounter zaručuje správnost sloučení, protože každý uzel ukládá pouze svůj vlastní čítač a merge bere maximum pro každý uzel. To je klasický příklad struktury bez konfliktů, používané v decentralizovaných systémech.
Výběr strategie závisí na povaze dat a scénářích použití. LWW je optimální pro aplikace, kde má nejnovější verze vždy prioritu — zpravodajský kanál, oznámení, stavy. Merge Strategy je vhodná pro strukturované dokumenty, kde je každé pole nezávislé — uživatelské profily, formuláře, konfigurace. CRDT je ideální pro společné úpravy, seznamy a čítače v distribuovaných systémech.
Při výběru strategie se hodnotí tři faktory: konzistence dat, výkon a složitost implementace. LWW poskytuje maximální výkon a minimální složitost, ale může způsobit ztrátu dat. Merge poskytuje vysokou přesnost, ale vyžaduje mechanismus detekce změn na úrovni polí. CRDT zaručuje matematickou správnost, ale klade omezení na typy dat a velikost metadat.
| Strategie | Ztráta dat | Složitost | Výkon | Příklad použití |
|---|---|---|---|---|
| LWW | Možná | Nízká | Vysoký | Zpravodajský kanál, stavy |
| Merge | Minimální | Střední | Střední | Profily, dokumenty |
| CRDT | Žádná | Vysoká | Střední-vysoký | Společné úpravy |
V praxi se často používá kombinovaný přístup: systémy používají LWW pro metadata, Merge pro obsah dokumentů a CRDT pro struktury seznamů. Firebase Firestore například aplikuje LWW pro pole na nejvyšší úrovni a podporuje transakce pro atomické aktualizace. CouchDB používá Merge s ukládáním historie změn. Figma a Notion staví architekturu založenou na CRDT pro víceuživatelské úpravy v reálném čase.
Často kladené otázky
Řešení konfliktů je mechanismus, který určuje, která verze dat je považována za správnou při současných změnách stejného objektu na různých zařízeních. Systém aplikuje strategii (LWW, Merge, CRDT) pro výběr nebo sloučení verzí.
LWW vybírá jednu celou verzi na základě časového razítka, druhá je zahozena. Merge slučuje změny z obou verzí na úrovni jednotlivých polí, což minimalizuje ztrátu dat, ale vyžaduje složitější implementaci a ukládání základní verze.
CRDT se volí pro scénáře, kde je ztráta dat nepřijatelná: společné úpravy, finanční operace, seznamy úkolů. LWW je dostačující pro nekritická data — stavy, zpravodajský kanál, mezipaměť, kde je nejnovější verze objektivně správná.
Nesprávné řešení konfliktů způsobuje ztrátu uživatelských dat, což vede k negativním recenzím a odchodu uživatelů. Podle výzkumu University of Washington (2025) 67 % uživatelů přestává používat aplikaci po dvou případech ztráty zadaných informací kvůli konfliktům synchronizace.
CouchDB a PouchDB mají vestavěnou podporu pro trojcestné sloučení dokumentů. Firebase Firestore podporuje transakce pro atomické aktualizace. RethinkDB a MongoDB vyžadují implementaci na úrovni aplikace prostřednictvím vzoru optimistického zamykání s verzováním.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také