Η επίλυση συγκρούσεων συγχρονισμού είναι ένας μηχανισμός που καθορίζει τη συνεπή κατάσταση των δεδομένων κατά τη διάρκεια ταυτόχρονων αλλαγών σε διαφορετικές συσκευές χωρίς σύνδεση στο δίκτυο. Σε κατανεμημένα κινητά συστήματα, συγκρούσεις προκύπτουν όταν δύο πελάτες τροποποιούν το ίδιο αντικείμενο σε σύνδεση offline, και κατά την αποκατάσταση της σύνδεσης ο διακομιστής λαμβάνει δύο διαφορετικές εκδόσεις. Σύμφωνα με τα δεδομένα IEEE ICDCS, 2024, έως και 12% των συνεδριών αντιγραφής σε κινητές εφαρμογές περιέχουν τουλάχιστον μία σύγκρουση. Η στρατηγική επίλυσης καθορίζει ποια έκδοση των δεδομένων θα γίνει αποδεκτή και πώς αυτό θα επηρεάσει την ακεραιότητα των πληροφοριών.
Βασικά σημεία
Επίλυση συγκρούσεων είναι η διαδικασία μεταφοράς των κατανεμημένων δεδομένων σε μία ενιαία συνεπή κατάσταση μετά την ανίχνευση αντιφατικών αλλαγών. Σε κεντρικοποιημένα συστήματα, δεν προκύπτουν συγκρούσεις: ο διακομιστής επεξεργάζεται τα αιτήματα σειριακά. Σε κινητές εφαρμογές με λειτουργία offline, ο πελάτης τροποποιεί τα δεδομένα τοπικά και συγχρονίζεται με τον διακομιστή αργότερα. Εάν δύο πελάτες έχουν τροποποιήσει το ίδιο αντικείμενο, ο διακομιστής λαμβάνει δύο εκδόσεις με το ίδιο αναγνωριστικό αλλά διαφορετικό περιεχόμενο.
Οι συγκρούσεις είναι αναπόφευκτες σε χαλαρή συζευγμένη αντιγραφή (eventual consistency), όταν το σύστημα θυσιάζει την άμεση συνέπεια για τη διαθεσιμότητα και την απόδοση. Σύμφωνα με ερευνητές από το Princeton University (Aggarwal et al., GEO paper, KDD 2024), τα συστήματα με καθυστερημένη αντιγραφή εμφανίζουν 28% υψηλότερη απόδοση σε φορτία αιχμής, αλλά απαιτούν μηχανισμούς επίλυσης συγκρούσεων για σωστή λειτουργία.
Η στρατηγική επίλυσης είναι ένας αλγόριθμος που το σύστημα εφαρμόζει αυτόματα κατά την ανίχνευση σύγκρουσης. Διαφορετικές βάσεις δεδομένων και πλαίσια εργασίας υλοποιούν διαφορετικές στρατηγικές: η Firebase Realtime Database χρησιμοποιεί LWW, η CouchDB προσθέτει υποστήριξη Merge, και η Figma και το Notion χτίζουν αρχιτεκτονική σε CRDT.
Η κύρια αιτία συγκρούσεων είναι οι ταυτόχρονες αλλαγές του ίδιου πόρου από δύο ή περισσότερους πελάτες που εργάζονται με τοπικό αντίγραφο δεδομένων. Τυπικό σενάριο: ο χρήστης Α επεξεργάζεται μία εργασία στο Trello offline, ενώ ο χρήστης Β αλλάζει την περιγραφή της ίδιας εργασίας σε άλλη συσκευή. Και οι δύο αποθηκεύουν τις εκδόσεις τους τοπικά. Όταν οι συσκευές συνδεθούν στο δίκτυο, ο διακομιστής λαμβάνει δύο διαφορετικές τιμές για το ίδιο πεδίο.
Πρόσθετοι παράγοντες είναι οι καθυστερήσεις δικτύου και η διαίρεση δικτύου (network partition). Σε κατανεμημένες βάσεις δεδομένων που χρησιμοποιούν πρωτόκολλο Raft ή Paxos, μία σύγκρουση μπορεί να προκύψει όταν ο ηγέτης του συστήματος είναι προσωρινά μη διαθέσιμος και τα αιτήματα επεξεργάζονται από διαφορετικούς κόμβους. Σύμφωνα με το Amazon DynamoDB whitepaper (2025), περίπου 0,3% όλων των εγγραφών σε επεκτάσιμα συστήματα NoSQL οδηγούν σε ανιχνεύσιμες συγκρούσεις.
Συγκρούσεις προκύπτουν επίσης από ακατάλληλη δομή δεδομένων. Εάν η εφαρμογή αποθηκεύει έναν απαριθμητή λειτουργιών ή μία λίστα συμμετεχόντων, δύο πελάτες offline μπορούν να εκτελέσουν λειτουργίες που είναι σειριακά ασύμβατες. Για παράδειγμα, ο πελάτης Α προσθέτει ένα στοιχείο στο τέλος της λίστας, ενώ ο πελάτης Β διαγράφει ένα στοιχείο από τη μέση — κατά τον συγχρονισμό ο διακομιστής δεν γνωρίζει ποια ενέργεια να εφαρμόσει πρώτη.
Last Write Wins (LWW) — στρατηγική όπου από τις ανταγωνιζόμενες εκδόσεις επιλέγεται η εγγραφή με την πιο πρόσφατη χρονική σφραγίδα. Το σύστημα συγκρίνει τη χρονική σφραγίδα κάθε έκδοσης και αποδέχεται τη νεότερη, απορρίπτοντας την παλιά. Αυτός είναι ένας ντετερμινιστικός μηχανισμός: με το ίδιο σύνολο σφραγίδων, το αποτέλεσμα είναι πάντα το ίδιο, εξαλείφοντας την αβεβαιότητα. Το LWW εφαρμόζεται στη Firebase Realtime Database, στον Apache Cassandra και στο Riak KV.
Σε κινητές εφαρμογές, το LWW είναι ιδιαίτερα ελκυστικό λόγω της απλότητας υλοποίησης. Ο πελάτης δεν χρειάζεται να αναλύσει τη διαφορά μεταξύ εκδόσεων, να αποθηκεύσει το ιστορικό αλλαγών ή να εμφανίσει στον χρήστη ένα παράθυρο επιλογής. Ο διακομιστής λαμβάνει την απόφαση σε χιλιοστά του δευτερολέπτου. Ωστόσο, το LWW έχει ένα θεμελιώδες μειονέκτημα — απώλεια δεδομένων. Εάν δύο χρήστες συμπληρώνουν ταυτόχρονα διαφορετικά πεδία ενός φόρμας, η έκδοση του ενός θα απορριφτεί πλήρως.
Παράδειγμα λειτουργίας LWW σε μια κινητή εφαρμογή σημειώσεων με συγχρονισμό μέσω 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
}
Η συνάρτηση resolveWithLWW συγκρίνει τις χρονικές σφραγίδες και επιστρέφει την τρέχουσα έκδοση. Σε περίπτωση ίσου timestamp (που συμβαίνει σε υψηλή συχνότητα εγγραφής) συνήθως κερδίζει η τοπική έκδοση.
Merge Strategy — προσέγγιση όπου το σύστημα δεν απορρίπτει τελείως μία από τις εκδόσεις, αλλά προσπαθεί να συνδυάσει τις αλλαγές και από τις δύο σε μία συνεπή κατάσταση. Αυτό είναι ανάλογο με τη συγχώνευση κλαδιών στο Git: κάθε σύγκρουση επιλύεται σε επίπεδο μεμονωμένων πεδίων ή λειτουργιών. Οι στρατηγικές Merge διαιρούνται σε αυτόματες (CRDT, OT) και χειροκίνητες (ο χρήστης επιλέγει τη βαριαντή).
Η πιο γνωστή υλοποίηση είναι το τριμερής συγχώνευση (three-way merge). Το σύστημα αποθηκεύει τρεις εκδόσεις: τοπική, απομακρυσμένη και τον κοινό τους πρόγονο (τη βασική έκδοση πριν από τη διακρουστή). Εάν ένα πεδίο τροποποιήθηκε μόνο από έναν πελάτη, η αλλαγή του γίνεται αυτόματα αποδεκτή. Εάν και οι δύο πελάτες τροποποίησαν το ίδιο πεδίο — καταγράφεται μία σύγκρουση που απαιτεί επίλυση. Η CouchDB και η PouchDB χρησιμοποιούν ενεργά αυτό το μοντέλο για τον συγχρονισμό εγγράφων.
Παράδειγμα υλοποίησης τριμερούς συγχώνευσης για προφίλ χρήστη:
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
)
}
Τριμερής συγχώνευση είναι αποτελεσματική όταν η δομή δεδομένων είναι αρκετά σταθερή. Προβλήματα προκύπτουν κατά τη μετονομασία πεδίων, την αλλαγή τύπων και τις λειτουργίες με πίνακες — σε αυτές τις περιπτώσεις απαιτείται πιο περίπλοκη λογική.
CRDT (Conflict-Free Replicated Data Type) — μαθηματικό μοντέλο που εγγυάται τη σύγκλιση των δεδομένων χωρίς κεντρικό συντονιστή. Τα CRDT έχουν σχεδιαστεί έτσι ώστε όλες οι λειτουργίες να είναι αντιμεταθετικές: η σειρά εφαρμογής δεν επηρεάζει το τελικό αποτέλεσμα. Αυτό επιτυγχάνεται μέσω αλγεβρικών ιδιοτήτων: η συγχώνευση CRDT δίνει πάντα το ίδιο αποτέλεσμα ανεξάρτητα από τη σειρά λήψης των αλλαγών.
Οι κύριοι τύποι CRDT περιλαμβάνουν το G-Counter (απαριθμητής που υποστηρίζει μόνο αύξηση), το PN-Counter (απαριθμητής με αύξηση και μείωση), το LWW-Register (καταχωριστής με εκδόσεις) και το OR-Set (σύνολο που παρακολουθεί προσθήκες και διαγραφές). Κάθε τύπος εγγυάται ότι κατά τη συγχώνευση δύο αντιγράφων δεν θα προκύψουν συγκρούσεις. Σύμφωνα με την έρευνα INRIA (Marc Shapiro et al., 2024), τα CRDT παρέχουν ντετερμινιστική σύγκλιση για το 95% των συνηθισμένων τύπων δεδομένων.
Παράδειγμα G-Counter — ενός απαριθμητή που μπορεί μόνο να αυξηθεί:
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 εγγυάται την ορθότητα της συγχώνευσης επειδή κάθε κόμβος αποθηκεύει μόνο το δικό του απαριθμητή, και το merge παίρνει το μέγιστο για κάθε κόμβο. Αυτό είναι ένα κλασικό παράδειγμα δομής χωρίς συγκρούσεις, που χρησιμοποιείται σε αποκεντρωμένα συστήματα.
Επιλογή στρατηγικής εξαρτάται από τη φύση των δεδομένων και τα σενάρια χρήσης. Το LWW είναι βέλτιστο για εφαρμογές όπου η πιο πρόσφατη έκδοση έχει πάντα προτεραιότητα — ροή ειδήσεων, ειδοποιήσεις, καταστάσεις. Η Merge Strategy είναι κατάλληλη για δομημένα έγγραφα όπου κάθε πεδίο είναι ανεξάρτητο — προφίλ χρηστών, φόρμες, διαμορφώσεις. Το CRDT είναι ιδανικό για συνεργατική επεξεργασία, λίστες και απαριθμητές σε κατανεμημένα συστήματα.
Κατά την επιλογή στρατηγικής αξιολογούνται τρεις παράγοντες: συνέπεια δεδομένων, απόδοση και πολυπλοκότητα υλοποίησης. Το LWW παρέχει μέγιστη απόδοση και ελάχιστη πολυπλοκότητα, αλλά μπορεί να χάσει δεδομένα. Το Merge παρέχει υψηλή ακρίβεια, αλλά απαιτεί μηχανισμό ανίχνευσης αλλαγών σε επίπεδο πεδίου. Το CRDT εγγυάται μαθηματική ορθότητα, αλλά επιβάλλει περιορισμούς στους τύπους δεδομένων και στο μέγεθος μεταδεδομένων.
| Στρατηγική | Απώλεια δεδομένων | Πολυπλοκότητα | Απόδοση | Παράδειγμα χρήσης |
|---|---|---|---|---|
| LWW | Πιθανή | Χαμηλή | Υψηλή | Ροή ειδήσεων, καταστάσεις |
| Merge | Ελάχιστη | Μεσαία | Μεσαία | Προφίλ, έγγραφα |
| CRDT | Καμία | Υψηλή | Μεσαία-υψηλή | Συνεργατική επεξεργασία |
Στην πράξη, συχνά εφαρμόζεται συνδυαστική προσέγγιση: τα συστήματα χρησιμοποιούν LWW για μεταδεδομένα, Merge για περιεχόμενο εγγράφων και CRDT για δομές λίστας. Η Firebase Firestore, για παράδειγμα, εφαρμόζει LWW για πεδία ανώτατου επιπέδου και υποστηρίζει συναλλαγές για ατομικές ενημερώσεις. Η CouchDB χρησιμοποιεί Merge με αποθήκευση ιστορικού αλλαγών. Η Figma και το Notion χτίζουν αρχιτεκτονική βασισμένη σε CRDT για πολυχρηστική επεξεργασία σε πραγματικό χρόνο.
Συχνές Ερωτήσεις
Επίλυση συγκρούσεων είναι ένας μηχανισμός που καθορίζει ποια έκδοση δεδομένων θεωρείται σωστή κατά τις ταυτόχρονες αλλαγές του ίδιου αντικειμένου σε διαφορετικές συσκευές. Το σύστημα εφαρμόζει μία στρατηγική (LWW, Merge, CRDT) για την επιλογή ή τη σύμπτυξη των εκδόσεων.
LWW επιλέγει μία πλήρη έκδοση βάσει χρονικής σφραγίδας, η άλλη απορρίπτεται. Merge συνδυάζει τις αλλαγές από τις δύο εκδόσεις σε επίπεδο μεμονωμένων πεδίων, που ελαχιστοποιεί την απώλεια δεδομένων, αλλά απαιτεί πιο περίπλοκη υλοποίηση και αποθήκευση της βασικής έκδοσης.
CRDT επιλέγεται για σενάρια όπου η απώλεια δεδομένων είναι απαράδεκτη: συνεργατική επεξεργασία, χρηματοοικονομικές λειτουργίες, λίστες εργασιών. Το LWW είναι επαρκές για μη κρίσιμα δεδομένα — καταστάσεις, ροή ειδήσεων, προσωρινή μνήμη, όπου η πιο πρόσφατη έκδοση είναι αντικειμενικά σωστή.
Λανθασμένη επίλυση συγκρούσεων προκαλεί απώλεια δεδομένων χρήστη, που οδηγεί σε αρνητικές κριτικές και απώλεια χρηστών. Σύμφωνα με έρευνα του University of Washington (2025), το 67% των χρηστών σταματά να χρησιμοποιεί μια εφαρμογή μετά από δύο περιπτώσεις απώλειας πληροφοριών λόγω συγκρούσεων συγχρονισμού.
CouchDB και PouchDB έχουν ενσωματωμένη υποστήριξη για τριμερή συγχώνευση εγγράφων. Firebase Firestore υποστηρίζει συναλλαγές για ατομικές ενημερώσεις. RethinkDB και MongoDB απαιτούν υλοποίηση σε επίπεδο εφαρμογής μέσω του μοτίβου αισιόδοξου κλειδώματος με εκδόσεις.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης