RRedis Handbook

İLERİ

Client-Side Caching (Tracking)

Redis 6+ RESP3 ile server-assisted client caching: Redis, client'ın cache'lediği key'ler değiştiğinde invalidation bildirimi gönderir. Network roundtrip'i tamamen ortadan kaldırır.

Kod örneği görünümü Bu sayfadaki eşleşen örnekleri seçilen istemciye göre gösterir.

Nasıl Çalışır?

  1. Client, CLIENT TRACKING ON ile tracking'i aktifleştirir
  2. Client GET yaptığında Redis hangi key'lerin okunduğunu takip eder
  3. Başka bir client o key'i değiştirdiğinde Redis invalidation mesajı gönderir
  4. Client local cache'den ilgili entry'yi siler → sonraki okuma Redis'e gider
# RESP3 ile tracking aktifleştir
CLIENT TRACKING ON REDIRECT <client-id>

# Broadcasting mode (pattern-based, daha az memory kullanır)
CLIENT TRACKING ON BCAST PREFIX user: PREFIX product:

# Tracking durumu
CLIENT TRACKINGINFO

# Hangi client'lar tracking kullanıyor?
CLIENT LIST
# flags=T → tracking aktif

# Manuel invalidate (test/debug)
CLIENT TRACKING ON
GET user:1001
# Başka terminal:
SET user:1001 "updated"
# İlk terminal invalidation alır
// Client-side caching: IMemoryCache + Redis invalidation
// StackExchange.Redis 2.6.100+ RESP3 tracking desteği sunar
// Ancak tam otomatik client-side cache henüz built-in değil.
// En pratik yaklaşım: Keyspace notifications + IMemoryCache hybrid

public class ClientSideCacheService
{
    private readonly IDatabase _redis;
    private readonly IMemoryCache _localCache;
    private readonly ISubscriber _subscriber;
    private readonly TimeSpan _localTtl = TimeSpan.FromSeconds(30);
    private readonly ILogger<ClientSideCacheService> _logger;

    public ClientSideCacheService(
        IConnectionMultiplexer mux,
        IMemoryCache memoryCache,
        ILogger<ClientSideCacheService> logger)
    {
        _redis = mux.GetDatabase();
        _localCache = memoryCache;
        _subscriber = mux.GetSubscriber();
        _logger = logger;
        SubscribeToInvalidations();
    }

    private void SubscribeToInvalidations()
    {
        // Keyspace notifications ile invalidation
        // redis.conf: notify-keyspace-events KEA
        _subscriber.Subscribe(
            RedisChannel.Pattern("__keyevent@0__:*"),
            (channel, key) =>
            {
                var eventType = channel.ToString().Split(':').Last();
                if (eventType is "set" or "del" or "expire" or "expired")
                {
                    _localCache.Remove(key.ToString());
                    _logger.LogDebug("Local cache invalidated: {Key} ({Event})",
                        key, eventType);
                }
            });
    }

    // L1 (local) → L2 (Redis) stratejisi
    public async Task<T?> GetAsync<T>(string key) where T : class
    {
        // L1: Memory cache (0 latency)
        if (_localCache.TryGetValue(key, out T? local))
            return local;

        // L2: Redis
        var value = await _redis.StringGetAsync(key);
        if (!value.HasValue) return null;

        var result = JsonSerializer.Deserialize<T>(value!);
        if (result is not null)
        {
            // L1'e yaz — invalidation gelene kadar geçerli
            _localCache.Set(key, result, _localTtl);
        }
        return result;
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan ttl)
    {
        await _redis.StringSetAsync(key,
            JsonSerializer.Serialize(value), ttl);
        // Local cache'i güncelle (kendi yazdığımızı biz biliriz)
        _localCache.Set(key, value, _localTtl);
    }
}
// DI kayıt
builder.Services.AddMemoryCache();
builder.Services.AddSingleton<ClientSideCacheService>();

// redis.conf'ta keyspace notification aktifleştir:
// notify-keyspace-events KEA
Yaklaşım Latency Tutarlılık Memory Kullanım
Sadece Redis ~0.5ms Güçlü 0 client Çoğu uygulama
L1+L2 (invalidation) ~0 (hit) Eventual (~ms) Client RAM Hot key protection
L1+L2 (short TTL) ~0 (hit) Eventual (TTL kadar) Client RAM Basit, notification gerekmez
RESP3 Tracking (native) ~0 (hit) Güçlü Server tracks SE.Redis 2.8+ (gelişmekte)

Keyspace notifications overhead: Çok sayıda key değişimiyle notification volume artabilir. Pattern ile filtrele veya BCAST mode kullan.

Ne zaman kullan: Saniyede >10K okuma yapılan hot key'ler, read/write oranı >10:1 olan veriler. Her key için kullanma — sadece hot data.