RRedis Handbook

UZMAN

Monitoring & Observability

Production Redis'te neyi izlemeli, nasıl alarm kurmalı.

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

Kritik Metrikler

Metrik Komut Alarm Eşiği Anlamı
Memory usage INFO memoryused_memory >%80 maxmemory Eviction yaklaşıyor
Connected clients INFO clientsconnected_clients >%80 maxclients Connection pool tükeniyor
Fragmentation ratio INFO memorymem_fragmentation_ratio >1.5 veya <1.0 Bellek verimsiz / swap
Hit rate INFO statskeyspace_hits/(hits+misses) <%80 Cache çalışmıyor
Evicted keys INFO statsevicted_keys >0/dk artış Memory yetersiz
Blocked clients INFO clientsblocked_clients >10 BLPOP/BRPOP bekleme
Replication lag INFO replicationmaster_repl_offset - slave_repl_offset >1MB Replica geride
Slowlog SLOWLOG LEN Artan trend Yavaş komutlar
Latency redis-cli --latency >1ms p99 Network/CPU sorunu
# Prometheus exporter (redis_exporter)
docker run -d --name redis-exporter \
  -p 9121:9121 \
  oliver006/redis_exporter \
  --redis.addr=redis://redis:6379

# Key metrics endpoint: http://localhost:9121/metrics
# Grafana dashboard: https://grafana.com/grafana/dashboards/763-redis-dashboard-for-prometheus-redis-exporter/

# Real-time monitoring
redis-cli MONITOR          # TÜM komutları göster (debug, production'da KULLANMA!)
redis-cli INFO ALL         # Tüm section'lar

# Latency tracking (Redis 2.8.13+)
CONFIG SET latency-monitor-threshold 5   # 5ms+ olayları kaydet
LATENCY LATEST
LATENCY HISTORY command
LATENCY RESET
// OpenTelemetry ile Redis tracing
// NuGet: OpenTelemetry.Instrumentation.StackExchangeRedis
builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing
            .AddAspNetCoreInstrumentation()
            .AddHttpClientInstrumentation()
            .AddRedisInstrumentation(options =>
            {
                options.SetVerboseDatabaseStatements = true; // komut detayı
                options.Enrich = (activity, eventName, rawObject) =>
                {
                    if (rawObject is IProfiledCommand cmd)
                    {
                        activity.SetTag("redis.database", cmd.Db);
                        activity.SetTag("redis.flags", cmd.Flags.ToString());
                    }
                };
            })
            .AddOtlpExporter(); // Jaeger, Tempo, etc.
    });

// ConnectionMultiplexer'a profiler ekle
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{
    var mux = ConnectionMultiplexer.Connect(
        builder.Configuration.GetConnectionString("Redis")!);

    // OpenTelemetry profiling hook
    var tracerProvider = sp.GetRequiredService<TracerProvider>();
    mux.RegisterProfiler(
        () => new ProfilingSession());

    return mux;
});
// Custom metrics (Prometheus / OpenTelemetry Metrics)
public class RedisMetricsCollector : BackgroundService
{
    private readonly IConnectionMultiplexer _mux;
    private readonly Meter _meter;
    private readonly ObservableGauge<long> _usedMemory;
    private readonly ObservableGauge<int> _connectedClients;
    private readonly Counter<long> _commandsProcessed;

    public RedisMetricsCollector(IConnectionMultiplexer mux)
    {
        _mux = mux;
        _meter = new Meter("Redis.Monitoring");

        _usedMemory = _meter.CreateObservableGauge("redis.memory.used_bytes",
            () => GetMetric("used_memory"));
        _connectedClients = _meter.CreateObservableGauge("redis.clients.connected",
            () => (int)GetMetric("connected_clients"));
        _commandsProcessed = _meter.CreateCounter<long>("redis.commands.total");
    }

    private long GetMetric(string key)
    {
        try
        {
            var server = _mux.GetServers().First();
            var info = server.Info();
            var section = info.SelectMany(s => s);
            var pair = section.FirstOrDefault(p => p.Key == key);
            return long.TryParse(pair.Value, out var v) ? v : 0;
        }
        catch { return 0; }
    }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            await Task.Delay(TimeSpan.FromSeconds(30), ct);
        }
    }
}

Minimum monitoring stack: redis_exporter + Prometheus + Grafana. Dashboard ID 763 ile 5 dakikada kurulur.

MONITOR komutu production'da KULLANMA. Tüm komutları loglar → Redis throughput'u %50+ düşer. Sadece debug amaçlı, kısa süreli.

PromQL Alert Kuralları

# prometheus/rules/redis-alerts.yml
groups:
  - name: redis.rules
    rules:
      # 1. Memory %80'i aştı — eviction yaklaşıyor
      - alert: RedisMemoryHigh
        expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis memory usage >80% ({{ $labels.instance }})"
          description: "Current: {{ $value | humanizePercentage }}. Eviction başlayabilir."

      # 2. Cache hit rate düştü — cache çalışmıyor
      - alert: RedisCacheHitRateLow
        expr: |
          rate(redis_keyspace_hits_total[5m]) /
          (rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m])) < 0.8
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Redis hit rate <80% ({{ $labels.instance }})"
          description: "Hit rate: {{ $value | humanizePercentage }}. TTL, key pattern veya cache logic kontrol et."

      # 3. Bağlantı sayısı limiti yaklaştı
      - alert: RedisConnectionsHigh
        expr: redis_connected_clients / redis_config_maxclients > 0.8
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Redis connections >80% maxclients ({{ $labels.instance }})"

      # 4. Replication lag yüksek
      - alert: RedisReplicationLag
        expr: redis_replication_backlog_bytes > 1048576
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis replication lag >1MB ({{ $labels.instance }})"