Redis Publish/Subscribe (Pub/Sub) mekanizması, mesajlaşma modeli olarak gönderici (publisher) ve alıcı (subscriber) arasında tam bir ayrım sağlayan, geçici ve bağlantı temelli bir iletişim paradigmadır. Publisher'lar, belirli bir kanala (channel) mesaj gönderirken, subscriber'lar ilgili kanala abone olarak bu mesajları dinlerler. Sistemin temel gücü, tarafların birbirinden tamamen habersiz olmasından gelir; publisher bir mesajı kanala bırakır ve bu mesajı kimin veya kaç kişinin aldığıyla ilgilenmez. Bu yapı, klasik istemci-sunucu veya request-response modelinden köklü bir kopuşu temsil eder.

Redis'in bu modeli uygulama şekli, TCP bağlantıları ve soketler üzerine inşa edilmiştir. Bir istemci SUBSCRIBE komutu ile bir veya daha fazla kanala abone olduğunda, Redis sunucusu o bağlantıyı "abonelik moduna" geçirir. Bu moda geçen bir bağlantı artık geleneksel Redis komutlarını (GET, SET gibi) çalıştıramaz; sadece abonelikleri yöneten komutları (SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE) kabul eder veya publisher'dan gelen mesajları alır. Bu tasarım, bağlantı durumunun korunmasını ve mesajların güvenilir bir şekilde ilgili sokete iletilmesini sağlar. Bağlantı koptuğunda tüm abonelikler otomatik olarak temizlenir.

Varlık Rol Karakteristik
Publisher (Yayıncı) Mesaj Üreticisi Kanal ismini ve mesajı bilir, subscriber'ları bilmez.
Subscriber (Abone) Mesaj Tüketicisi Abone olduğu kanalı/kanalları bilir, publisher'ları bilmez.
Channel (Kanal) Mesaj Yolu (Topic) Mesajların yönlendirildiği isimlendirilmiş hedef.
Redis Sunucusu Mesaj Broker'ı Mesajları kanallardan ilgili tüm abonelere iletir.
  • Bağlantı Temelli (Connection-Oriented): Abonelikler fiziksel TCP bağlantısına bağlıdır. Bağlantı sonlanırsa abonelikler silinir.
  • Geçici (Ephemeral): Gönderilen mesajlar Redis'te kalıcı olarak saklanmaz. Aktif aboneler o anda bağlı değilse mesaj kaybolur.
  • Çoklu Yayın (Multicast): Bir mesaj, aynı kanala abone olan birden fazla istemciye aynı anda iletilir.
  • Eşzamansız (Asenkron): Publisher mesajı gönderir ve işlemine devam eder; subscriber'ın mesajı alıp işlemesini beklemez.

PUBLISH ve SUBSCRIBE Komutları

Mekanizmanın işleyişi, birkaç temel komut etrafında şekillenir. PUBLISH komutu, bir mesajı belirli bir kanala göndermek için kullanılır. Komutun sözdizimi `PUBLISH channel message` şeklindedir. Komutun dönüş değeri, mesajı alan abone sayısıdır. Bu sayı, o kanala aktif olarak abone olmuş ve bağlantısı sağlam olan istemci sayısını ifade eder. Eğer abone yoksa, Redis mesajı işler ancak hiçbir yere iletmez ve publisher'a 0 değerini döndürür. Bu, publisher'ın mesajın ulaşıp ulaşmadığını bilmesini sağlayan tek geri bildirim mekanizmasıdır.

SUBSCRIBE komutu ise bir istemcinin bir veya daha fazla kanala abone olmasını sağlar. `SUBSCRIBE channel1 channel2 ...` formatında kullanılır. Bu komut çalıştırıldığı anda, istemci bağlantısı pub/sub moduna geçer ve komut istemi (prompt) normal moda dönmez. Bunun yerine, abone olduğu kanallara gönderilen her mesaj için Redis sunucusundan bir mesaj paketi gelir. Bu paket üç elemanlı bir dizi (array) şeklindedir: ilk eleman mesajın türünü ("message"), ikinci eleman mesajın geldiği kanalın adını, üçüncü eleman ise mesajın içeriğini taşır. Bu durum, Redis istemci kütüphanelerinin bu özel durumu yönetmek üzere tasarlanmasını gerektirir.

Abonelikten çıkmak için kullanılan `UNSUBSCRIBE` komutu da benzer şekilde çalışır. Bir istemci, belirli kanallardan veya (kanal belirtilmezse) tüm kanallardan aboneliğini sonlandırabilir. Komutun işlenmesinden sonra, ilgili kanallara gelen mesajlar artık bu istemciye iletilmez. Komutların protokol seviyesindeki etkileşimi, Redis'in RESP (Redis Serialization Protocol) protokolü ile uyumlu bir şekilde gerçekleşir. PUBLISH komutu senkron, SUBSCRIBE komutu asenkron bir iletişim başlatır. Aşağıda tipik bir etkileşim örneği görülmektedir:

// Publisher (Terminal 1)
127.0.0.1:6379> PUBLISH news:tech "Redis 7.0 released!"
(integer) 2 // 2 aboneye iletildi.

// Subscriber (Terminal 2 - Node.js örneği)
const redis = require('redis');
const subscriber = redis.createClient();

subscriber.on('message', (channel, message) => {
    console.log(`Kanal: ${channel}, Mesaj: ${message}`);
});
subscriber.subscribe('news:tech');

// Mesaj geldiğinde çıktı: "Kanal: news:tech, Mesaj: Redis 7.0 released!"

Kalıp Tabanlı Abonelik (Pattern Subscription)

Redis Pub/Sub, basit kanal ismi eşleştirmesinin ötesine geçen daha esnek bir abonelik modeli sunar: kalıp tabanlı abonelik. Bu modelde, aboneler tek bir kanal ismi yerine, glob-style pattern olarak adlandırılan bir desene abone olabilirler. Bu desenlerde `*` karakteri herhangi bir karakter dizisini, `?` karakteri tek bir karakteri temsil eder. Örneğin, `sensor:*` deseni, "sensor:temperature", "sensor:humidity", "sensor:room1:pressure" gibi `sensor:` ile başlayan tüm kanallarla eşleşir. Bu özellik, dinamik veya hiyerarşik olarak yapılandırılmış kanal ad alanlarında merkezi bir abonelik yönetimi sağlar ve sistem esnekliğini önemli ölçüde artırır.

Kalıp tabanlı abonelik, `PSUBSCRIBE` komutu ile başlatılır ve `PUNSUBSCRIBE` komutu ile sonlandırılır. Bir istemci hem kanal adına göre (`SUBSCRIBE`) hem de kalıba göre (`PSUBSCRIBE`) aynı anda abone olabilir. Sunucu, bir `PUBLISH` komutu aldığında öncelikle mesajın gönderildiği tam kanal adına abone olan istemcileri bulur. Daha sonra, kayıtlı tüm kalıpları tarar ve kanal adının bu kalıpla eşleşip eşleşmediğini kontrol eder. Eşleşme bulursa, mesajı bu kalıba abone olan istemcilere de iletir. Bu işlem, yayın anında gerçekleşen bir ek yük getirir, bu nedenle çok sayıda karmaşık kalıp, publish performansını olumsuz etkileyebilir.

Kalıp tabanlı abonelikte mesaj bildirim paketi farklılık gösterir. Normal `SUBSCRIBE` işleminde gelen paketin ilk elemanı "message" iken, bir kalıp eşleşmesi sonucu gelen paketin ilk elemanı "pmessage" olur. Paket dört elemanlıdır: mesaj tipi ("pmessage"), eşleşen orijinal kalıp, mesajın geldiği gerçek kanal adı ve nihayet mesajın kendisi. Bu ayrım, istemci tarafında mesajın kaynağının doğru bir şekilde anlaşılmasını sağlar. PSUBSCRIBE, mikroservis mimarilerinde esnek event routing sağlar.

Redis Pub/Sub'nin Özellikleri ve Sınırlamaları

Redis Pub/Sub, sunduğu basitlik ve düşük gecikme süresi ile belirli kullanım senaryolarında oldukça çekicidir. En önemli özelliklerinden biri, yüksek performans ve düşük latans sağlamasıdır. Bellek içi (in-memory) yapısı ve basit tasarımı sayesinde, saniyede yüz binlerce mesajın yayınlanması ve iletilmesi mümkündür. Ayrıca, merkezi bir mesaj broker'ı olarak hareket ettiği için, dağıtık sistemlerdeki farklı bileşenlerin birbirini doğrudan bilmesine gerek kalmadan, gevşek bağlı (loosely coupled) bir mimari oluşturulmasına imkan tanır. Bu özellik, sistemin genişletilebilirliği (scalability) ve bakım kolaylığı açısından kritiktir.

Ancak, bu basitliğin beraberinde getirdiği önemli sınırlamalar ve garanti eksiklikleri vardır. En belirgin sınırlama, mesajların kalıcı olmamasıdır. Redis, Pub/Sub mesajlarını diske yazmaz veya bellekte buffer'lamaz. Bir mesaj, yayınlandığı anda aktif ve bağlı olan abonelere iletilir. Eğer bir abone o anda bağlı değilse veya geçici bir ağ sorunu yaşıyorsa, o mesajı kaçırır ve geri alma şansı yoktur. Bu model, "en fazla bir kez" (at-most-once) teslimat garantisi sunar, ki bu birçok kritik iş süreci için yetersizdir. Ayrıca, ölçeklenme stratejisi sınırlıdır; yükün tek bir Redis sunucusu üzerinde yoğunlaşmasına neden olur.

Özellik / Sınırlama Açıklama Mimarideki Etkisi
Mesaj Kalıcılığı Yok. Mesajlar sadece aktif bağlantılara iletilir. Abonelerin kesintisiz çalışmasını zorunlu kılar, güvenilirlik için uygun değildir.
Teslimat Garantisi En fazla bir kez (At-Most-Once). Kayıp mesajlara tahammülü olmayan sistemlerde kullanılamaz.
Ölçeklenebilirlik (Scale-Out) Sınırlı. Tüm pub/sub trafiği tek bir sunucu düğümünden geçer. Yüksek hacimli sistemlerde bir darboğaz (bottleneck) oluşturabilir.
Sıralama (Ordering) Kanal bazında gönderim sırası korunur. Aynı kanaldaki mesajlar, tüm abonelere aynı sırayla ulaşır.
Tarihsel Mesaj Erişimi Yok. Yayınlanan mesajlara sonradan erişilemez. Yeni başlayan bir abone geçmiş mesajları alamaz (replay yok).

Bir diğer önemli sınırlama, ölçeklenebilirlik ile ilgilidir. Redis Cluster kullanılsa bile, Pub/Sub mekanizması tüm yayınların cluster'daki her düğüme yayılmasını gerektirir. Bu, büyük ölçüde ağ trafiği yaratabilir. Ayrıca, yüksek kullanılabilirlik (high availability) için Redis Sentinel veya Cluster kullanıldığında, bir failover durumunda istemci bağlantıları kesileceği için tüm abonelikler kaybolur. İstemcilerin yeniden bağlanıp aboneliklerini yeniden oluşturması gerekir ve bu sırada gönderilen mesajlar kaçırılır. Bu sınırlamalar, Redis Pub/Sub'ın kullanım alanını net şekilde tanımlar.

Kullanım Senaryoları ve Alternatifler

Redis Pub/Sub'nin teknik karakteristiği, onun ideal kullanım alanlarını ve kaçınılması gereken durumları netleştirir. En uygun olduğu senaryolar, mesaj kaybının kritik olmadığı, gerçek zamanlılığın ön planda olduğu ve abone bağlantılarının nispeten stabil olduğu ortamlardır. Buna örnek olarak, canlı spor skorları veya borsa verisi gibi anlık veri yayınları, oyun sunucularında çok oyunculu durum güncellemeleri, ve basit bir komut ve kontrol (command and control) kanalı üzerinden sunucu yönetimi verilebilir. Bu tür sistemlerde, geçmiş bir veri noktasının kaybı, mevcut durumu yansıtan yeni bir veri noktası geldiği için genellikle tolere edilebilir. Ayrıca, WebSocket bağlantılarını beslemek için bir arka plan mesajlaşma katmanı olarak da sıklıkla kullanılır.

Ancak, finansal işlem bildirimleri, sipariş işleme sistemleri veya uç cihazlardan gelen telemetri verilerinin işlendiği IoT pipeline'ları gibi, mesaj kaybının kabul edilemez olduğu ve kesin teslimat garantisi gerektiren sistemlerde Redis Pub/Sub saf haliyle uygun değildir. Benzer şekilde, abonelerin sürekli olarak bağlı kalamayacağı veya iş yükü dağıtımı (load balancing) gerektiren yüksek hacimli sistemlerde de temel Pub/Sub modeli yetersiz kalacaktır. Bu durumlarda, Redis'in kendi içindeki daha gelişmiş yapıları veya harici mesaj kuyruklama sistemleri dikkate alınmalıdır.

Redis ekosistemi içindeki ilk ve en önemli alternatif, Redis Streams veri yapısıdır. Streams, 2018'de Redis 5.0 ile tanıtıldı ve Pub/Sub'nin birçok sınırlamasını ele alır. Streams, mesajları kalıcı olarak, sıralı bir log yapısında tutar. Her mesaj benzersiz bir ID'ye sahiptir ve consumer grupları (consumer groups) özelliği sayesinde, birden fazla istemci mesajları yük paylaşımı yaparak işleyebilir. Consumer'lar işledikleri mesajın ID'sini saklayarak, bağlantı kopmalarında veya yeniden başlamalarda kaldıkları yerden devam edebilirler. Bu, "en az bir kez" (at-least-once) ve hatta dikkatli bir şekilde yönetilirse "tam olarak bir kez" (exactly-once) teslimat garantisi sağlar. Redis Streams, güvenilir mesajlaşma için tercih edilen modern yaklaşımdır.

Streams'in yanı sıra, `LIST` veri yapısı ve `BLPOP`/`BRPOP` gibi engellemeli (blocking) komutlar kullanılarak basit bir mesaj kuyruğu da oluşturulabilir. Bu model, basit çalışan kuyrukları (task queues) için uygundur ve mesajlar liste içinde saklandığı için belirli bir dayanıklılık sağlar. Ancak, çoklu abone (broadcast) özelliği yoktur ve tüketici sayısı arttıkça yönetimi karmaşıklaşır. Redis'in key-space bildirimleri (keyspace notifications) de bir çeşit pub/sub mekanizmasıdır, fakat burada kanallar, veritabanındaki anahtarlara yapılan işlemlerle (SET, DEL gibi) otomatik olarak oluşturulur. Bu özellik, önbellek tutarlılığını sağlamak gibi dahili izleme senaryolarında faydalıdır.

  • Redis Streams: Kalıcı mesaj log'u, consumer grupları, kesin teslimat garantisi. Karmaşık, güvenilir mesajlaşma ve event sourcing için.
  • Redis Lists (BLPOP/BRPOP): Basit mesaj kuyruğu, dayanıklı mesajlar, iş yükü dağıtımı. Basit çalışan kuyrukları için.
  • Harici Mesaj Broker'ları (RabbitMQ, Apache Kafka): Gelişmiş yönlendirme, yüksek dayanıklılık, işlem desteği, sofistike cluster yapıları. Kurumsal düzeyde, karmaşık senaryolar için.

Sonuç olarak, Redis Pub/Sub seçimi bir mimari karardır ve gereksinimlerin net analizine dayanmalıdır. Düşük gecikme süresi ve basitlik en öncelikli gereksinimler ise, ve mesaj kaybı tolere edilebiliyorsa, Redis Pub/Sub mükemmel bir çözüm olabilir. Ancak, sistem dayanıklılık, güvenilir teslimat veya tarihsel mesaj erişimi gerektiriyorsa, Redis Streams veya harici bir mesajlaşma altyapısı değerlendirilmelidir. Seçim, veri kaybının sistem üzerindeki potansiyel etkisi, iş yükünün ölçeği ve operasyonel karmaşıklığın kabul edilebilirliği gibi faktörler göz önünde bulundurularak yapılmalıdır. Doğru araç, işin doğasına bağlıdır.