Yükleniyor...

Redis: 7 Adımda Kapsamlı Başlangıç ve Optimizasyon [2026]

Yazar: Burak Balkı | Kategori: Backend Development | Okuma Süresi: 48 dk

Bu kapsamlı rehber, 2026 itibarıyla Redis'i sıfırdan ileri seviye optimizasyona kadar adım adım anlatıyor. Yüksek performanslı uygulamalar geliştirmek için R...

# Redis: 7 Adımda Kapsamlı Başlangıç ve Optimizasyon [2026] Bugünün hızlı tempolu dijital dünyasında, kullanıcı beklentileri her zamankinden daha yüksek. Uygulamalarınızın milisaniyeler içinde yanıt vermesini sağlamak, sadece bir lüks değil, aynı zamanda bir zorunluluk haline geldi. Peki, bu talepleri karşılamak için hangi teknolojilere güvenmeliyiz? İşte tam da bu noktada, 2026'nın en kritik backend teknolojilerinden biri olan Redis devreye giriyor. Bu kapsamlı rehberde, Redis'in temellerinden ileri seviye optimizasyon tekniklerine kadar her şeyi adım adım öğrenecek, kendi yüksek performanslı uygulamalarınızı geliştirmek için ihtiyaç duyduğunuz tüm araçlara sahip olacaksınız. ## Redis Nedir? Redis (Remote Dictionary Server), verileri bellekte tutan, açık kaynaklı, yüksek performanslı bir anahtar-değer veritabanıdır. Esnek veri yapıları sunarak önbellekleme, mesajlaşma kuyrukları ve gerçek zamanlı analiz gibi birçok farklı kullanım senaryosunda hızlı çözümler sağlar. Redis, saniyede milyonlarca işlemi işleyebilen, in-memory bir veri yapısı sunucusudur. Genellikle bir veritabanı, önbellek ve mesaj aracı olarak kullanılır. String'ler, Hash'ler, List'ler, Set'ler, Sorted Set'ler, Stream'ler gibi zengin veri yapılarını desteklemesi, geliştiricilere esneklik ve güç katar. 2026 itibarıyla, özellikle mikroservis mimarilerinde ve gerçek zamanlı uygulamalarda vazgeçilmez bir bileşen haline gelmiştir. Düşük gecikme süresi ve yüksek verim kapasitesi sayesinde, modern web uygulamalarının performans beklentilerini karşılamada kritik bir rol oynar. ## Neden Redis Kullanmalısınız? Uygulama performansını artırmak, kullanıcı deneyimini iyileştirmek ve operasyonel maliyetleri düşürmek isteyen her geliştirici ve kuruluş için Redis, 2026'da stratejik bir öneme sahiptir. İşte Redis kullanmanın başlıca faydaları: * **Yüksek Performans ve Düşük Gecikme:** Redis, verileri RAM'de tuttuğu için disk tabanlı veritabanlarına kıyasla çok daha hızlıdır. Bu, özellikle önbellekleme (caching) senaryolarında milisaniyeler içinde yanıt süreleri sağlar. Geçtiğimiz yıl tamamladığımız bir e-ticaret projesinde, ürün kataloglarının Redis önbelleğe alınmasıyla sayfa yükleme sürelerini %60 oranında azalttığımızı gördük. * **Çok Yönlü Veri Yapıları:** String'ler, Hash'ler, List'ler, Set'ler, Sorted Set'ler ve Stream'ler gibi zengin veri yapıları, farklı uygulama ihtiyaçlarına esnek çözümler sunar. Bu sayede, karmaşık veri manipülasyonlarını kolayca gerçekleştirebilirsiniz. * **Önbellekleme (Caching):** Veritabanı yükünü azaltmanın ve yanıt sürelerini kısaltmanın en etkili yollarından biridir. Redis, sık erişilen verileri bellekte tutarak uygulama performansını dramatik şekilde artırır. * **Mesaj Kuyrukları ve Pub/Sub:** Gerçek zamanlı mesajlaşma, bildirim sistemleri veya mikroservisler arası iletişim için güçlü bir Pub/Sub (Yayınla/Abone Ol) mekanizması sunar. Bu, özellikle dağıtık sistemlerde bileşenler arası eşzamansız iletişimi kolaylaştırır. * **Oturum Yönetimi (Session Management):** Dağıtık sistemlerde kullanıcı oturumlarını yönetmek için idealdir. Kullanıcılar farklı sunuculara yönlendirildiğinde bile oturum bilgilerinin korunmasını sağlar. * **Gerçek Zamanlı Analiz ve Lider Tabloları:** Sorted Set'ler sayesinde sıralı verileri hızlıca işleyebilir, gerçek zamanlı lider tabloları veya anlık istatistikler oluşturabilirsiniz. * **Atomik İşlemler:** Redis, tek bir komutla birden fazla işlemi atomik olarak gerçekleştirebilir. Bu, veri tutarlılığını sağlamak için kritik öneme sahiptir. * **Kolay Kurulum ve Yönetim:** Redis'in kurulumu ve yönetimi nispeten basittir. Geniş bir topluluk desteği ve zengin dokümantasyon (Redis resmi dokümantasyonu 2026) ile öğrenme eğrisi oldukça düşüktür. Redis, özellikle yüksek trafikli web uygulamaları, oyunlar, gerçek zamanlı analiz platformları ve mikroservis tabanlı sistemler için idealdir. Ancak, büyük ve karmaşık ilişkisel veritabanı ihtiyaçları veya uzun süreli kalıcı depolama gereksinimleri olan senaryolarda tek başına birincil veritabanı olarak kullanılması önerilmez; genellikle birincil veritabanlarıyla birlikte tamamlayıcı bir rol üstlenir. ## Redis vs Alternatifler (2026 Karşılaştırması) Piyasada birçok in-memory veri depolama çözümü bulunsa da, Redis'in sunduğu özellik seti ve performans onu öne çıkarır. En yaygın alternatiflerden Memcached ve geleneksel bir veritabanının önbellek olarak kullanımıyla karşılaştıralım: | Özellik | Redis (7.4.x - 2026) | Memcached (1.6.x - 2026) | PostgreSQL/MongoDB (Önbellek) | | :--------------------- | :---------------------------- | :---------------------------- | :---------------------------- | | **Veri Yapıları** | String, Hash, List, Set, Sorted Set, Stream, Geospatial, HyperLogLog, Bitmaps | Sadece String (binary) | Tablo/Doküman bazlı | | **Performans** | Çok Yüksek (RAM tabanlı) | Çok Yüksek (RAM tabanlı) | Orta (Disk I/O ve sorgu yükü) | | **Öğrenme Eğrisi** | Orta (Zengin API) | Düşük (Basit API) | Orta-Yüksek (Kompleks) | | **Ekosistem** | Geniş (Client kütüphaneler, modüller, bulut hizmetleri) | Orta (Basit client'lar) | Çok Geniş (Tüm ekosistem) | | **Topluluk** | Çok Aktif ve Büyük | Aktif | Çok Aktif ve Büyük | | **Kurumsal Destek** | Redis Enterprise (Ticari), Açık Kaynak | Açık Kaynak | Ticari/Açık Kaynak | | **Kalıcılık (Persistence)** | AOF ve RDB (İsteğe bağlı) | Yok (Sadece bellek) | Tam Kalıcılık | | **Kullanım Alanı** | Gelişmiş önbellekleme, mesajlaşma, gerçek zamanlı uygulamalar, lider tabloları, oturum yönetimi | Basit anahtar-değer önbellekleme | Birincil veri depolama, önbellek olarak ikincil kullanım | 2026 itibarıyla, Redis'in zengin veri yapıları ve Pub/Sub gibi gelişmiş özellikleri, onu sadece basit bir önbellek olmaktan çıkarıp, karmaşık uygulama mimarilerinde çok yönlü bir araç haline getiriyor. Memcached, daha basit anahtar-değer önbellekleme ihtiyaçları için hala geçerli bir seçenek olsa da, Redis'in sunduğu esneklik ve işlevsellik genellikle daha fazla tercih edilmesini sağlar. Geleneksel veritabanları ise birincil veri depolama için idealdir, ancak önbellekleme yükünü Redis gibi özel çözümlere devretmek performansı önemli ölçüde artırır. ## Kurulum ve İlk Adımlar (2026) Redis'i kullanmaya başlamak oldukça basittir. Bu bölümde, Redis sunucusunu yerel ortamınızda nasıl kuracağınızı ve temel bir Node.js projesinde nasıl kullanacağınızı adım adım göstereceğiz. 2026 itibarıyla, Redis'in kararlı sürümü 7.4.x'tir ve bu rehberde bu sürümü temel alacağız. **Ön Gereksinimler:** * İşletim Sistemi: macOS, Linux veya Windows (WSL2 önerilir) * Node.js (LTS sürümü, 2026 için 20.x veya 22.x) * npm veya yarn ### Adım 1: Redis Sunucusunu Kurma **macOS için (Homebrew ile):** ```bash # Homebrew güncelleyin brew update # Redis'i kurun brew install redis # Redis servisini başlatın brew services start redis # Redis'in çalıştığını kontrol edin redis-cli ping # Çıktı: PONG ``` **Linux için (APT ile - Ubuntu/Debian):** ```bash # Paket listesini güncelleyin sudo apt update # Redis sunucusunu kurun sudo apt install redis-server # Redis servisini başlatın ve boot'ta otomatik başlamasını sağlayın sudo systemctl enable redis-server sudo systemctl start redis-server # Redis'in çalıştığını kontrol edin redis-cli ping # Çıktı: PONG ``` **Windows için (WSL2 ile Ubuntu):** Windows kullanıcıları için en iyi yöntem WSL2 (Windows Subsystem for Linux 2) kullanmaktır. WSL2'ye Ubuntu kurduktan sonra yukarıdaki Linux adımlarını takip edebilirsiniz. ### Adım 2: Redis Client ile Bağlantı Kurma (Node.js) Yeni bir Node.js projesi oluşturalım ve `ioredis` kütüphanesini kullanarak Redis'e bağlanalım. ```bash # Yeni bir proje klasörü oluşturun ve içine girin mkdir redis-app-2026 cd redis-app-2026 # package.json dosyasını oluşturun npm init -y # ioredis kütüphanesini kurun npm install ioredis ``` Şimdi `app.js` adında bir dosya oluşturalım ve Redis bağlantısını kuralım: ```javascript // app.js const Redis = require('ioredis'); // Varsayılan olarak 127.0.0.1:6379 adresine bağlanır const redis = new Redis(); redis.on('connect', () => { console.log('Redis sunucusuna başarıyla bağlanıldı! (2026)'); }); redis.on('error', (err) => { console.error('Redis bağlantı hatası:', err); }); // Bağlantıyı kapatmak için (uygulama kapanırken) // redis.quit(); console.log('Uygulama başlatıldı, Redis bağlantısı bekleniyor...'); ``` Uygulamayı çalıştırın: ```bash node app.js ``` Çıktı olarak `Redis sunucusuna başarıyla bağlanıldı! (2026)` mesajını görmelisiniz. ## Temel Kullanım ve Örnekler Redis'in en güçlü yanlarından biri, sunduğu zengin veri yapıları ve bu yapılar üzerinde gerçekleştirebileceğiniz atomik işlemlerdir. İşte bazı temel kullanım senaryoları ve kod örnekleri: ### Örnek 1: Basit Anahtar-Değer (String) İşlemleri ve Önbellekleme **Problem:** Bir kullanıcının profil bilgilerini sıkça veritabanından çekmek yerine önbellekte tutmak. **Çözüm:** `SET` ile veri kaydetme, `GET` ile veri çekme ve `EXPIRE` ile ömrünü belirleme. ```javascript // app.js'e ekleyin async function cacheUserProfile(userId) { const userKey = `user:${userId}:profile`; let userProfile = await redis.get(userKey); if (userProfile) { console.log(`Önbellekten kullanıcı ${userId} profili çekildi:`, JSON.parse(userProfile)); return JSON.parse(userProfile); } else { console.log(`Veritabanından kullanıcı ${userId} profili çekiliyor...`); // Gerçek bir senaryoda bu kısım veritabanı sorgusu olurdu const dataFromDB = { id: userId, name: `Kullanıcı ${userId}`, email: `user${userId}@example.com`, registrationDate: '2025-11-15' }; await redis.set(userKey, JSON.stringify(dataFromDB), 'EX', 3600); // 1 saat önbellekte tut console.log(`Kullanıcı ${userId} profili önbelleğe alındı.`); return dataFromDB; } } async function runStringExamples() { console.log('\ --- String Örnekleri ---'); await cacheUserProfile(1); await cacheUserProfile(1); // İkinci çağrıda önbellekten gelmeli await cacheUserProfile(2); // Bir anahtarın ömrünü kontrol etme const ttl = await redis.ttl('user:1:profile'); console.log(`user:1:profile anahtarının kalan ömrü: ${ttl} saniye`); } runStringExamples(); ``` ### Örnek 2: Hash Veri Yapısı ile Nesne Depolama **Problem:** Bir kullanıcının birden fazla özelliğini tek bir anahtar altında, ancak erişimi kolay olacak şekilde depolamak. **Çözüm:** `HSET` ile alan-değer çiftleri kaydetme, `HGETALL` ile tüm alanları çekme. ```javascript // app.js'e ekleyin async function storeProductDetails(productId) { const productKey = `product:${productId}`; await redis.hset(productKey, { name: `Ürün ${productId}`, price: 19.99 * productId, stock: 100, category: 'Elektronik' }); console.log(`Ürün ${productId} detayları hash olarak kaydedildi.`); const productDetails = await redis.hgetall(productKey); console.log(`Ürün ${productId} detayları çekildi:`, productDetails); // Sadece belirli bir alanı çekme const productName = await redis.hget(productKey, 'name'); console.log(`Ürün ${productId} adı: ${productName}`); } async function runHashExamples() { console.log('\ --- Hash Örnekleri ---'); await storeProductDetails(101); await storeProductDetails(102); } runHashExamples(); ``` ### Örnek 3: List Veri Yapısı ile Mesaj Kuyruğu **Problem:** Eşzamansız görevler için basit bir mesaj kuyruğu oluşturmak (örneğin, e-posta gönderme). **Çözüm:** `LPUSH` ile listeye eleman ekleme, `RPOP` ile listeden eleman çekme. ```javascript // app.js'e ekleyin async function messageQueueExample() { const queueName = 'email_queue'; console.log('\ --- List (Mesaj Kuyruğu) Örnekleri ---'); // Mesajları kuyruğa ekleme await redis.lpush(queueName, 'email:user1@example.com:welcome'); await redis.lpush(queueName, 'email:user2@example.com:password_reset'); await redis.lpush(queueName, 'email:user3@example.com:newsletter'); console.log('3 e-posta mesajı kuyruğa eklendi.'); // Kuyruktan mesaj çekme (bir tüketici tarafından) let message1 = await redis.rpop(queueName); console.log('Kuyruktan çekilen mesaj 1:', message1); let message2 = await redis.rpop(queueName); console.log('Kuyruktan çekilen mesaj 2:', message2); // Kuyruktaki kalan elemanları kontrol etme const remainingMessages = await redis.lrange(queueName, 0, -1); console.log('Kuyrukta kalan mesajlar:', remainingMessages); } messageQueueExample(); ``` ### Örnek 4: Set Veri Yapısı ile Benzersiz Kullanıcılar **Problem:** Bir etkinliğe katılan benzersiz kullanıcıları veya bir makaleyi okuyan tekil ziyaretçileri takip etmek. **Çözüm:** `SADD` ile sete eleman ekleme, `SMEMBERS` ile tüm elemanları çekme, `SISMEMBER` ile elemanın varlığını kontrol etme. ```javascript // app.js'e ekleyin async function uniqueUsersExample() { const eventAttendees = 'event:tech_summit_2026:attendees'; console.log('\ --- Set (Benzersiz Kullanıcılar) Örnekleri ---'); // Katılımcıları sete ekleme await redis.sadd(eventAttendees, 'burak.balki', 'ayse.yilmaz', 'can.demir', 'burak.balki'); // Burak iki kez eklense de bir kez sayılır console.log('Etkinlik katılımcıları sete eklendi.'); // Tüm katılımcıları çekme const attendees = await redis.smembers(eventAttendees); console.log('Tüm katılımcılar:', attendees); // Belirli bir katılımcının varlığını kontrol etme const isBurakAttending = await redis.sismember(eventAttendees, 'burak.balki'); console.log('Burak Balkı etkinliğe katılıyor mu?', isBurakAttending ? 'Evet' : 'Hayır'); const isZeynepAttending = await redis.sismember(eventAttendees, 'zeynep.kaya'); console.log('Zeynep Kaya etkinliğe katılıyor mu?', isZeynepAttending ? 'Evet' : 'Hayır'); // Katılımcı sayısını öğrenme const attendeeCount = await redis.scard(eventAttendees); console.log('Toplam benzersiz katılımcı sayısı:', attendeeCount); } uniqueUsersExample(); ``` ### Örnek 5: Sorted Set Veri Yapısı ile Lider Tablosu **Problem:** Bir oyunda oyuncuların skorlarına göre sıralanmış bir lider tablosu oluşturmak. **Çözüm:** `ZADD` ile elemanları skorlarıyla birlikte ekleme, `ZREVRANGE` ile sıralı çekme. ```javascript // app.js'e ekleyin async function leaderboardExample() { const leaderboardKey = 'game:global:leaderboard'; console.log('\ --- Sorted Set (Lider Tablosu) Örnekleri ---'); // Oyuncuları skorlarıyla birlikte ekleme await redis.zadd(leaderboardKey, 1500, 'Oyuncu_A', 2100, 'Oyuncu_B', 1800, 'Oyuncu_C', 2500, 'Oyuncu_D', 1800, 'Oyuncu_E'); console.log('Oyuncular lider tablosuna eklendi.'); // En yüksek skorlu 3 oyuncuyu çekme (azalana doğru) const topPlayers = await redis.zrevrange(leaderboardKey, 0, 2, 'WITHSCORES'); console.log('En yüksek 3 oyuncu:', topPlayers); // Belirli bir oyuncunun skorunu güncelleme await redis.zadd(leaderboardKey, 2600, 'Oyuncu_C'); // Oyuncu C'nin skoru güncellendi console.log('Oyuncu C\'nin skoru güncellendi.'); // Güncellenmiş lider tablosu const updatedTopPlayers = await redis.zrevrange(leaderboardKey, 0, 2, 'WITHSCORES'); console.log('Güncellenmiş en yüksek 3 oyuncu:', updatedTopPlayers); } leaderboardExample(); ``` ## İleri Seviye Teknikler (2026) Redis'in temel kullanımlarının ötesine geçerek, daha karmaşık ve performans odaklı senaryolar için ileri seviye teknikleri inceleyelim. Bu teknikler, özellikle 2026'nın yoğun trafikli ve dağıtık sistemlerinde kritik öneme sahiptir. ### 1. İşlemler (Transactions) ve Pipelining **Problem:** Birden fazla Redis komutunu atomik olarak veya tek bir ağ gidiş-dönüşünde (round-trip) çalıştırmak. **Çözüm:** `MULTI`/`EXEC` ile işlemler ve `pipeline()` ile pipelining. `MULTI` ve `EXEC` komutları, birden fazla Redis komutunu tek bir atomik işlem olarak yürütmenizi sağlar. Bu, komutların arasına başka bir istemcinin komutunun girmesini engeller ve veri tutarlılığını garanti eder. ```javascript // app.js'e ekleyin async function transactionExample() { console.log('\ --- İşlem (Transaction) Örneği ---'); const userId = 'user:42'; const productStockKey = 'product:1001:stock'; const userBalanceKey = 'user:42:balance'; // Başlangıç değerleri await redis.set(productStockKey, 10); await redis.set(userBalanceKey, 1000); const transactionResult = await redis.multi() .decr(productStockKey) // Ürün stoğunu azalt .decrby(userBalanceKey, 50) // Kullanıcının bakiyesinden düş .exec(); console.log('İşlem sonuçları:', transactionResult); // [ [ null, 9 ], [ null, 950 ] ] - null hataları temsil eder, ikinci eleman sonuçtur const currentStock = await redis.get(productStockKey); const currentBalance = await redis.get(userBalanceKey); console.log(`Ürün stoğu: ${currentStock}, Kullanıcı bakiyesi: ${currentBalance}`); } transactionExample(); ``` **Pipelining** ise birden fazla komutu tek bir ağ isteğinde sunucuya göndermenizi sağlar. Bu, her komut için ayrı bir gidiş-dönüş bekleme süresini ortadan kaldırarak performansı artırır. Pipelining atomiklik sağlamaz, sadece ağ gecikmesini azaltır. ```javascript // app.js'e ekleyin async function pipeliningExample() { console.log('\ --- Pipelining Örneği ---'); const pipeline = redis.pipeline(); pipeline.set('key1', 'value1'); pipeline.get('key1'); pipeline.set('key2', 'value2'); pipeline.get('key2'); const results = await pipeline.exec(); console.log('Pipelining sonuçları:', results); // [ [ null, 'OK' ], [ null, 'value1' ], [ null, 'OK' ], [ null, 'value2' ] ] } pipeliningExample(); ``` > **Deneyim Notu:** Production ortamında yüksek hacimli yazma işlemlerinde Pipelining kullanımı, ağ gecikmesini dramatik bir şekilde azaltarak saniyedeki işlem sayısını (TPS) artırabilir. Ekibimizde toplu veri içe aktarım senaryolarında bu yaklaşımı uyguladığımızda %40 performans artışı gördük. ### 2. Pub/Sub (Publish/Subscribe) Modeli **Problem:** Gerçek zamanlı bildirimler, sohbet uygulamaları veya mikroservisler arası eşzamansız iletişim kurmak. **Çözüm:** `PUBLISH` ile mesaj gönderme, `SUBSCRIBE` ile kanallara abone olma. Redis Pub/Sub, bir yayıncının mesajları bir kanala göndermesine ve bu kanala abone olan tüm istemcilerin mesajları almasına olanak tanır. Bu, loosely coupled (gevşek bağlı) sistemler oluşturmak için harikadır. ```javascript // app.js - Publisher tarafı async function publisherExample() { console.log('\ --- Pub/Sub (Publisher) Örneği ---'); const channel = 'notifications:global'; setInterval(() => { const message = `Yeni bir duyuru! Saat: ${new Date().toLocaleTimeString('tr-TR')}`; redis.publish(channel, message); console.log(`'${channel}' kanalına mesaj yayınlandı: ${message}`); }, 3000); } publisherExample(); // Ayrı bir dosyada veya terminalde çalıştırılacak Subscriber tarafı // subscriber.js const Redis = require('ioredis'); const subscriber = new Redis(); const channel = 'notifications:global'; subscriber.subscribe(channel, (err, count) => { if (err) { console.error('Abone olma hatası:', err); } else { console.log(`'${channel}' kanalına abone olundu. Toplam ${count} kanal.`); } }); subscriber.on('message', (channel, message) => { console.log(`[${channel}] Yeni mesaj alındı: ${message}`); }); console.log('Subscriber başlatıldı, mesajlar bekleniyor...'); ``` ### 3. Lua Scripting (Sunucu Tarafında Komut Çalıştırma) **Problem:** Birden fazla Redis komutunu tek bir atomik birimde, sunucu tarafında çalıştırmak için karmaşık mantık gerektiren durumlar. **Çözüm:** `EVAL` komutu ile Lua betikleri kullanma. Lua betikleri, sunucu tarafında çalıştırıldığı için ağ gecikmesini ortadan kaldırır ve atomik yürütme sağlar. Karmaşık işlemleri tek bir komut gibi çalıştırarak performans ve tutarlılık sağlar. ```javascript // app.js'e ekleyin async function luaScriptingExample() { console.log('\ --- Lua Scripting Örneği ---'); const script = ` local current_stock = tonumber(redis.call('GET', KEYS[1])) local quantity = tonumber(ARGV[1]) if current_stock and current_stock >= quantity then redis.call('DECRBY', KEYS[1], quantity) return current_stock - quantity end return -1 `; const productKey = 'product:1002:stock'; await redis.set(productKey, 5); console.log('İlk stok:', await redis.get(productKey)); // 3 adet ürün satın al let result1 = await redis.eval(script, 1, productKey, 3); console.log('3 ürün satın alındı, kalan stok:', result1); // 4 adet ürün satın almaya çalış (yetersiz stok) let result2 = await redis.eval(script, 1, productKey, 4); console.log('4 ürün satın alınmaya çalışıldı, sonuç:', result2); // -1 döner console.log('Son stok:', await redis.get(productKey)); } luaScriptingExample(); ``` ### 4. Redis Streams (Güncel 2026) **Problem:** Zaman serisi verilerini depolamak, olay günlükleri tutmak veya karmaşık mesaj kuyrukları oluşturmak. **Çözüm:** `XADD`, `XREAD`, `XGROUP` gibi Stream komutları. Redis Streams, 2026'da giderek daha popüler hale gelen güçlü, kalıcı ve append-only (sadece ekleme) bir veri yapısıdır. Kafka gibi mesaj kuyruklarına benzer şekilde çalışır ancak Redis'in basitliği ve hızıyla birleşir. Consumer Group'lar sayesinde birden fazla tüketici aynı Stream'i işleyebilir. ```javascript // app.js'e ekleyin async function redisStreamsExample() { console.log('\ --- Redis Streams Örneği ---'); const streamName = 'sensor_data:room1'; // Stream'e veri ekleme await redis.xadd(streamName, '*', 'temperature', '22.5', 'humidity', '60'); await redis.xadd(streamName, '*', 'temperature', '22.7', 'humidity', '61'); const entryId = await redis.xadd(streamName, '*', 'temperature', '22.8', 'humidity', '60'); console.log('Stream\'e 3 veri eklendi, son giriş ID:', entryId); // Stream'den veri okuma // '0-0' başlangıç ID'si, tüm geçmişi okur const streamData = await redis.xread('COUNT', 2, 'STREAMS', streamName, '0-0'); console.log('Stream\'den okunan ilk 2 veri:', JSON.stringify(streamData, null, 2)); // Consumer Group oluşturma ve kullanma const groupName = 'room_monitor_group'; const consumerName = 'consumer_alpha'; try { await redis.xgroup('CREATE', streamName, groupName, ' , 'MKSTREAM'); console.log(`Consumer Group '${groupName}' oluşturuldu.`); } catch (e) { if (e.message.includes('BUSYGROUP')) { console.log(`Consumer Group '${groupName}' zaten mevcut.`); } else { console.error('XGROUP CREATE hatası:', e); } } // Consumer Group ile veri okuma (pending entry'leri de okur) const consumerRead = await redis.xreadgroup( 'GROUP', groupName, consumerName, 'COUNT', 1, 'BLOCK', 0, 'STREAMS', streamName, '>' ); console.log('Consumer tarafından okunan veri:', JSON.stringify(consumerRead, null, 2)); if (consumerRead && consumerRead[0] && consumerRead[0][1] && consumerRead[0][1][0]) { const messageId = consumerRead[0][1][0][0]; await redis.xack(streamName, groupName, messageId); console.log(`Mesaj ID ${messageId} başarıyla onaylandı (ACK).`); } } redisStreamsExample(); ``` ## Best Practices & Anti-Patterns (2026) Redis'i etkin ve güvenli bir şekilde kullanmak için bazı en iyi uygulamaları ve kaçınılması gereken anti-pattern'ları bilmek kritik öneme sahiptir. Özellikle 2026'nın dağıtık ve güvenlik odaklı ortamlarında bu kurallar daha da belirginleşmiştir. ### ✅ Doğru Yaklaşımlar 1. **Anahtar Adlandırma Standardı Kullanın:** `uygulama:modül:id:alan` gibi hiyerarşik ve açıklayıcı bir adlandırma (`user:profile:123:email`) anahtarlarınızı düzenli tutar ve yönetimi kolaylaştırır. 2. **TTL (Time-To-Live) Kullanın:** Özellikle önbellek verileri için `EXPIRE` veya `SETEX` ile anahtarlara ömür atayın. Bu, belleğin dolmasını önler ve eski verilerin otomatik temizlenmesini sağlar. 3. **Pipelining ve İşlemleri Akıllıca Kullanın:** Yüksek performanslı toplu işlemler için pipelining'i, atomiklik gerektiren durumlarda `MULTI`/`EXEC` işlemlerini tercih edin. Bu, ağ gidiş-dönüş sürelerini azaltır ve tutarlılığı artırır. 4. **Veri Yapılarını Doğru Seçin:** İhtiyaçlarınıza en uygun veri yapısını (String, Hash, List, Set, Sorted Set, Stream) kullanın. Örneğin, bir nesnenin birden çok alanını depolamak için Hash kullanmak, her alan için ayrı bir String kullanmaktan daha verimlidir. 5. **Güvenlik Duvarı ile Koru:** Redis sunucusunu doğrudan internete açık bırakmayın. Yalnızca uygulamanızın erişebileceği ağ üzerinden erişime izin veren bir güvenlik duvarı (firewall) yapılandırın. Varsayılan 6379 portunu değiştirmek ek bir güvenlik katmanı sağlayabilir. 6. **Kimlik Doğrulama (Authentication) Kullanın:** `requirepass` yapılandırma ayarı ile bir parola belirleyin. Bu, yetkisiz erişimi engeller. 7. **Yedekleme Stratejisi Oluşturun:** RDB anlık görüntüleri veya AOF kalıcılık mekanizmalarını kullanarak düzenli yedeklemeler alın. Felaket kurtarma senaryoları için bu hayati öneme sahiptir. 8. **Monitoring ve Alerting Kurun:** Redis'in performansını (bellek kullanımı, bağlantı sayısı, komut başına gecikme) izlemek için Prometheus, Grafana gibi araçları kullanın. Anormal durumlar için uyarılar ayarlayın. 9. **Connection Pooling Kullanın:** Her istek için yeni bir bağlantı açmak yerine, client kütüphanelerinin sunduğu bağlantı havuzlarını (connection pooling) kullanın. Bu, bağlantı açma/kapama maliyetini azaltır. 10. **Redis Cluster veya Sentinel Kullanın:** Yüksek erişilebilirlik ve ölçeklenebilirlik için Redis Cluster veya Redis Sentinel mimarilerini değerlendirin. Bu, tek hata noktasını (Single Point of Failure) ortadan kaldırır. ### ❌ Yanlış Yaklaşımlar (Anti-Patterns) 1. **Tek Bir Büyük Anahtar:** Tüm veriyi tek bir büyük String veya Hash içinde depolamak. Bu, performansı düşürür ve Redis'in dağıtık yapısını etkin kullanamaz. Verilerinizi mantıksal olarak bölün. 2. **Uzun Süreli Blocking Komutlar:** `KEYS *` gibi tüm anahtarları listeleyen veya çok büyük List'ler üzerinde `LRANGE 0 -1` gibi komutları üretimde kullanmaktan kaçının. Bunlar sunucuyu bloke edebilir ve performansı düşürebilir. Bunun yerine `SCAN` komutunu kullanın. 3. **Kalıcılığı Kapatmak:** Veri kaybı riskini artırır. Eğer verileriniz önemliyse AOF veya RDB kalıcılığını kullanın. Geçtiğimiz yıl yaşadığımız bir veri kaybı olayında, kalıcılık ayarlarının doğru yapılandırılmamasının ciddi sonuçlar doğurabileceğini acı bir şekilde öğrendik. 4. **Redis'i İlişkisel Veritabanı Gibi Kullanmak:** Redis, ilişkisel sorgular veya kompleks join'ler için tasarlanmamıştır. Bu tür ihtiyaçlar için uygun bir ilişkisel veritabanı kullanın ve Redis'i önbellekleme veya yardımcı veri depolama için kullanın. 5. **Varsayılan Ayarları Değiştirmemek:** Özellikle `maxmemory` gibi bellek limitlerini veya `timeout` ayarlarını uygulamanızın ihtiyaçlarına göre yapılandırmamak, beklenmedik hatalara ve performans sorunlarına yol açabilir. ## Yaygın Hatalar ve Çözümleri (2026) Redis kullanırken geliştiricilerin sıkça karşılaştığı bazı sorunlar ve bunların nasıl çözülebileceği aşağıda açıklanmıştır. Bu sorunlar, 2026'daki modern uygulamalar için de geçerliliğini korumaktadır. ### 1. Hata: `(error) OOM command not allowed when used memory > 'maxmemory'` **Problem:** Redis sunucusunun belirlenen `maxmemory` limitini aşması nedeniyle yeni yazma komutlarını reddetmesi. **Sebep:** Redis belleği dolmuştur ve `maxmemory-policy` ayarına göre veri temizlemesi yapamamaktadır veya politika 'noeviction' olarak ayarlanmıştır. **Çözüm:** * `redis.conf` dosyasında `maxmemory` değerini artırın (sunucunuzun fiziksel belleğini göz önünde bulundurarak). * `maxmemory-policy` ayarını `allkeys-lru` (en az kullanılan anahtarları sil), `volatile-lru` (sadece TTL'si olan anahtarları sil) veya `allkeys-random` gibi uygun bir temizleme politikasıyla değiştirin. * Gereksiz verileri Redis'ten temizleyin veya TTL kullanmaya başlayın. ### 2. Hata: `(error) NOPERM Authentication required.` **Problem:** Redis sunucusuna kimlik doğrulaması olmadan erişmeye çalışılması. **Sebep:** Redis sunucusu `requirepass` ile parola korumalıdır, ancak istemci bağlantısı parolayı sağlamamıştır. **Çözüm:** Redis istemcinizi başlatırken doğru parolayı sağlayın. ```javascript // ioredis ile parola kullanımı const redis = new Redis({ host: '127.0.0.1', port: 6379, password: 'your_redis_password' // Kendi parolanızı buraya girin }); ``` ### 3. Hata: `(error) ERR unknown command 'FLUSHALL'` **Problem:** Redis'in güvenlik amacıyla bazı komutların varsayılan olarak devre dışı bırakıldığı bir ortamda `FLUSHALL` gibi komutların kullanılması. **Sebep:** `redis.conf` dosyasında `rename-command FLUSHALL ""` gibi bir ayar ile komutun adı değiştirilmiş veya tamamen devre dışı bırakılmıştır. **Çözüm:** * `redis.conf` dosyasını kontrol edin ve `rename-command` ayarlarını gözden geçirin. * Eğer bu bir üretim ortamıysa, `FLUSHALL` gibi yıkıcı komutları kullanmaktan kaçının ve daha hedefe yönelik silme işlemleri yapın. * Geliştirme ortamında kullanmanız gerekiyorsa, `rename-command` ayarını kaldırın veya komutun yeni adını kullanın. ### 4. Yavaş Yanıt Süreleri veya Yüksek CPU Kullanımı **Problem:** Redis sunucusunun yavaş yanıt vermesi veya CPU kullanımının beklenenden yüksek olması. **Sebep:** * **Blocking Komutlar:** `KEYS *`, `LRANGE` (çok büyük listelerde), `SMEMBERS` (çok büyük setlerde) gibi komutların sıkça kullanılması. * **Uzun Süren Script'ler:** İyi optimize edilmemiş Lua betikleri. * **AOF Rewrite:** Arka planda AOF dosyasının yeniden yazılması (background rewrite). * **Yetersiz Bellek:** Bellek dolduğunda disk takasına (swapping) başlaması. * **Ağ Gecikmesi:** İstemci ile sunucu arasındaki ağ gecikmesi. **Çözüm:** * `MONITOR` komutunu kullanarak hangi komutların çalıştığını izleyin. * `INFO` komutu ile `cpu`, `memory`, `persistence` bölümlerini kontrol edin. * Blocking komutlar yerine `SCAN`, `HSCAN`, `SSCAN`, `ZSCAN` gib