Node.js İle Redis Kullanarak Önbellekleme Sistemi Nasıl Yapılır?

Node.js İle Redis Kullanarak Önbellekleme Sistemi Nasıl Yapılır?
Node.js İle Redis Kullanarak Önbellekleme Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Uygulamaya başlamadan önce sisteminizde gerekli araçların kurulu olduğundan emin olmalısınız. Redis, verileri RAM üzerinde tuttuğu için disk tabanlı veritabanlarına göre çok daha hızlıdır.

  • Node.js (LTS sürümü, 2026 itibarıyla 22.x veya üzeri önerilir).
  • Redis Server (Yerel makinede veya Docker konteynerinde).
  • NPM (Node Package Manager) veya Yarn.
  • Temel Express.js bilgisi.

Redis'i yerel ortamınızda Docker ile hızlıca başlatmak için aşağıdaki komutu terminalinizde çalıştırabilirsiniz:

docker run --name redis-cache -p 6379:6379 -d redis

Bu komut, 6379 portunda bir Redis örneği başlatır ve uygulamanızın bu port üzerinden Redis ile haberleşmesini sağlar.

Redis İstemcisini Node.js Projesine Dahil Etme

Node.js uygulamalarında Redis ile iletişim kurmak için redis kütüphanesini kullanacağız. Bu kütüphane, Redis komutlarını asenkron (Promise tabanlı) bir şekilde çalıştırmamıza olanak tanır.

npm install redis

Kurulum tamamlandıktan sonra, Redis bağlantısını yöneten bir modül oluşturalım. Bu, uygulamanızın her yerinde bağlantı açıp kapatmak yerine merkezi bir yönetim sağlar.

const redis = require('redis');

const client = redis.createClient({
  url: 'redis://localhost:6379'
});

client.on('error', (err) => console.log('Redis Bağlantı Hatası:', err));

async function connectRedis() {
  await client.connect();
  console.log('Redis sunucusuna başarıyla bağlandı.');
}

connectRedis();

module.exports = client;

Burada createClient fonksiyonu ile bağlantı yapılandırmasını tanımladık. client.connect() ile bağlantıyı başlattık. Hata yönetimi için on('error') dinleyicisini eklemek, uygulamanın çökmesini engellemek adına kritiktir.

Önbellekleme Stratejisi: Cache-Aside Modeli

Önbellekleme sistemlerinde en yaygın kullanılan yöntem Cache-Aside (Kenara Bırak) modelidir. Bu modelde uygulama, önce veriyi Redis'te arar. Eğer veri varsa (Cache Hit), doğrudan döner. Eğer yoksa (Cache Miss), veritabanından veriyi alır, Redis'e yazar ve kullanıcıya döner.

async function getUserData(userId) {
  const cacheKey = `user:${userId}`;
  
  // 1. Redis'te kontrol et
  const cachedData = await client.get(cacheKey);
  if (cachedData) {
    return JSON.parse(cachedData);
  }

  // 2. Redis'te yoksa veritabanından çek (Örnek fonksiyon)
  const userData = await database.findUserById(userId);

  // 3. Redis'e kaydet (1 saatlik TTL - Time To Live)
  await client.setEx(cacheKey, 3600, JSON.stringify(userData));

  return userData;
}

Yukarıdaki kodda setEx metodu kullanılmıştır. Bu metod, veriyi kaydederken aynı zamanda bir yaşam süresi (TTL) belirler. 3600 saniye sonra bu veri Redis'ten otomatik silinir, böylece veritabanı güncellendiğinde eski verinin kalması engellenir.

Önbellekleme Yöntemlerinin Karşılaştırılması

Yöntem Avantaj Dezavantaj
Cache-Aside Basit, veritabanı ile uyumlu İlk sorguda gecikme (Cache Miss)
Write-Through Veri her zaman tutarlı Yazma işlemlerinde yavaşlama
Refresh-Ahead Sıfır gecikme Karmaşık yapı, gereksiz kaynak kullanımı

Veri Tutarlılığı ve TTL Yönetimi

Önbellekleme sistemindeki en büyük zorluk, veritabanındaki veri değiştiğinde önbellekteki verinin güncel kalmasıdır. Buna Cache Invalidation denir. Veri güncellendiğinde, ilgili anahtarı Redis'ten silmek en güvenli yoldur.

async function updateUserData(userId, newData) {
  // 1. Veritabanını güncelle
  await database.updateUser(userId, newData);

  // 2. Redis'teki eski veriyi geçersiz kıl (sil)
  await client.del(`user:${userId}`);
}

Bu yaklaşım, veritabanı ve önbellek arasındaki tutarsızlığı minimize eder. Silme işlemi, bir sonraki okuma isteğinde verinin veritabanından tekrar çekilip güncel haliyle önbelleğe alınmasını sağlar.

Güvenlik Uyarısı: Redis sunucunuzu asla dış dünyaya (public internet) doğrudan açmayın. Redis varsayılan olarak kimlik doğrulama gerektirmeyebilir; üretim ortamında mutlaka güçlü bir parola (requirepass) kullanın ve sadece uygulama sunucunuzun IP adresinden erişime izin verin.

Performans Testi ve Debug İpuçları

Sisteminizi kurduktan sonra performans artışını ölçmek için console.time ve console.timeEnd komutlarını kullanabilirsiniz. Ayrıca Redis tarafında MONITOR komutu ile gelen sorguları anlık izleyebilirsiniz.

console.time('SorguSuresi');
const data = await getUserData(123);
console.timeEnd('SorguSuresi');

Eğer SorguSuresi ilk istekte 200ms, ikinci istekte 5ms çıkıyorsa, önbellekleme sisteminiz başarıyla çalışıyor demektir.

Sıkça Sorulan Sorular

Redis ve Memcached arasındaki fark nedir?

Redis, sadece basit anahtar-değer çiftlerini değil; liste, set, hash ve sıralı set gibi karmaşık veri yapılarını da destekler. Ayrıca Redis'in veriyi diske kalıcı olarak yazma özelliği vardır, bu da onu sadece önbellek değil, bir veritabanı olarak da kullanabilmenizi sağlar.

Önbellek ne zaman temizlenmelidir?

Veri güncellendiğinde (update/delete) veya verinin geçerlilik süresi (TTL) dolduğunda temizlenmelidir. Çok sık değişen veriler için kısa TTL süreleri, nadir değişen veriler için uzun TTL süreleri tercih edilmelidir.

Redis sunucusu çökerse ne olur?

Uygulamanızda hata yönetimi (try-catch) bloğu kullanıyorsanız, Redis'e ulaşılamadığında veritabanına doğrudan sorgu atarak uygulamanın çalışmaya devam etmesini sağlayabilirsiniz.

JSON verisi Redis'te nasıl saklanır?

Redis verileri string olarak saklar. Bu nedenle nesnelerinizi JSON.stringify() ile stringe çevirip kaydetmeli, okurken JSON.parse() ile tekrar nesneye dönüştürmelisiniz.

Üretim ortamında Redis için ne kadar RAM gerekir?

Bu, önbelleğe alacağınız verinin boyutuna bağlıdır. Redis, RAM tabanlı olduğu için verilerin toplam boyutunun, sunucunuzdaki boş RAM miktarından az olması gerekir. Redis'in "eviction" (eski veriyi silme) politikalarını (LRU - Least Recently Used) yapılandırarak sınırlı RAM ile büyük veri setlerini yönetebilirsiniz.

Redis İle İleri Seviye Veri Yapıları ve Kullanım Senaryoları

Redis sadece basit anahtar-değer (key-value) çiftlerini saklamakla kalmaz; karmaşık veri yapılarını kullanarak uygulamanızın performansını daha da yukarı çekmenize olanak tanır. Özellikle Hash ve Sorted Set yapıları, önbellekleme stratejilerinde verimliliği artırır.

Hash Yapısı ile Nesne Bazlı Önbellekleme

Büyük JSON nesnelerini tek bir string olarak saklamak yerine, Redis Hash yapısını kullanmak, nesnenin sadece belirli alanlarını güncellemeniz gerektiğinde tüm veriyi tekrar serialize etme zorunluluğunu ortadan kaldırır.

// Bir kullanıcı profilini Hash olarak kaydetme
const redis = require('redis');
const client = redis.createClient();

async function cacheUserProfile(userId, userData) {
  // HSET komutu ile nesne alanlarını ayrı ayrı saklayabiliriz
  await client.hSet(`user:${userId}`, {
    name: userData.name,
    email: userData.email,
    lastLogin: Date.now().toString()
  });
  // TTL belirleyerek verinin ömrünü yönetin
  await client.expire(`user:${userId}`, 3600);
}

Sorted Set ile "En Çok Okunanlar" Listesi

Uygulamanızda en popüler ürünleri veya son erişilen içerikleri takip etmek istiyorsanız, Sorted Set (ZSET) yapısı idealdir. Her öğeye bir skor atayarak verileri otomatik olarak sıralı tutabilirsiniz.

// Bir içeriğin görüntülenme sayısını artırma
async function incrementViewCount(articleId) {
  // ZINCRBY ile skor (görüntülenme) artırılır
  await client.zIncrBy('popular_articles', 1, articleId);
}

// En popüler 5 içeriği getirme
async function getTopArticles() {
  // ZREVRANGE ile en yüksek skorlu öğeleri alıyoruz
  const topArticles = await client.zRange('popular_articles', 0, 4, {
    REV: true
  });
  return topArticles;
}

Üretim Ortamında Redis İzleme ve Hata Yönetimi

Redis'in sağlıklı çalıştığından emin olmak için sadece kod yazmak yeterli değildir; çalışma zamanı metriklerini izlemek ve bağlantı hatalarını yönetmek kritik öneme sahiptir.

Bağlantı Dayanıklılığı (Resilience)

Redis sunucusu geçici olarak erişilemez olduğunda uygulamanızın çökmesini engellemek için "Circuit Breaker" mantığı veya basit bir hata yakalama mekanizması kullanmalısınız.

client.on('error', (err) => {
  console.error('Redis Bağlantı Hatası:', err);
});

async function getCachedData(key) {
  try {
    return await client.get(key);
  } catch (error) {
    console.warn('Redis erişilemiyor, veritabanına yönlendiriliyor...');
    // Redis devre dışıysa doğrudan veritabanı sorgusuna düş
    return await fetchFromDatabase(key);
  }
}

Performans İzleme İpuçları

  • Slowlog Kullanımı: SLOWLOG GET komutu ile Redis tarafında çok uzun süren sorguları tespit edin.
  • Memory Eviction: INFO memory komutu ile Redis'in bellek kullanımını takip edin. Eğer bellek doluyorsa maxmemory-policy ayarını (örneğin: allkeys-lru) gözden geçirin.
  • Bağlantı Havuzu: Node.js tarafında bağlantılarınızı sürekli açıp kapatmak yerine, bağlantı havuzu (connection pooling) mantığıyla çalışan kütüphaneleri tercih edin.
Not: Üretim ortamında Redis bağlantılarını her zaman bir ortam değişkeni üzerinden yönetin ve REDIS_URL gibi hassas bilgileri asla kod içerisinde hard-coded olarak bırakmayın.

Sonuç

Node.js uygulamalarınızda Redis kullanarak önbellekleme yapmak, veritabanı yükünü azaltmanın ve kullanıcı deneyimini iyileştirmenin en etkili yoludur. Bu rehberde, Cache-Aside modelini, verinin nasıl geçersiz kılınacağını ve Redis ile nasıl güvenli bir bağlantı kurulacağını öğrendiniz. Bir sonraki adım olarak, Redis'in Pub/Sub mekanizmasını inceleyerek gerçek zamanlı bildirim sistemleri üzerine çalışabilir veya Redis Cluster yapısı ile uygulamanızı yatayda nasıl ölçekleyeceğinizi araştırabilirsiniz.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce Redis yapılandırmanızı, ağ güvenliğinizi ve veri gizliliği politikalarınızı (KVKK/GDPR) gözden geçiriniz. Uygulamanızın güvenlik açıklarından geliştirici sorumludur.

Bu yazıya tepkinizi paylaşın:
Zeynep Arslan

Kullanıcı deneyimi odaklı içerik üretiminde uzmanlaşmış bir editörüm. Özellikle DIY projeleri ve teknik rehberler üzerine detaylı içerikler üretiyorum.

Yorumlar (0)

Yorum Yaz