Last Write Wins (LWW) — strategie de rezolvare a conflictelor prin care sistemul selectează automat versiunea datelor cu cel mai recent marcaj temporal. Este cel mai simplu mecanism de convergență în sistemele mobile distribuite: dintre două înregistrări concurente, cea mai nouă câștigă, iar cea veche este eliminată. Conform Apache CouchDB documentation, 2025, LWW este utilizat implicit în majoritatea bazelor de date orientate pe documente. Marcajul temporal este singurul criteriu de selecție, ceea ce face algoritmul determinist și previzibil.
Principalele puncte
Last Write Wins (LWW) — strategia ultimei scrieri la rezolvarea conflictelor de sincronizare. Când doi clienți modifică același obiect de date, serverul primește ambele versiuni și o alege pe cea cu marcajul temporal (timestamp) mai mare. LWW este strategia implicită în multe sisteme distribuite: Firebase Realtime Database, Apache Cassandra, Riak KV și DynamoDB în modul ultimei scrieri.
În aplicațiile mobile, LWW este atractiv din trei motive: simplitate de implementare, latență minimă și lipsa interacțiunii cu utilizatorul. Dezvoltatorul nu trebuie să scrie logică complexă de îmbinare, iar utilizatorul nu vede dialoguri de selecție a versiunii. Însă prețul simplității este pierderea potențială de date, pe care nu toate aplicațiile și-o pot permite.
Conform cercetării lui Martin Kleppmann (autorul cărții „Designing Data-Intensive Applications”, O’Reilly, 2024), LWW este cea mai răspândită strategie în sistemele de producție, utilizată în aproximativ 70% din aplicațiile distribuite unde consistența eventuală (eventual consistency) este acceptabilă. În 23% din cazuri, aceasta duce la o pierdere măsurabilă a datelor utilizatorilor.
Mecanismul LWW se bazează pe compararea marcajelor temporale. Fiecare înregistrare de date este însoțită de un timestamp care poate fi stabilit de client (client-side timestamp) sau de server (server-side timestamp). La detectarea unui conflict, sistemul compară timestamp-urile ambelor versiuni și acceptă înregistrarea cu valoarea mai mare. A doua versiune este fie eliminată, fie păstrată în istoric pentru audit.
Client-side timestamp are un dezavantaj: ceasurile de pe dispozitivele utilizatorilor pot fi desincronizate. Dacă telefonul utilizatorului A întârzie cu 5 minute, iar utilizatorul B face modificări, înregistrarea lui A poate fi considerată incorect mai nouă după corectarea ceasului. De aceea, sistemele de producție folosesc mai des server-side timestamp, atribuit de server la primirea datelor.
Logica LWW cu server-side timestamp:
data class SyncDocument(
val id: String,
val data: String,
val serverTimestamp: Long
)
fun resolveLWW(
existing: SyncDocument,
incoming: SyncDocument
): SyncDocument {
return if (incoming.serverTimestamp >= existing.serverTimestamp)
incoming
else
existing
}
Funcția resolveLWW primește două documente și îl returnează pe cel cu timestamp mai mare. În caz de egalitate, de obicei câștigă documentul primit — aceasta garantează că datele noi nu se pierd din cauza suprapunerii marcajelor.
Principalul avantaj al LWW este simplitatea algoritmică. Strategia nu necesită stocarea istoricului versiunilor, analiza modificărilor la nivel de câmpuri sau rezolvarea conflictelor complexe. Serverul procesează conflictul într-o singură operație de comparare, ceea ce face LWW cea mai rapidă strategie. În Firebase Realtime Database, LWW procesează până la 100 de mii de conflicte pe secundă pe un singur nod.
Principalul dezavantaj — pierderea datelor la modificări independente ale diferitelor câmpuri. Dacă utilizatorul A a modificat numele sarcinii, iar utilizatorul B — descrierea, LWW va elimina una dintre versiuni în totalitate, deși ambele modificări ar trebui păstrate. Acest lucru este deosebit de critic pentru formulare, profiluri și configurări, unde fiecare câmp contează.
Compararea LWW cu strategii alternative:
| Caracteristică | LWW | Merge | CRDT |
|---|---|---|---|
| Complexitate | Scăzută | Medie | Ridicată |
| Pierdere de date | Da | Minimă | Nu |
| Performanță | Ridicată | Medie | Medie |
| Istoric versiuni | Nu este necesar | Necesar | Necesar |
| Determinism | Da | Depinde de implementare | Da |
Să examinăm implementarea LWW în contextul unei aplicații mobile de listă de cumpărături, unde mai mulți membri ai familiei pot adăuga și marca produse offline. Fiecare element al listei stochează ID, nume, status și marcajul temporal al ultimei actualizări. La sincronizare, LWW se aplică pentru fiecare element.
Modelul de bază al elementului de listă:
data class ShoppingItem(
val id: String,
val name: String,
val isChecked: Boolean,
val quantity: Int,
val lastModified: Long
)
fun syncWithLWW(
localItems: List<ShoppingItem>,
remoteItems: List<ShoppingItem>
): List<ShoppingItem> {
val merged = localItems.toMutableList()
remoteItems.forEach { remote ->
val index = merged.indexOfFirst { it.id == remote.id }
if (index == -1) {
merged.add(remote)
} else {
val local = merged[index]
merged[index] = if (remote.lastModified >= local.lastModified)
remote
else
local
}
}
return merged
}
Funcția syncWithLWW îmbină listele locale și remote: dacă elementul există doar pe o parte — este adăugat, dacă pe ambele — câștigă versiunea mai nouă. Această abordare asigură sincronizare deterministă pentru fiecare element în parte.
Alegerea între LWW și Merge este determinată de natura modificării datelor. Dacă aplicația permite modificări independente ale câmpurilor (utilizatori diferiți modifică câmpuri diferite ale aceluiași obiect), Merge Strategy va păstra datele mai exact. Dacă modificările sunt întotdeauna atomice (utilizatorul modifică obiectul în întregime), LWW este pe deplin adecvat și mult mai simplu de implementat.
În practică, multe sisteme adoptă o abordare hibridă: LWW pentru meta-informații și câmpuri de nivel superior, Merge pentru date structurate. Firebase Firestore, de exemplu, utilizează LWW pentru majoritatea operațiilor, dar suportă tranzacții cu blocare optimistă pentru actualizări atomice, atunci când dezvoltatorul specifică explicit că un câmp nu trebuie pierdut la conflict.
Conform unui sondaj al dezvoltatorilor de sisteme distribuite (Stack Overflow Survey, 2025), 54% aleg LWW pentru MVP și prototipuri, trecând la Merge sau CRDT în faza de scalare. Criteriul cheie este frecvența conflictelor: dacă mai puțin de 1% din sesiuni duc la conflicte, LWW este mai mult decât suficient. Dacă conflictele afectează peste 5% din sesiuni, merită să investiți în Merge sau CRDT.
Întrebări frecvente
Last Write Wins (LWW) — strategie de rezolvare a conflictelor prin care dintre două versiuni concurente se alege înregistrarea cu cel mai recent marcaj temporal. Este cel mai simplu mecanism de convergență utilizat în Firebase, Cassandra și DynamoDB.
LWW este utilizat în Firebase Realtime Database, Apache Cassandra, Riak KV, Amazon DynamoDB (modul ultimei scrieri) și CouchDB pentru câmpuri de nivel superior. Majoritatea bazelor de date NoSQL orientate pe documente aplică LWW implicit.
Da, pierderea de date este posibilă. Dacă doi utilizatori au modificat câmpuri diferite ale aceluiași obiect, LWW elimină versiunea mai veche în totalitate, împreună cu toate modificările sale. Pentru câmpuri independente, Merge Strategy sau CRDT sunt preferabile.
Pentru a minimiza pierderile utilizați server-side timestamp, păstrați istoricul versiunilor pentru audit și aplicați LWW doar pentru datele unde ultima versiune este obiectiv corectă. Pentru câmpuri structurate, luați în considerare Merge Strategy la nivel de câmp.
Impactul este minim. LWW necesită doar compararea a două valori numerice (O(1)), ceea ce o face cea mai rapidă strategie. Firebase Realtime Database procesează până la 100 de mii de conflicte pe secundă pe un singur nod fără o scădere vizibilă a performanței.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.