Aşırı Yüklenen Redis Cache'i Veritabanını Öldürdü
Redis veritabanımızı kurtardı. Onu öldürene kadar.
Ne oldu:
- Trafik sıçraması: tek bir Redis instance'ına saniyede 50K istek
- Bu hız tek başına sorun olmazdı — Redis basit GET/SET işlemlerinde çok daha fazlasını kaldırır — ama biz yüzlerce KB'lık serialize edilmiş nesneler saklıyor ve istek başına birkaç O(N) komut çalıştırıyorduk
- Redis %100 CPU'ya vurdu; yanıt süreleri milisaniyenin altından yüzlerce milisaniyeye çıktı
- İstemci timeout'ları tetiklendi — ve cache istemcimiz her timeout'u cache miss olarak ele aldı
- Saniyede 50K isteğin tamamı thundering herd olarak veritabanına düştü
- Veritabanı 30 saniye içinde öldü
Kök neden:
Birbirini büyüten iki hata. Pahalı payload'ları tek bir sıcak instance'a koyduk ve circuit breaker'ımız yoktu: Redis yavaşladığında “timeout eşittir miss” mantığı yüzünden kontrollü biçimde gerilemek yerine tüm yükü, cache'in korumak için var olduğu tek sisteme yönlendirdik.
Çözüm:
- Circuit breaker deseni: Redis yavaşsa bayat veriyi sun ya da isteği başarısız say — veritabanına düşme
- Cache istemcisinde timeout'ları miss'lerden ayır; yalnızca gerçek miss'ler veritabanını sorgulayabilir
- Yatay ölçekleme için Redis Cluster; daha küçük değerler, sıcak yollarda O(N) komut yok
- Timeout'lu connection pooling ve kapasiteye yaklaşınca load shedding
Yalnızca uygulama katmanını değil cache katmanını da kapasite testinden geçirmek, tam da bu nedenle DevOps ve güvenilirlik projelerimizin standart bir adımıdır.
Ders: Cache'iniz yalnızca bir performans optimizasyonu değildir. Kritik bir bileşendir. Arızalandığında, veritabanınızı yok etmeyi içermeyen bir planınız olmalı.
Bu tür olaylar önlenebilir. AWS Yönetilen Hizmetler ekibimiz müşteri ortamlarını yapay zekâ destekli izleme ve nöbetteki kıdemli mühendislerle 7/24 gözetir — böylece bu tür hikâyeler arşivde kalır.