28 Eylül 2026 Pazartesi

Yazılım Mimarisi - Replication Consistency

Giriş
Açıklaması şöyle
The primary replica set up will result in update delay in replicas and is a classic eventual consistency model. Essentially we trade strong consistency for read scalability. Eventual consistency is enough for most applications, except for ones requiring ‘read your write’ consistency.

‘Read your write’ consistency can be improved by forcing the read request to primary if it’s following a write. Or naively force the read to wait for several seconds so that all replicas have caught up. When there are replicas not in the same datacenter(DC), the read will also need to be restricted to the same DC.
Read-your-own-writes consistency 
Farklı çözümler var

1. Route To Master
Açıklaması şöyle
... 
a user updates their profile and doesn't see the change.
...
But there's a catch nobody warns you about: replication lag.

Your replica is 200ms behind master. User changes their avatar, page reloads, reads from replica - old avatar. "Did my update even save?" They click save again. Now you have a duplicate write and a confused user.

The fix is called read-your-own-writes consistency. After a write, route that specific user's reads to master for the next N seconds. Everyone else still reads from replicas. This solves 90% of "my changes disappeared" tickets.

Implementation: set a short-lived cookie or Redis key after a write. Middleware checks it - if present, route to master. If expired, back to replica. Five lines of code that save you hundreds of bug reports.

2. Short TTL Redis Kullanmak
Örnek
Şöyle yaparız
// CORRECT — a user's own recent writes are read from the primary
@Service
@RequiredArgsConstructor
public class ProfileService {
    private final RecentWriteTracker recentWrites; // Redis, short TTL
    @Transactional
    public void updateProfile(Long userId, ProfileRequest request) {
        User user = userRepository.findById(userId).orElseThrow();
        user.applyChanges(request);
        userRepository.save(user);
        recentWrites.mark(userId, Duration.ofSeconds(10)); // Longer than max lag
    }
    public UserProfile getProfile(Long userId) {
        return recentWrites.hasRecentWrite(userId)
            ? readFromPrimary(userId)   // This user just wrote - don't risk the replica
            : readFromReplica(userId);  // Everyone else reads the cheap path
    }
}


Hiç yorum yok:

Yorum Gönder