System Design

Eventual Consistency

Eventual Consistency — distributed systemda ma’lumot darhol emas, balki vaqt o’tishi bilan bir xil bo’ladi.

Strong vs Eventual Consistency

Strong Consistency

Write → Node 1
Wait for all nodes sync 
Return success
→ All reads see new value immediately

Latency: Yuqori (sync kutish)
Availability: Past (node down = write fail)

Eventual Consistency

Write → Node 1 
Return success (immediately)
Background sync → Node 2, Node 3
→ Eventually all nodes have new value

Latency: Past (no wait)
Availability: Yuqori (single node yetarli)

Real-world Misol

DNS

1. Domain yangilanadi: example.com → 1.2.3.4
2. Immediately qaytadi 
3. DNS servers dunyo bo'ylab 24-48 soat ichida yangilanadi

Eventual consistency: 48 soat.

Social Media

Ali posts → "Hello world"
Time 0s: Post saved
Time 0.5s: Vali refresh → post yo'q 
Time 2s: Vali refresh → post ko'rinadi 

Eventual consistency: 2 sekund.

Conflict Resolution

Muammo: Ikki node bir vaqtda o’zgartiradi.

Node 1: profile.bio = "Backend dev"
Node 2: profile.bio = "Frontend dev"
(same time, concurrent writes)

Conflict! 

1. Last Write Wins (LWW)

// Timestamp-based
{
  value: "Backend dev",
  timestamp: 1704067200000
}

{
  value: "Frontend dev",
  timestamp: 1704067201000 // 1s later
}

// Winner: "Frontend dev" 

Oddiy
Data loss (birinchi write yo’qoladi)

2. Version Vectors

// Har bir node o'z versionini track qiladi
Node1: { v1: 1, v2: 0 } → "Backend dev"
Node2: { v1: 0, v2: 1 } → "Frontend dev"

// Merge qilishda ikkalasi ham ko'rinadi
Conflict detected → Manual resolution

3. CRDTs (Conflict-free Replicated Data Types)

// Mathematical merge
const set1 = new Set(['redis', 'postgres']);
const set2 = new Set(['postgres', 'mongo']);

// Union (automatic merge)
const merged = union(set1, set2);
// → ['redis', 'postgres', 'mongo'] 

Automatic merge
Limited data types

4. Application-level Resolution

// Store both versions, user chooses
{
  conflicts: [
    { value: "Backend dev", source: "node1" },
    { value: "Frontend dev", source: "node2" }
  ]
}

// UI: "Which one to keep?"

Quorum Consensus

Distributed systemda ko’pchilik (majority) yetarli:

N = 3 nodes
W = 2 (write quorum)
R = 2 (read quorum)

W + R > N → Strong consistency
W + R ≤ N → Eventual consistency

Example: Cassandra

-- Strong consistency
CONSISTENCY QUORUM; -- 2/3 nodes

-- Eventual consistency  
CONSISTENCY ONE; -- 1/3 nodes

Read Repair

Eventual consistency’ni tezlashtirish:

Read request → Node 1, Node 2, Node 3
Node 1: value = 100 (latest)
Node 2: value = 50  (stale)
Node 3: value = 50  (stale)

Return 100 to client 
Background: Update Node 2 & 3 → 100

Anti-entropy

Background process ma’lumotlarni sync qiladi:

Every 10 minutes:
- Compare hashes
- Identify differences
- Sync stale data

Merkle Trees:

Root hash represents entire dataset
Compare roots → fast check
Different? → Drill down to find differences

Vector Clocks

// Track causality
{
  value: "Hello",
  vectorClock: {
    node1: 5,
    node2: 3,
    node3: 2
  }
}

// Next write on node1:
{
  value: "Hello world",
  vectorClock: {
    node1: 6, // Incremented
    node2: 3,
    node3: 2
  }
}

Detect:

Practical Examples

DynamoDB

// Eventual consistency (default)
const item = await dynamodb.get({
  TableName: 'Users',
  Key: { id: 123 },
  ConsistentRead: false // May be stale
});

// Strong consistency
const item = await dynamodb.get({
  TableName: 'Users',
  Key: { id: 123 },
  ConsistentRead: true // Always fresh
});

Cassandra

-- Eventual
SELECT * FROM users WHERE id = 123;
-- CONSISTENCY ONE (default)

-- Strong
CONSISTENCY QUORUM;
SELECT * FROM users WHERE id = 123;

MongoDB

// Eventual (read from secondary)
db.users.find({ id: 123 }).readPref('secondary');

// Strong (read from primary)
db.users.find({ id: 123 }).readPref('primary');

Best Practices

1. Tolerate staleness

// Good: Social feed (stale OK)
const posts = await cache.get('feed');

// Bad: Bank balance (stale = problem)
const balance = await cache.get('balance'); // NO!

2. Idempotent operations

// Idempotent (safe to retry)
UPDATE users SET status = 'active' WHERE id = 123;

// Not idempotent
UPDATE users SET balance = balance + 100 WHERE id = 123;
// Retry = double credit!

3. Conflict-free design

// Conflict-prone
profile.bio = "Backend dev"
profile.bio = "Frontend dev"

// Append-only (no conflict)
skills.add("Backend")
skills.add("Frontend")

4. Monitor lag

const lag = Date.now() - lastSyncTime;
if (lag > 5000) {
  console.warn('Replication lag > 5s');
}

Trade-offs

Strong ConsistencyEventual Consistency
LatencyHighLow
AvailabilityLowerHigher
ComplexityLowerHigher
Use caseBanking, inventorySocial, analytics

Xulosa

Eventual Consistency:

Conflict Resolution:

When to use:

Keyingi dars: Message Queues asoslari.