Redis ve Önbellekleme (Caching)

Yazılım mimarisinde Redis ve bellek içi önbellekleme (In-Memory Caching) nedir? Cache-Aside, Write-Through stratejileri, TTL yönetimi ve milisaniyelik yanıt.

Yozel

12 dakika

Redis ve Önbellekleme (Caching)
İçindekiler (19)

Modern yüksek trafikli web ve mobil uygulamalarda kullanıcı deneyimini belirleyen en kritik metrik yanıt süresidir (response latency). Bir e-ticaret sitesinin ana sayfasında, popüler bir ürün detayında veya finansal bir döviz kuru ekranında saniyede 100.000 kullanıcı aynı veriyi görüntülemek istediğinde, her istek için ilişkisel veritabanına (PostgreSQL, MySQL, Oracle) gidip karmaşık SQL JOIN sorguları çalıştırmak donanım kaynaklarını saniyeler içinde tüketir ve sistemi kilitler. İşte disk tabanlı veritabanlarının fiziksel hız sınırlarını aşarak sık erişilen verileri doğrudan sunucunun ana belleğinde (RAM) tutan ve yanıt sürelerini yüzlerce milisaniyeden 1 milisaniyenin altına (sub-millisecond) indiren mimari katmana Önbellekleme (Caching), bu katmanın dünyadaki tartışmasız endüstri standardına ise Redis adı verilir.

Günümüzde Uygulama ve Yazılım dünyasında mikroservis mimarilerinden gerçek zamanlı oyun sunucularına, yapay zeka vektör aramalarından dağıtık kilit (distributed lock) mekanizmalarına kadar her yüksek performanslı sistem Redis kullanır. Bu kapsamlı mühendislik rehberinde; RAM ile SSD arasındaki donanım gecikme fiziğini, Redis'in tek iş parçacıklı (single-threaded) olay döngüsü mimarisini, ileri seviye veri yapılarını, Cache-Aside ve Write-Through stratejilerini, Cache Stampede (Önbellek İzdihamı) felaketini önleme yollarını ve bellek tahliye (Eviction) politikalarını tüm detaylarıyla inceliyoruz.

1. Neden Bellek İçi Önbellekleme (In-Memory Caching)? Donanım Gecikme Fiziği

İlişkisel bir veritabanını ne kadar iyi indekslerseniz indeksleyin ve altında ne kadar hızlı NVMe SSD diskler çalıştırırsanız çalıştırın, fizik kuralları değişmez. Bilgisayar mimarisinde işlemcinin (CPU) farklı depolama katmanlarına erişim süreleri arasında devasa uçurumlar vardır:

  • L1 / L2 CPU Önbellek Erişimi: ~0.5 ile 7 nanosaniye
  • Ana Bellek (RAM) Erişimi: ~100 nanosaniye (0.1 mikrosaniye)
  • Modern NVMe SSD Disk I/O Erişimi: ~100.000 nanosaniye (100 mikrosaniye - 1 milisaniye)
  • Karmaşık İlişkisel Veritabanı Sorgusu (Ağ + Disk + Ayrıştırma): ~5 ile 150 milisaniye

Görüldüğü üzere, ana bellekten (RAM) veri okumak, en hızlı SSD diskten veri okumaktan bile yaklaşık 1.000 kat daha hızlıdır. Üstelik çoğu uygulamada trafik dağılımı Pareto İlkesine (80/20 Kuralı) uyar: Sistemdeki toplam okuma (Read) trafiğinin %80'i hatta %90'ı, veritabanındaki verilerin yalnızca %10'luk popüler bir alt kümesine (günün fırsat ürünleri, son dakika haberleri, aktif kullanıcı oturumları, kategori ağaçları) yönelir. Bu %10'luk sıcak veriyi (Hot Data) RAM üzerinde çalışan Redis'te tutmak, ana veritabanının yükünü %90 oranında azaltarak sistemin ek sunucu maliyeti olmadan 10 kat daha fazla kullanıcıya hizmet vermesini sağlar.

2. Redis Nedir ve Neden Bu Kadar Hızlıdır?

Salvatore Sanfilippo (antirez) tarafından 2009 yılında geliştirilen Redis (Remote Dictionary Server), açık kaynaklı (ve ekosistemi Valkey, Dragonfly gibi türevlerle de genişleyen), bellek içi (in-memory) çalışan bir anahtar-değer (key-value) veri yapısı sunucusudur. Redis'in tek bir sunucu çekirdeğinde saniyede 100.000 ile 500.000 arasında işlemi (OPS) <1 ms gecikmeyle tamamlayabilmesinin arkasında dört temel mühendislik sırrı yatar:

  1. Tamamen RAM Üzerinde Çalışması: Tüm okuma ve yazma işlemleri disk I/O darboğazına takılmadan doğrudan C diliyle optimize edilmiş RAM bellek blokları üzerinde gerçekleşir.
  2. Single-Threaded Event Loop ve I/O Multiplexing (epoll/kqueue): Birçok geliştiriciyi şaşırtan bir gerçek olarak, Redis'in ana komut işleme motoru tek iş parçacıklı (single-threaded) çalışır! Çok iş parçacıklı (multi-threaded) sistemlerde işlemci zamanının önemli bir kısmı thread'ler arası bağlam değiştirme (Context Switching) ve aynı veriye erişirken oluşan kilitlenme (Mutex / Lock Contention) beklemeleriyle harcanır. Redis ise işletim sisteminin epoll (Linux) veya kqueue (macOS/BSD) asenkron ağ çoklama mekanizmasını kullanarak binlerce istemci bağlantısını sıfır kilitlenme (lock-free) ve atomik işlem garantisiyle tek bir olay döngüsünde sırayla eritir. (Redis 6+ sürümleriyle birlikte ağ soket okuma/yazma işlemleri çoklu thread ile hızlandırılmış, ancak komut yürütme atomikliği korunmuştur.)
  3. Optimize Edilmiş Alt Seviye Veri Yapıları: Redis, verileri standart C dizileri yerine Simple Dynamic Strings (SDS), Skiplist (Atlama Listesi), Ziplist / Listpack ve Hash Table gibi algoritmik karmaşıklığı O(1) veya O(log N) olan özel veri yapılarında saklar.
  4. RESP (Redis Serialization Protocol): İstemci ile sunucu arasında HTTP gibi ağır başlıklar (headers) içeren bir protokol yerine, ayrıştırılması (parsing) işlemciyi hiç yormayan ultra hafif ikili/metin tabanlı TCP protokolü (RESP) kullanılır.

3. Redis Veri Yapıları: Sadece Basit Bir Key-Value Değil!

Geleneksel Memcached gibi önbellek araçları yalnızca düz metin (String) saklayabilirken, Redis'i "Veri Yapısı Sunucusu" yapan özelliği, karmaşık programlama veri yapılarını doğrudan bellek üzerinde yerel komutlarla işleyebilmesidir:

  • Strings (Metin ve Sayaçlar): JSON nesneleri, HTML parçacıkları veya INCR / DECR atomik komutlarıyla saniyede yüz binlerce kez artırılan sayfa görüntülenme sayaçları ve API hız sınırlama (Rate Limiting) anahtarları için kullanılır.
  • Hashes (Sözlük / Nesne Alanları): Bir kullanıcının profilini veya alışveriş sepetini tek bir JSON metni olarak saklayıp her küçük değişiklikte tüm metni tekrar yazmak yerine, HSET user:1042 name "Ahmet" balance 500 şeklinde sadece ilgili alanı O(1) sürede güncellemek için idealdir. Özellikle Composable Commerce (Birleştirilebilir Ticaret) mimarilerinde sepet (cart) mikroservisleri doğrudan Redis Hash yapıları üzerinde çalışır.
  • Lists (Bağlı Listeler): LPUSH ve RPOP komutlarıyla basit iş kuyrukları veya sosyal medya zaman akışlarındaki "Son 100 Gönderi" listesini tutmak için kullanılır.
  • Sets ve Sorted Sets (ZSET - Sıralı Kümeler): Redis'in en güçlü silahlarından biridir. ZSET, her elemana bir puan (score) atayarak elemanları her zaman otomatik sıralı tutar (Skiplist). Çok oyunculu oyunlarda milyonlarca oyuncunun bulunduğu Gerçek Zamanlı Liderlik Tablosu (Leaderboard) oluşturmak ve bir oyuncunun sıralamasını (ZRANK) milisaniyede bulmak veya Sliding Window Rate Limiter kurgulamak ZSET ile tek satırlık bir işlemdir.
  • Bitmaps, HyperLogLogs ve Geospatial: Milyonlarca kullanıcının günlük aktiflik durumunu (DAU) sadece birkaç kilobaytlık bit dizisinde (Bitmap) tutmak, tekil ziyaretçi sayısını (Unique Visitors) sadece 12 KB bellek harcayarak %99.2 doğrulukla tahmin etmek (HyperLogLog) veya "Bana en yakın 5 km içindeki kuryeleri bul" (GEOSEARCH) sorgusunu çalıştırmak doğrudan Redis içinde yerleşiktir.

4. Önbellekleme Stratejileri (Caching Patterns): Hangi Desen Ne Zaman Kullanılır?

Uygulama katmanı, Redis ve ana veritabanı (Database) arasındaki veri okuma ve yazma koreografisi 4 temel mimari desenle yönetilir:

Cache-Aside Write-Through ve Write-Behind Önbellekleme Stratejileri
Cache-Aside (Lazy Loading), Write-Through ve Write-Behind stratejileri okuma hızı ile veri tutarlılığı arasındaki dengeyi belirler.

4.1. Cache-Aside (Lazy Loading / Tembel Yükleme - En Yaygın Model)

Uygulama önce Redis'e bakar: Eğer veri Redis'te varsa (Cache Hit) doğrudan döner. Eğer veri Redis'te yoksa (Cache Miss), uygulama ana veritabanına gider, veriyi SQL ile çeker, bir sonraki istekler için belirli bir yaşam süresiyle (TTL - Time To Live, örn: 300 saniye) Redis'e yazar ve kullanıcıya döner. Veri güncellendiğinde ise uygulama veritabanını günceller ve Redis'teki eski anahtarı siler (Cache Invalidation). Yalnızca gerçekten talep edilen veriler belleğe yüklendiği için RAM israfını önler.

4.2. Read-Through ve Write-Through (Doğrudan Geçişli Yazma)

Write-Through deseninde uygulama her veri güncellemesini önce (veya aynı anda) hem Redis'e hem de veritabanına yazar. Böylece önbellekteki veri asla bayatlamaz (stale data oluşmaz) ve ilk okuma isteğinde Cache Miss yaşanmaz. Ancak her yazma işlemi iki sisteme birden yapıldığı için yazma gecikmesi (write latency) artar ve bir kez yazılıp bir daha hiç okunmayacak veriler de bellekte yer kaplar.

4.3. Write-Behind (Write-Back / Arkadan Asenkron Yazma)

Yazma trafiğinin aşırı yüksek olduğu senaryolarda (örneğin bir videonun beğeni sayacı veya IoT sensör verileri) uygulama veriyi yalnızca Redis'e yazar ve kullanıcıya anında başarılı yanıt döner. Arka planda çalışan bir işçi süreç, Redis'te biriken bu değişiklikleri her 5 saniyede bir toplu halde (Batch Insert/Update) ana veritabanına yazar. Muazzam bir yazma performansı sağlar ancak veritabanına yazılmadan önce tüm Redis kümesi enerjisini kaybederse birkaç saniyelik veri kaybı riski taşır.

Önbellekleme Deseni Okuma Performansı Yazma Performansı Veri Tutarlılığı En Uygun Kullanım Senaryosu
Cache-Aside (Lazy) Çok Yüksek (İlk istek hariç) Yüksek (DB yaz + Cache sil) Orta-Yüksek (TTL + Invalidation) Genel amaçlı e-ticaret, ürün katalogları, CMS ve API yanıtları
Write-Through Maksimum (Her zaman sıcak) Düşük (Çift senkron yazma) Çok Yüksek Bankacılık bakiyeleri, stok adetleri, sık okunan kullanıcı profilleri
Write-Behind (Back) Maksimum Ultra Yüksek (RAM hızında) Nihai Tutarlılık (Eventual) Görüntülenme/Beğeni sayaçları, oyun içi skorlar, analitik telemetri
Refresh-Ahead Maksimum (Sıfır Miss) Orta (Arka plan yenileme) Yüksek Canlı döviz kurları, borsa endeksleri, ana sayfa vitrin blokları

5. Üretim Ortamı Felaketleri: Cache Stampede, Penetration ve Avalanche

Bilgisayar bilimci Phil Karlton'ın meşhur sözüyle: "Bilgisayar bilimlerinde yalnızca iki zor şey vardır: Önbellek geçersiz kılma (Cache Invalidation) ve şeylere isim vermek." Yüksek trafikli bir sistemde önbellek katmanını yanlış yönetmek üç büyük üretim felaketine yol açabilir:

Cache Stampede Thundering Herd Önleme ve Dağıtık Kilit Redlock Mimarisi
Cache Stampede (Önbellek İzdihamı) durumunda süresi dolan popüler bir anahtar için binlerce paralel isteğin veritabanına hücum etmesi Mutex Lock veya Jitter ile engellenir.

5.1. Cache Stampede (Thundering Herd / Önbellek İzdihamı)

Ana sayfadaki çok popüler bir kampanya listesinin Redis TTL süresinin (örneğin 60 dakika) tam dolduğu saniyede sitede 10.000 aktif kullanıcı olduğunu düşünün. Milisaniyeler içinde gelen 10.000 isteğin tamamı Redis'e bakar, anahtarın silindiğini görür (Cache Miss) ve 10.000 isteğin tamamı aynı anda PostgreSQL veritabanına ağır SQL sorgusu gönderir! Veritabanı CPU'su %100'e vurur ve tüm sistem çöker.
Çözüm:
1. Distributed Mutex Lock (Dağıtık Kilit / Singleflight): Cache Miss olduğunda yalnızca ilk gelen 1 istek Redis üzerinde kısa süreli bir kilit (SET lock:key true NX PX 5000) alır ve veritabanına gider; diğer 9.999 istek 50 ms bekleyip ilk isteğin doldurduğu önbelleği okur.
2. Logical Expiration / Stale-While-Revalidate: Anahtar fiziksel olarak silinmez; süresi yaklaştığında arka planda tek bir thread veriyi sessizce yenilerken kullanıcılara mevcut veri sunulmaya devam eder.

5.2. Cache Penetration (Önbellek Delinmesi - Olmayan Veri Saldırısı)

Kötü niyetli bir saldırganın veya hatalı bir botun veritabanında hiç var olmayan ID'leri (product?id=-999991, id=-999992) saniyede binlerce kez sorgulamasıdır. Veri veritabanında olmadığı için Redis'e de hiçbir zaman yazılmaz ve her istek doğrudan veritabanını vurur.
Çözüm: Veritabanında bulunamayan kayıtlar için Redis'e kısa TTL süreli (örn: 60 sn) NULL veya boş nesne yazmak (Negative Caching) ya da Redis önünde bir Bloom Filter kullanarak bir ID'nin veritabanında var olup olamayacağını O(1) sürede bellekten doğrulamaktır.

5.3. Cache Avalanche (Önbellek Çığı)

Uygulama ilk ayağa kalktığında 100.000 ürünün tamamını Redis'e tam TTL = 3600 saniye (1 saat) ile yüklerseniz, tam 1 saat sonra aynı saniyede 100.000 anahtarın tamamı aynı anda silinir ve veritabanı çığ altında kalır.
Çözüm (TTL Jitter): Sabit TTL vermek yerine her anahtarın süresine rastgele bir sapma (Jitter) eklenir: TTL = 3600 + random(0, 600) saniye. Böylece anahtarların silinme zamanı 10 dakikalık bir zamana yayılır.

6. Bellek Tahliye Politikaları (Eviction Policies) ve Kalıcılık (RDB vs. AOF)

Sunucunuzun RAM kapasitesi sınırlıdır (örneğin 32 GB). Redis'e ayrılan bellek (maxmemory) tamamen dolduğunda yeni gelen veriye yer açmak için hangi eski verinin silineceğini Eviction Policy belirler:

  • allkeys-lru (Least Recently Used): En uzun süredir kullanılmayan (erişilmeyen) anahtarları siler. Genel önbellekleme için en güvenli standarttır.
  • allkeys-lfu (Least Frequently Used): Erişim sıklığı (frekansı) en düşük olan anahtarları siler. Sadece bir kez okunup bırakılan verilerin belleği işgal etmesini önlemede LRU'dan daha başarılıdır.
  • volatile-lru / volatile-ttl: Yalnızca üzerinde TTL (son kullanma tarihi) tanımlı olan anahtarlar arasından seçim yaparak siler; oturum veya kalıcı konfigürasyon gibi TTL'siz anahtarlara dokunmaz.
  • noeviction: Hiçbir veriyi silmez; bellek dolduğunda yazma isteklerine OOM (Out of Memory) hatası döner (Redis birincil veritabanı veya mesaj kuyruğu olarak kullanıldığında tercih edilir).

Ayrıca Redis yeniden başlatıldığında RAM'deki verilerin sıfırlanmaması için iki kalıcılık (Persistence) mekanizması sunar: Belirli aralıklarla belleğin sıkıştırılmış fotoğrafını diske kaydeden RDB (Redis Database Snapshot) ve her yazma komutunu diske sıralı günlük olarak ekleyen AOF (Append-Only File). Kurumsal sistemlerde hem hızlı kurtarma hem de minimum veri kaybı için RDB + AOF hibrit modu ve Redis Sentinel / Redis Cluster yüksek erişilebilirlik mimarisi kullanılır. Özellikle eski monolitik veritabanı sorgularını analiz edip önbellek katmanına taşırken yapay zeka destekli tersine mühendislik ve APM araçları darboğaz yaratan yavaş sorguları otomatik tespit eder.

7. Dağıtık Kilit (Distributed Lock - Redlock) ve Oturum Yönetimi

Yatayda ölçeklenmiş 10 farklı sunucu kopyası (pod) üzerinde çalışan bir mikroservis mimarisinde, iki sunucunun aynı anda aynı koltuğu iki farklı müşteriye satmasını veya aynı zamanlanmış görevi (Cron Job) iki kez çalıştırmasını nasıl engellersiniz? Tek bir sunucu içindeki synchronized veya lock blokları dağıtık sunucular arasında işe yaramaz. İşte burada Redis'in atomik SET resource_name my_random_value NX PX 30000 komutu ve Redlock algoritması devreye girerek tüm mikroservis kümesi genelinde milisaniyelik Dağıtık Kilit (Distributed Lock) sağlar. Benzer şekilde hem Web3 RPC düğüm önbelleklerinde hem de No-Code B2B bayi portallerinin merkezi oturum (Session) ve JWT kara liste (Token Revocation) yönetiminde Redis vazgeçilmez katmandır.

Sıkça Sorulan Sorular (SSS)

1. Redis ile Memcached arasındaki temel fark nedir?

Memcached yalnızca basit metin (String) saklayabilen çok iş parçacıklı saf bir önbellektir. Redis ise Hash, List, Set, Sorted Set, Stream, Geospatial gibi zengin veri yapılarını destekleyen, disk kalıcılığı (RDB/AOF), Pub/Sub mesajlaşma, Lua script çalıştırma ve Cluster/Replication yeteneklerine sahip çok yönlü bir bellek içi veri platformudur.

2. Redis çökerse ana veritabanım da çöker mi?

Eğer uygulamanızda Circuit Breaker (Devre Kesici) ve hız sınırlama önlemleri yoksa, Redis'in aniden devre dışı kalması tüm okuma trafiğinin aynı anda ana veritabanına yönelmesine ve veritabanının aşırı yükten çökmesine neden olabilir. Bunu önlemek için Redis Cluster ile yedekli (Master-Replica) mimari kurulmalı ve uygulama içinde yerel önbellek (In-Process L1 Cache - örn: Caffeine) ile Redis (L2 Distributed Cache) birlikte kullanılmalıdır.

3. Redis'te bir anahtara (Key) ne kadar TTL süresi vermeliyim?

TTL süresi verinin iş doğasına bağlıdır: Canlı borsa/döviz verileri için 1-5 saniye, e-ticaret ürün fiyatları ve stokları için 1-5 dakika (veya olay bazlı anında silme), kategori ağaçları ve blog yazıları için 1-24 saat idealdir. TTL tanımlanmayan anahtarlar bellekte unutularak zamanla RAM sızıntısına (memory leak) yol açar.

4. Redis tek başına birincil veritabanı (Primary Database) olarak kullanılabilir mi?

RDB ve AOF kalıcılığı sayesinde küçük veri setlerinde mümkün olsa da, RAM maliyeti SSD diske göre çok yüksek olduğu ve karmaşık ilişkisel sorgular / ACID işlemleri gerekebileceği için kurumsal mimarilerde Redis birincil veritabanı (PostgreSQL/MongoDB) ile birlikte hızlandırıcı önbellek ve durum katmanı olarak konumlandırılır.

5. Valkey ve Dragonfly nedir, Redis ile uyumlu mudur?

Redis'in 2024 yılındaki lisans değişikliği sonrasında Linux Foundation çatısı altında AWS, Google ve Oracle desteğiyle açık kaynaklı (BSD) olarak çatallanan (fork) resmi topluluk sürümüne Valkey adı verilmiştir. Dragonfly ise modern çok çekirdekli sunucular için sıfırdan yazılmış yüksek performanslı bir alternatiftir. Her ikisi de mevcut Redis istemci kütüphaneleri ve komutlarıyla %100 uyumlu çalışır.

Paylaş

Yozel

Codex haberleri en az iki bağımsız kaynakla doğrulanır; düzeltmeler yazının altında tarih ve saatle belirtilir. Yayın ilkelerimiz