Redis Pub/Sub ve .NET 6 ile Cache Yönetimi

Enes BABAOĞLU
inventiv
4 min readMay 25, 2023

--

Redis Nedir?

Redis, açık kaynaklı ve in-memory veri yapısı sunan bir veritabanı yönetim sistemidir. “Remote Dictionary Server” kelimelerinin kısaltması olan Redis, verileri hızlı bir şekilde okuma ve yazma yeteneğine sahiptir.

Redis, anahtar-değer (key-value) tabanlı bir veri modeli kullanır. Dizeler, sayılar, listeler, kümeler (set), sıralı kümeler (sorted set) gibi birçok farklı veri türünü destekler ve bu yapıları bellekte saklar.

Ayrıca, pub/sub (yayın/abonelik) mekanizması, Client-side caching gibi diğer özellikleriyle birlikte gelir.

Redis, genel olarak hız, ölçeklenebilirlik ve esneklik sağlayarak, birçok farklı uygulama senaryosu için ideal bir veritabanı yönetim sistemidir.

Bazı kullanım çeşitleri aşağıdaki gibidir :

  1. Yüksek Performanslı Veri Depolama
  2. Önbellekleme (Caching)
  3. Oturum Yönetimi
  4. Kuyruk Yönetimi
  5. Gerçek Zamanlı Mesajlaşma

Biz bu yazımızda Gerçek Zamanlı Mesajlaşma(Pub/Sub) kullanım şeklini anlatacağız.

Redis Kurulumu ve Kullanımı

Redis kurulumunu docker üzerinden yapabiliriz. Öncelikle cmd açılır ve aşağıdaki komut çalıştırılır. Bu komutun çalışması için docker yüklü olmalıdır.

docker run --rm -p 6379:6379 --name rediscontainer -d redis

Sonrasında redisi ayağa kaldırmak için aşağıdaki komut çalıştırılır.

redis-cli -h localhost -p 6379

Ping yazılarak çalışıp çalışmadığı kontrol edilebilir.

Artık Redisi kullanmaya hazırız. Aşağıdaki gibi denemeler yapabilirsiniz.

Örnek komutlar

Redis Pub/Sub Nedir?

Pub/sub client’ların birbirlerinin yayınladıkları bilgilere ulaşmaları için kullanılan bir yöntemdir. Bir client belirli kanallara üye olup, bu kanallara mesaj gönderebilir. Bu kanallara üye olan clientlar da gönderilen mesajlara ulaşabilir. Aktif üyelikleri bulunduğu sürece her client bildirimleri almaya devam eder.

Bunu toplu mesaj attığımız mail gruplarına benzetebilirsiniz. Bir mail grubuna attığınız mesaj, ona subscribe olan tüm mail adreslerine gidecektir.

Burada devreye publisherlar ve subscriberlar girmektedir.

Publisher : Mesajlar bir kanala(CHANNEL) gönderilir. Kanallara gönderme kısmı publisher ile yapılır.

Subscriber : Kanalları subscriber dinler sonrasında da bu kanallara gelen mesajları alarak gerekli işlemleri yapar.

Bir kanala ait birden fazla publisher ve subscriber olabilir.

Redis CLI Pub/Sub Örnekleri

CLI da kullanılan Komutlar PUBLISH ve SUBSCRIBE ’dır.

Aşağıdaki gibi SUBSCRIBER oluşturarak PUBLISHER ile attığınız mesajları görebilirsiniz.

Subscriber oluştururken hangi kanalı dinleyeceği bilgisi verilmelidir.(TestChannel)

Sonrasında bu kanala bir adet mesaj Publish edilir. Burada farklı bir cli açmak gereklidir.

Aşağıda görüldüğü üzere Publish ettiğimiz her mesaj subscriber tarafıdan dinlenerek gösterilmektedir.

Birden fazla Subscriber oluşturarak onlarında aynı mesajları almasını sağlayabilirsiniz.

.NET 6 Cache Yönetim Implementasyonu

Redis Pub/Sub kurgusunu ApplicationCache yönetiminde kullandık. Bu bize cache te tutulan bilgiler de herhangi bir değişiklik durumunda sadece değişen client da değil, diğer clientlarda da bu değişikliğin yapılmasını sağladı.

İlk olarak redis için StackExchange.Redis kütüphanesini projeye dahil ettik.

Sonrasında CacheManager class ı oluşturduk ve publish bu classta gerçekleştirdik. Bu işlemi generic yapabilmek adına T cinsinden bir object verdik. Bu metod kanal ismini ve gönderilen T cinsinden veriyi içermektedir.

public class CacheManager : ICacheManager
{
private readonly IRedisCacheClient _redisCacheClient;
private readonly ILogger<CacheManager> _logger;
private readonly IRedisDatabase _redisDatabase;

public CacheManager(IRedisCacheClient redisCacheClient, ILogger<CacheManager> logger)
{
_redisCacheClient = redisCacheClient;
_logger = logger;
_redisDatabase = _redisCacheClient.GetDbFromConfiguration();
}
public void Publish<T>(RedisChannel channel, T message)
{
try
{
_redisDatabase.PublishAsync(channel, message);
}
catch (Exception e)
{
_logger.LogCritical("Redis Publish Error : " + e.ToString());
}
}
}

Subscriber tanımlarını ayrı bir sınıfta gerçekleştirerek. Cache yönetimi için gerekli olan cache silme, ekleme ve güncelleme işlemleri için subscriberlar oluşturduk.

Aşağıdaki örnekte olduğu gibi InvalidateCacheRedisSubscriber InvalidateApplicationCache kanalını dinleyerek cache silme işlemini gerçekleştirir.

   public interface IRedisSubscriber
{
Task Subscribe();
}

public class InvalidateCacheRedisSubscriber : IRedisSubscriber
{
private readonly IRedisDatabase _redisDatabase;
private readonly IApplicationCache _applicationCache;

public InvalidateCacheRedisSubscriber(IRedisCacheClient redisCacheClient, IApplicationCache applicationCache)
{
_applicationCache = applicationCache;
_redisDatabase = redisCacheClient.GetDbFromConfiguration();
}
public Task Subscribe()
{
return _redisDatabase.SubscribeAsync<string>("InvalidateApplicationCache",
key =>
{
Console.WriteLine("Key : " + key);
var type = (CacheTypes)Enum.Parse(typeof(CacheTypes), key);
_applicationCache.Type(type).Clear();

return Task.CompletedTask;
});
}
}

Uygulama başlarken her clientta çalışmasını sağlayacak şekilde ayağa kalkmasını sağladık. Bunu Program.cs classında yaptık.

public static class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();

InitializeRedisSubscribers(host);

host.Run();
}

private static void InitializeRedisSubscribers(IHost host)
{
var redisSubscribers = host.Services.CreateScope().ServiceProvider.GetServices<IRedisSubscriber>();

foreach (var redisSubscriber in redisSubscribers)
{
redisSubscriber.Subscribe();
}
}
}

Ve işlem yapılacak cacheler için publish metodu ile bu kanallara mesaj göndermesini sağladık.

InvalidateApplicationCache kanalına silinecek cache tipinin ismini gönderiyoruz.

public class ApplicationCacheService
{
public BaseResponse InvalidateApplicationCache(CacheTypes type)
{
_cacheManager.Publish("InvalidateApplicationCache", type.ToString());

return new BaseResponse(
$" {type} cache deleted.");

}
}

SONUÇ

Uygulamalarınızda bu yöntemi uygulayarak cache yönetimini sağlayabilirsiniz. Bununla birlikte sadece bu amaçla değil dağıtık sistemlerde veri yönetimi içinde kullanılabilir.

Umarım faydalı bir yazı olmuştur. Katkılarından dolayı Ahmet Hüzeyfe Demir’ e teşekkür ederim.

Kaynakça

https://redis.io/docs/manual/pubsub/

--

--