.net uygulamalarında redis kullanımı

.Net Uygulamalarında Redis Kullanımı

İÇİNDEKİLER

Redis Nedir ?

Redis; açık kaynak, in-memory çalışan nosql veritabanıdır. https://github.com/redis/redis adresinde reposu yer almaktadır.
Yüksek performanslı servis olup, bu özelliğinde C dili ile yazılmış olmasının katkısını yabana atmamak gerekir. Linux dağıtımlarında sorunsuz çalışmaktadır. Redis’in bize sunduğu (en azından uygulamalarınızdaki gözlemlerimiz) avantajları vardır.

Avantajları

  • Yüksek Performans
    in-memory çalıştığı için; verileri sabit diskte tutmak yerine, Ram üzerinde tutar. Veri erişimi Ram seviyesinde olmaktadır.
  • Yedeklilik
    Redis, master-slave mimarisinde çalışır. Etkin servis Master tanımlanan servistir.Slave üzerindeki tüm veriler master’in birer kopyası olarak çalışır.Master servisi fail olduğunda, slave pozisyondaki servis,master pozisyonuna geçer.

  • Veri Tipi Çeşitliliği
    Redis verileri ram üzernde key,value çift olarak tutmaktadır. Verilerdeki key karşılıkları farklı tiplerdeki veriler olabilmektedir. Başlıca desteklediği veri tipleri; String ,List, Set, Hash, Bitmaps, HyperLogLogs

  • Çoklu Dil İmplementasyonu
    Redis, Bir çok programlama dilinde destek vermektedir. Bunlar Java,C#,Python,C,C++,Node.js,R,Go,Ruby. vb.

    Kurumsal Uygulama

Kurumsal uygulama yöntemi olarak docker üzerinde ayağa kaldırmayı tercih ediyoruz. Bu sebeple docker üzerinde redis servisi ayağa kaldırma yöntemlerinden bahsediyor olacağız.

Redis Deployment

Docker üzerinde Redis Kurulumu

Docker; windows 10 işletim sisteminde https://docs.docker.com/docker-for-windows/install/ adresinden indirip kuruyoruz. Docker’in windows için GUI içeren uygulamasıdır. GUI üzerinde image ekleyip yönetebiliyorsunuz. Biz konsol üzerinden işlemlerimizi ilerleteceğiz.
Uygulamayı kurduktan sonra windows komut satırında(cmd) docker komutu ile kurulup kurulmadığını kontrol edebilirsiniz.

C:\>docker 

komut çıktısında; docker komutlarını içeren bir help mesaj çıktısı alınacaktır. Şİmdi gelelim Redis imajını alıp docker üzerinde ayağa kaldırmaya.
Docker’ın kendi sitesinde Redis imajı ile ilgili dokuman mevcuttur. https://hub.docker.com/_/redis adresinden erişime açıktır.

Redis imajını çekelim(105 MB)

c:\docker pull redis

Redis Ayağa Kaldırma

Kısa sürede Redis Containeri oluşturduk. Şimdi Redis’i ayağa kaldıralım. Redis varsayılan olarak 6379 portunu kullanır.

docker run -d -p 6379:6379 redis

Komut detayı :

  • -d : detached modda çalışsın
  • -p 6379:6379 hostun 6379 numaralı portunu container üzerindeki 6379 numaralı porta map et.
    komut başarıyla işlendikten sonra, kurduğumuz docker GUI ekranında redis containerin in-use olduğunu göreceksiniz.

Redis Ayarlar

Redis Network Ayarları

Redis default 6379 portunu kullanır. Host cihazdaki 6379 portunu container’ın 6379 portuna map ediyoruz. Böylelikle cihazın 6379 portuna gelen istekler, Redise yönlendirilecektir. Bu ayarı yapmadıysanız:

C:\>docker inspect ff614abe7f23 --> container ID ya da adı 

komutu ile redis container network ayarlarını gözlemleyebiliriz. Network Settings altında Ports parametrelerinden gereken düzenleme aşağıdaki gibi yapılabilmektedir.

 "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "19af672cb7172912db59b5a964ef489eaad4e7cd64dad78e17960f9e1da001a5",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "6379/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "6379"
                    }
                ]
            },

Redis Konsol

Docker üzerinde Redis Cli Erişim

Docker konsol üzerinde container ile ilgili bilgi almak için;

C:\>docker container ls

komutu uyguladıktan sonra konsolda , kurulu ve çalışan konteynırlar listelenecektir.

C:\>docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                    NAMES
ff614abe7f23   redis     "docker-entrypoint.s…"   9 minutes ago   Up 9 minutes   0.0.0.0:6379->6379/tcp   admiring_morse

görüldüğü gibi Redis imajından oluşturduğumuz container ayakta ve 6379 portunda dinleme yapıyor.admiring_morse adında ve ff614abe7f23 ID’ye sahip bir yapımız var. Şimdi Redis Konsola Docker üzerinden erişim sağlayacağız.

C:\>docker exec -it ff614abe7f23 redis-cli
127.0.0.1:6379>

Yukarıdaki komut seti ile docker üzerinde ID ile belirttiğimiz Redis container konsoluna erişim sağladık. Erişim sağladıktaın sonra redis cli’a bağlanmış oluyoruz.

Test

Redis cli bağlantısından sonra cli üzerinde ilk test çalışmamızı gerçekleştirelim.

127.0.0.1:6379> Set name Test
OK
127.0.0.1:6379> get name
"Test"
127.0.0.1:6379>

Dotnet Uygulamasında Redis İmplementasyonu

.Net Uygulamamızda, Redis client işlemleri için Nuget PM üzerinden ServiceStack.Redis kütüphanesini kullanıyor olacağız.

Senaryo

Birimimiz tarafından geliştirilen açık kaynak yayınlanan Web tabanlı Aktif Dizin Yönetim Uygulamasında, AD veritabanındaki kullanıcı ve cihazları redis’e alıp, sorguları redis üzerinde gerçekleştirmek.

Uygulama

Uygulamamızı Asp.net MVC model-view yapısı üzerinde geliştirdik.
RedisManager > Redis işlemlerini yapacağımız Sınıf

Arayüz tanımlama:

 public interface IRedisManager
    {
        bool IsKeyExist(string key);

        void SetKeyValue(string key, string value);

        string GetKeyValue(string key);

        bool StoreList<T>(string key, T Value, TimeSpan timeout);

        T GetList<T>(string key);


    }

 public class RedisManager:IRedisManager
    {
        RedisEndpoint _redisEndpoint;
 
        public RedisManager()
        {

          
            _redisEndpoint = new RedisEndpoint(_redisHost, _redisPort);

        }

        // Key Redis veritabanında var ise true döner
        public bool IsKeyExist(string key)
        {
            using (var client = new RedisClient(_redisEndpoint))
            {
                return client.ContainsKey(key);
            }
        }

        // Key set edilir
        public void SetKeyValue(string key, string value)
        {

            using (var client = new RedisClient(_redisEndpoint))
            {

                client.SetValue(key, value);
            
            }
        
        }

        // Key karşılık değeri geriye döndürülür.
        public string GetKeyValue(string key )
        {

            using (var client = new RedisClient(_redisEndpoint))
            {

                return client.GetValue(key);
            }

        }

        // Generic yapıda key kontrolü
        public bool StoreList<T>(string key, T Value, TimeSpan timeout)
        {

            try
            {

                using (var client = new RedisClient(_redisEndpoint))
                {

                    client.As<T>().SetValue(key, Value, timeout);
                }
                return true;
            }

            catch (Exception)
            {
                throw;
            }
        
        }

        // Generic: Key karşılık değeri döndürülür.
        public T GetList<T>(string key)
        {

            T result;

            using (var client = new RedisClient(_redisEndpoint))
            {

                var wrapper = client.As<T>();
                result = wrapper.GetValue(key);
            
            }

            return result;
        }
    }

RedisEndpoint Sınıfı, ServiceStack.Redis kütüphanesinden implement edilen, redis servis bağlantısını yapacağımız sınıftır.

RedisClient sınıfı,ServiceStack.Redis kütüphanesinden implement edilen, redis işlemlerini yapan sınıf.

_redisHost = Redis Servisinin İP’si

_redisPort: Redis Port

Redis İşlemleri için sınıfı tanımladıktan sonra, Web Uygulamamızda redis işlemlerine devam edelim.
### Aktif Dizin Kullanıcıları Listeleme

Aktif Dizin veritabanında kayıtlı kullanıcıları , kullanıcı arayüzünde listeleyeceğiz.
redis

İş Planı şu şekilde olacak :

  • Kullanıcı Listesi için uygulama Redis Servisine istek atacak
  • Redis Servisinde UserList Key değeri var ise, Redis Servisinden, GetList() Methodu ile ilgili veriyi alacağız
  • Redis Servisinde UserList key değeri yok ise; Aktif Dizin Veritabanından listeyi alıp, redis’e StoreList methodu ile ekleyeceğiz.
  • Tekrar Redis Servisinden Kullanıcı Listesini isteyeceğiz.
    Görüldüğü gibi senaryonun ektin rolü redis üzerindedir. Tüm sorguları onun üzerinde kontrol edip, yok ise DB’ye erişim sağlıyor olacağız.

Kullanıcı işlemlerini yaptığımız UserController içerisinde ilgili düzenlemeleri yapıyoruz.

  
        public ActionResult KullaniciListele()
        {
            List<UserEntities> userList;
  
           // Kullanıcı Redis'te var mı 
            if (_redisManager.IsKeyExist("UserList"))
            {
                userList = _redisManager.GetList<List<UserEntities>>("UserList");
            }

            else
            {
                var  usersFromServer = KullaniciGetir(); // Aktif dizin veritabanında kullanıcıları getiren method
                _redisManager.StoreList<List<UserEntities>>("UserList",usersFromServer,TimeSpan.MaxValue); //AD DB'den alınan kullanıcı listesi UserList Key adı ile Redise yazılıyor.
                userList = _redisManager.GetList<List<UserEntities>>("UserList"); // Redisten UserList key değer karşılığı çekiliyor.

            }
           
           return View(userList);
        }

Performans

İlgili düzenlemeden sonra sorgu süresi 6sn’den 150 ms seviyesine inmiştir. Redis Servisi cache hizmetinden beklentimizin üzerinde performans karşılığı alınmıştır..

Session Provider olarak Redis

Redis’in muazzam özelliklerinden birisine daha değineceğiz.Redis’i web uygulamalarında session yöneticisi olarak ayarlayabiliyoruz. Böylece sunucu üzerinden bu yükü alıp, redis’e aktarmış oluyoruz.

Örnek Uygulama İle Session Yönetimi

Asp.Net uygulamamızda, Redis ile Session yönetimi için, npm ile RedisSessionStateProvider paketini kurduk.
Session verileri, Redis tarafında Redis Hash veri tipinde saklanır. RedisSessionStateProvider paketini kurduktan sonra web.config dosyası içerisinde, etiketleri arasında “sessionstate” etiketi oluşacaktır. Gereken ayarları burdan yapacağız.
Örnek :

  <sessionState mode="Custom" customProvider="MySessionStateStore">
      <providers>
        <!-- For more details check https://github.com/Azure/aspnet-redis-providers/wiki -->
        <!-- Either use 'connectionString' OR 'settingsClassName' and 'settingsMethodName' OR use 'host','port','accessKey','ssl','connectionTimeoutInMilliseconds' and 'operationTimeoutInMilliseconds'. -->
        <!-- 'throwOnError','retryTimeoutInMilliseconds','databaseId' and 'applicationName' can be used with both options. -->
        <!--
          <add name="MySessionStateStore" 
            host = "127.0.0.1" [String]
            port = "" [number]
            accessKey = "" [String]
            ssl = "false" [true|false]
            throwOnError = "true" [true|false]
            retryTimeoutInMilliseconds = "5000" [number]
            databaseId = "0" [number]
            applicationName = "" [String]
            connectionTimeoutInMilliseconds = "5000" [number]
            operationTimeoutInMilliseconds = "1000" [number]
            connectionString = "<Valid StackExchange.Redis connection string>" [String]
            settingsClassName = "<Assembly qualified class name that contains settings method specified below. Which basically return 'connectionString' value>" [String]
            settingsMethodName = "<Settings method should be defined in settingsClass. It should be public, static, does not take any parameters and should have a return type of 'String', which is basically 'connectionString' value.>" [String]
            loggingClassName = "<Assembly qualified class name that contains logging method specified below>" [String]
            loggingMethodName = "<Logging method should be defined in loggingClass. It should be public, static, does not take any parameters and should have a return type of System.IO.TextWriter.>" [String]
            redisSerializerType = "<Assembly qualified class name that implements Microsoft.Web.Redis.ISerializer>" [String]
          />
        -->
        <add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="127.0.0.1"  accessKey="" ssl="false" />
      </providers>
    </sessionState>
  

Yukarıda yer alan ayarlarda, “add name” etiketi içerisinde gereken ayarı yapıyoruz. Önemli nokta Redis host ve port bilgilerinin belirtilmesi. Port belirtilmez ise default 6379 portunu kullanacaktır. lokalde çalıştığımız için ssl attribute değerini false yaptık.
config tarafı bu kadar. Şimdi gelelim örnek kodlara.
Controller :

  public class HomeController : Controller
    {
        public ActionResult Index()
        {
            Session["Username"] = "Test";
            Session["LoginTime"] = DateTime.Now;
            return View();
        }
    }
 

View :

<!DOCTYPE html>
<html>
<body>
    <div class="container">
       @Session["Username"] | @Session["LoginTime"]
    </div>
</body>
</html>

Redis tarafındaki Key ve data takibi için Another Redis Desktop Manager adlı uygulamayı kullanmaktayız. Bu uygulama üzerinde ilgili oturuma ait verileri görebilmekteyiz.

redisdm

March 15, 2021 tarihinde oluşturuldu.