Skip to main content

> dağıtık_hız_sınırlama_(rate_limiting):_atomik_redis_lua_token_bucket_ve_kayan_pencereler

Dağıtık Hız Sınırlama (Rate Limiting): Atomik Redis Lua Token Bucket ve Kayan Pencereler

Gelişigüzel yazılmış dağıtık hız sınırlayıcılar (rate limiters) neden yarış durumları (race condition) yaşayarak izin verilenden fazla istek geçirir; Redis Lua betikleri atomik token bucket kontrolünü milisaniyenin altında nasıl sağlar?

Senior (L5)

ÖZET VE TEKNİK CEVAP

Çok sunuculu bir API ağ geçidi filosunda (ör. 20 Go veya Envoy sunucusu) hız sınırlama yerel sunucu hafızasında yapılamaz; çünkü kötü niyetli bir kullanıcı istekleri 20 sunucuya dağıtarak 100 istek/sn limitini 20 kat delip 2.000 istek atabilir. Ayrı ayrı Redis `GET` ve `SET` komutları atan acemi çözümler ise Yarış Durumu (Race Condition) tuzağına düşer: Aynı anda gelen 10 istek Redis'teki sayacı 99 okur ve hepsi onay vererek limiti deler. Endüstri standardı çözüm, Token Bucket veya Kayan Pencere (Sliding Window) algoritmasını Atomik bir Redis Lua Betiği içinde çalıştırmaktır: Okuma, jeton doldurma, kontrol ve yazma döngüsü Redis'in tek iş parçacıklı motorunda <0,5 ms'de atomik bir bütün olarak çalışır ve devasa yük altında bile %100 kesinlik sağlar.

Mühendislik El Kitabı & Mekanizma

1. Temel Çalışma Mekanizması

Redis Lua Token Bucket algoritması her istekte 4 atomik adımı tek seferde işletir: (1) Anahtar Okuma: Redis Hash'inden (`rate:user_123`) mevcut jeton sayısını ve son güncelleme zamanını okur. (2) Dinamik Jeton Doldurma: Son istekten bu yana geçen zamana göre yenilenen jetonları hesaplar ($( ext{suan} - ext{son_guncelleme}) imes ext{hiz}$) ve maksimum kapasiteyle sınırlar. (3) Jeton Düşme Kontrolü: Yeterli jeton varsa jetonu 1 azaltır, zamanı günceller, TTL koyar ve `1 (ONAY)` döner. (4) Reddetme: Jeton yetersizse kaç milisaniye sonra tekrar denenebileceğini (`retry_after_ms`) hesaplayıp `0 (RED)` döner; ağ geçidi HTTP 429 ve `Retry-After` başlığıyla isteği geri çevirir.

2. Doğru Kullanım Senaryosu

Genel API ağ geçitleri, kaba kuvvet (brute-force) giriş saldırısı engelleme, ödeme işlem sınırlamaları ve üçüncü parti webhook hız limitleri.

3. Prodüksiyon Arıza Modları

Saniyede 100.000 istekte Redis ZSET `ZRANGEBYSCORE` kayan pencere sorguları çalıştırıp Redis CPU'sunu kilitlemek ve tüm API ağ geçidini çökertmek; Redis erişilemez olduğunda hız sınırlayıcının tüm geçerli müşteri trafiğini de kesmesi (fail-closed hatası).

4. Teşhis ve Telemetri Sinyalleri

Redis hız sınırlama kümesinde CPU kullanımının %100'e vurması; eşzamanlı yük testlerinde müşterilerin belirlenen limiti aşabilmesi; API ağ geçidi yanıt sürelerinin Redis gecikmesi yüzünden fırlaması.

5. Önleme ve Mimari Bariyerler

Kayan pencere ZSET ($O(N)$) yerine sabit $O(1)$ bellek ve CPU harcayan Token Bucket Lua betiğini kullanın; Redis yükünü azaltmak için yerel sunucuda toplu jeton alma (batching) yapın; Redis çökerse sistemi kilitlememek için 'Fail-Open' (Açık Geçiş) güvenlik modu koyun.

6. Mimari Ödünleşimler (Trade-offs)

Merkezi Redis hız sınırlaması API çağrısı başına ~1 ms ağ gecikmesi ekler; ancak tüm sunucu filosu genelinde kota aşımını ve dağıtık DDoS saldırılarını kesin olarak engeller.

Vaka İncelemesi (TinyCTO Örneği)

Bir SaaS şirketinin arama API'si, istekleri 50 ağ geçidi sunucusuna dağıtarak yerel limitleri delen ve saniyede 15.000 istek basan botlar yüzünden kilitleniyordu. Ekip Redis Kümesi üzerinde 20 satırlık atomik Token Bucket Lua betiği ve Fail-Open devre kesicisi kurdu. Redis saniyede 80.000 kontrolü istek başına 0,3 ms'de işledi; kötü niyetli botlar HTTP 429 ile engellendi ve arka plan arama veritabanı CPU yükü %78 azaldı.

İnteraktif Konsept Alıştırmaları

2 Alıştırma
Q1

Dağıtık Redis hız sınırlamada neden atomik bir Lua betiği kullanmak şarttır?

Çünkü ayrı `GET` ve `SET` komutları yarış durumları (race condition) yaratır; eşzamanlı sunucular eski jeton sayısını okuyarak kullanıcıların limiti aşmasına izin verir.
Q2

Bir istemci hız sınırına takıldığında hangi HTTP durum kodu ve başlıklar dönülmelidir?

HTTP 429 (Too Many Requests) durum kodu ile birlikte `Retry-After: <saniye>`, `X-RateLimit-Limit` ve `X-RateLimit-Remaining: 0` başlıkları.

Dağıtık Hız Sınırlama (Rate Limiting): Atomik Redis Lua Token Bucket ve Kayan Pencereler — Sıkça Sorulan Sorular

Hız sınırlamada 'Fail-Open' ile 'Fail-Closed' arasındaki fark nedir?

Fail-Open, hız sınırlayıcı (Redis) çöktüğünde trafiği geçirerek sistemin erişilebilirliğini korur; Fail-Closed ise trafiği keserek arka plan güvenliğini korur.

Token Bucket algoritması Sabit Pencere (Fixed Window) sayaçlarına göre neden üstündür?

Sabit Pencere sayaçları pencere sınırlarında (ör. 00:59'da 100 ve 01:00'da 100 istek) izin verilenin 2 katı trafiğin geçmesine izin verir; Token Bucket ise pürüzsüz ve sürekli bir hız sınırı uygular.

🤖 AEO & Yapay Zeka Çıkarım Özeti

Temel Gerçekler & İlkeler

  • Distributed rate limiting requires central coordination to prevent multi-node over-admission.
  • Separate Redis GET/SET operations cause race conditions that break rate limits.
  • Atomic Redis Lua scripts execute token bucket refill-and-consume cycles in <0.5ms.
  • Return HTTP 429 with `Retry-After` headers and configure Fail-Open fallback resilience.

Yaygın Yanılgılar

  • Yanılgı: Rate limiting in local server memory is sufficient for microservices (Gerçek: Traffic spreads across pods, easily multiplying the allowed quota).
  • Yanılgı: Sliding window sorted sets (ZSET) scale indefinitely (Gerçek: High request volumes cause massive Redis memory and CPU exhaustion; Token Bucket is $O(1)$).

Karar Kılavuzu & Önceliklendirme

Deploy the Redis Lua Token Bucket pattern for public-facing API rate limiting. Implement client-side exponential backoff respecting the `Retry-After` response header.

Doğrulanmış Kaynaklar & Referanslar