Eventual Consistency
KonsistensEn consistency model hvor systemet garanterer at alle replicas eventually vil converge til samme værdi hvis ingen nye updates sker.
Beskrivelse
Eventual Consistency er en weak consistency model brugt i distributed systems hvor data repliceres across multiple nodes. I modsætning til strong consistency (hvor alle nodes ser samme data instantly), tillader eventual consistency at forskellige nodes midlertidigt kan have forskellige værdier, men garanterer at hvis ingen nye writes sker, vil alle replicas eventually konvergere til samme state. Dette er en trade-off defineret i CAP theorem - du kan ikke have Consistency, Availability og Partition tolerance samtidig. Eventual consistency vælger Availability og Partition tolerance over immediate consistency. Det betyder systemet kan fortsætte med at fungere selv under network partitions, men læsninger kan returnere stale data. Eventual consistency er fundamentet for mange NoSQL databases (Cassandra, DynamoDB, Riak) og distributed caches. Convergence time kan variere fra millisekunder til sekunder eller længere afhængigt af system load og network conditions. Conflict resolution strategies som Last-Write-Wins, Vector Clocks, eller CRDTs håndterer concurrent updates.
Problem
I distributed systems med replication, hvordan balancerer vi mellem data consistency, system availability, og partition tolerance? Strong consistency kræver at alle replicas synkroniseres før en write returnerer, hvilket giver høj latency og reduceret availability under network issues.
Løsning
Eventual consistency lader writes complete hurtigt ved at acceptere at replicas kan være midlertidigt out-of-sync. Systemet garanterer kun at de eventually vil sync. Dette giver høj availability og lav latency, perfekt til use cases hvor stale reads er acceptable (social media likes, view counts, recommendations).
Eksempel
-- DynamoDB eksempel (eventual consistency)
// Default read er eventually consistent
const params = {
TableName: 'Users',
Key: { userId: '123' }
};
// Eventually consistent read (default, hurtigere)
const result = await dynamodb.get(params).promise();
// Kan læse fra enhver replica - måske stale data
// Strongly consistent read (langsommere)
const consistentResult = await dynamodb.get({
...params,
ConsistentRead: true
}).promise();
// Læser fra primary replica - altid fresh data
-- Cassandra eksempel
// Write med tunable consistency
INSERT INTO users (id, name, email)
VALUES (123, 'Peter', 'peter@email.dk')
USING CONSISTENCY QUORUM; -- Vent på majority
INSERT INTO users (id, name, email)
VALUES (124, 'Maria', 'maria@email.dk')
USING CONSISTENCY ONE; -- Kun vent på én replica (eventual)
// Read med tunable consistency
SELECT * FROM users WHERE id = 123
USING CONSISTENCY ALL; -- Læs fra alle replicas (strong)
SELECT * FROM users WHERE id = 123
USING CONSISTENCY ONE; -- Læs fra én replica (eventual)
-- Scenario der viser eventual consistency
// T0: Initial state
// Replica A: { userId: 123, likes: 100 }
// Replica B: { userId: 123, likes: 100 }
// Replica C: { userId: 123, likes: 100 }
// T1: User likes post (write til Replica A)
// Replica A: { userId: 123, likes: 101 } ✓ updated
// Replica B: { userId: 123, likes: 100 } (pending sync)
// Replica C: { userId: 123, likes: 100 } (pending sync)
// Write returns SUCCESS (eventual consistency)
// T2: Anden user læser fra Replica B
// Ser stadig likes: 100 (stale read!)
// T3: Replication completes
// Replica A: { userId: 123, likes: 101 }
// Replica B: { userId: 123, likes: 101 } ✓ synced
// Replica C: { userId: 123, likes: 101 } ✓ synced
// System er nu eventually consistent
// Conflict resolution med Last-Write-Wins
// T1: User A updates name på Replica 1
UPDATE users SET name = 'Peter Hansen', version = 2
WHERE id = 123;
// T1: User B updates name på Replica 2 (concurrent!)
UPDATE users SET name = 'Peter H', version = 2
WHERE id = 123;
// T2: Replication syncer
// Conflict detected! Begge har version 2
// Last-Write-Wins strategy: Brug timestamp
// Hvis User B's write har nyere timestamp, vinder den
// Final: name = 'Peter H' på alle replicas
-- Vector Clocks for conflict detection
const data = {
value: 'Hello',
vectorClock: {
'replica-A': 1,
'replica-B': 0,
'replica-C': 0
}
};
// Concurrent updates vil have forskellige vector clocks
// System kan detektere conflicts og resolve med strategy
-- Shopping cart eksempel (eventual consistency)
// User tilføjer item til cart på forskellige devices
// Phone (Replica A): adds item X
cart = ['item-X'];
// Laptop (Replica B): simultaneously adds item Y
cart = ['item-Y'];
// Eventual sync med merge strategy:
cart = ['item-X', 'item-Y']; // Union af begge
-- Social media example
// Post likes counter
INCREMENT post_likes WHERE post_id = 456;
// Hver replica tæller lokalt
// Eventually syncs til total count
// Slight inaccuracy er acceptable
-- Redis Cluster eksempel
const redis = require('redis');
const cluster = redis.createCluster({
rootNodes: [
{ host: 'node1' },
{ host: 'node2' },
{ host: 'node3' }
]
});
// Writes går til master
await cluster.set('user:123', JSON.stringify(userData));
// Returns success efter master write
// Replicas syncer asynchronously
// Reads kan komme fra replicas
const data = await cluster.get('user:123');
// Might be slightly stale
-- MongoDB replica set
// Write concern
await collection.insertOne(
{ name: 'Peter' },
{ writeConcern: { w: 1 } } // Eventually consistent (return after primary)
);
await collection.insertOne(
{ name: 'Maria' },
{ writeConcern: { w: 'majority' } } // Stronger (wait for majority)
);
// Read preference
await collection.find().readPref('secondary'); // Eventual (read from secondary)
await collection.find().readPref('primary'); // Strong (read from primary)Fordele
- ✓Høj availability
- ✓Lav latency (writes returnerer hurtigt)
- ✓Partition tolerance
- ✓Skalerbarhed (mange replicas)
- ✓Kan fortsætte under network issues
Udfordringer
- ⚠Stale reads mulige
- ⚠Conflict resolution nødvendig
- ⚠Applikationer skal håndtere inconsistency
- ⚠Debugging kan være svært
- ⚠User experience considerations (stale data)
Anvendelsesområder
- •Social media (likes, follows, comments)
- •E-commerce product catalogs
- •Content delivery networks (CDN)
- •DNS systemer
- •Shopping carts og wishlists
Eksempler fra den virkelige verden
- •Amazon shopping cart (items eventually sync across devices)
- •Facebook likes counter (eventual count acceptable)
- •Twitter follower counts
- •CDN content distribution
- •DynamoDB global tables