Loading...

.NET ile Cache (In-Memory)


Bu blog yazısı, ".NET'te Cache Kullanımı" serisinin ilk bölümüdür ve küçük-orta ölçekli uygulamalar için ideal olan bellek içi (in-memory) önbelleklemenin temellerini anlatır. Önbellekleme, veritabanı sorguları ve API çağrıları gibi pahalı işlemlerden kaynaklanan performans darboğazlarını gidererek uygulama hızını artırır ve kaynak tüketimini azaltır. Yazı, ASP.NET Core'da IMemoryCache kullanımı ve temel önbellek operasyonlarını örneklerle açıklıyor, ancak uygulamanın ölçeklenmesi durumunda dağıtılmış önbelleğe geçişin gerekliliğine vurgu yapıyor.

.NET'te Cache Kullanımı: In-Memory Cache İle Başlangıç (Cache Serisi Bölüm 1)

Modern yazılım geliştirmenin temel hedeflerinden biri, uygulamaları daha hızlı ve daha verimli hale getirmektir. Kullanıcıların beklemekten hoşlanmadığı bir gerçek; bu nedenle uygulama yanıt sürelerini kısaltmak ve sunucu kaynaklarını optimize etmek hayati öneme sahiptir. Veritabanı sorguları, API çağrıları veya yoğun hesaplamalar gibi sıkça tekrarlanan işlemler, uygulamanızın performansında darboğazlar yaratabilir. İşte bu tür senaryolarda önbellekleme (caching), imdadımıza yetişen güçlü bir tekniktir.

.NET'te Cache Kullanımı serimizin bu ilk bölümünde, önbelleklemenin temel prensiplerini ve özellikle küçük ve orta ölçekli uygulamalar için ideal olan bellek içi (in-memory) önbellekleme yöntemini ele alacağız. In-memory cache'in ne olduğunu, neden gerekli olduğunu, sağladığı faydaları, yaygın kullanım alanlarını ve ASP.NET Core uygulamalarınızda nasıl kolayca kullanabileceğinizi basit bir örnekle açıklayacağız.

Cache Nedir ve Neden Gereklidir?

Cache, verilerin daha hızlı erişim için geçici olarak depolandığı bir bellek alanıdır. Bir veri ilk kez istendiğinde, hem kullanıcıya sunulur hem de önbelleğe alınır. Aynı veri bir sonraki istendiğinde, kaynak veritabanından veya harici bir servisten tekrar çekilmek yerine doğrudan önbellekten, yani çok daha hızlı bir şekilde sunulur.

Önbellekleme, bir uygulamanın performansını ve genel kullanıcı deneyimini doğrudan etkileyen birçok avantaj sunar:

  • Performans İyileştirmesi: Veri erişim süreleri önemli ölçüde kısalır. Bellekteki verilere erişim, diske veya ağa yapılan çağrılardan kat kat daha hızlıdır.

  • Kaynak Tüketiminin Azalması: Veritabanına veya harici API'lere yapılan pahalı çağrıların sayısını azaltarak, bu kaynaklar üzerindeki yükü düşürürsünüz. Bu, sunucu maliyetlerini düşürebilir ve sistemin daha fazla eşzamanlı isteği yönetmesine olanak tanır.

  • Kullanıcı Deneyimi: Uygulama, kullanıcının isteklerine daha hızlı yanıt verir, bu da daha akıcı ve tatmin edici bir deneyim sağlar.

  • Ağ Trafiği Azalması: Özellikle uzak servislere yapılan tekrarlayan çağrılar için önbellekleme, gereksiz ağ trafiğini azaltır.

In-Memory Cache Nedir?

In-memory cache, uygulamanın kendi RAM'inde (belleğinde) verileri depolayan bir önbellek türüdür. Her uygulama örneği (örneğin bir web sunucusundaki her süreç), kendi in-memory cache'ini yönetir. Bu, onu tek sunuculu uygulamalar veya uygulamaların her örneğinin kendi önbellek verisine sahip olmasının bir sakınca yaratmadığı senaryolar için hızlı ve kullanımı kolay bir seçenek haline getirir.

In-memory cache'in faydaları:

  • Çok Hızlı Erişim: Veriler aynı süreç belleğinde olduğu için erişim hızı inanılmaz derecede yüksektir.

  • Kolay Kurulum ve Kullanım: Ek bir sunucu veya altyapı gerektirmez, doğrudan uygulama kodunuzda yapılandırılır ve kullanılır.

  • Düşük Gecikme: Ağ gecikmesi (network latency) söz konusu değildir.

In-memory cache'in sınırlamaları:

  • Uygulama Örneğine Bağlılık: Her uygulama örneğinin kendi önbelleği vardır. Uygulama birden fazla sunucuda çalışıyorsa, farklı sunuculardaki aynı verinin farklı versiyonları olabilir (veri tutarsızlığı).

  • Geçici Depolama: Uygulama yeniden başlatıldığında veya çöktüğünde önbellekteki veriler kaybolur.

  • Bellek Limitleri: Sunucunun fiziksel belleği ile sınırlıdır. Büyük veri kümelerini önbelleğe almak bellek yetersizliğine neden olabilir.

Yaygın In-Memory Cache Kullanım Alanları

In-memory cache, özellikle aşağıdaki senaryolarda yaygın olarak kullanılır:

  • Küçük ve Orta Ölçekli Uygulamalar: Dağıtılmış bir mimariye ihtiyaç duymayan veya veri tutarsızlığının kritik olmadığı tek sunuculu uygulamalar.

  • Sık Erişilen Statik Veriler: Uygulama ayarları, sabit konfigürasyon değerleri, ülke listeleri gibi nadiren değişen veriler.

  • Kısa Süreli Önbellekleme: Çok kısa süreliğine önbelleğe alınması gereken, performansı kritik olan ancak çok hızlı değişen veriler.

  • Per-Request Cache: Bir HTTP isteği boyunca geçerli olan ve sonra atılacak veriler (ancak bunun için genellikle Request Scoped servisler daha uygundur).

ASP.NET Core ile In-Memory Caching Kullanımı

ASP.NET Core, IMemoryCache arayüzü ve Microsoft.Extensions.Caching.Memory paketi aracılığıyla varsayılan olarak dahili bir in-memory cache mekanizması sunar.

İşte basit bir ASP.NET Core uygulamasında in-memory cache'i nasıl kullanacağınıza dair bir örnek:

1. Servis Konfigürasyonu (Program.cs):

In-memory cache servisini uygulamanıza eklemeniz yeterlidir.

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Caching.Memory; // Gerekli using

var builder = WebApplication.CreateBuilder(args);

// In-memory cache servisini ekle
builder.Services.AddMemoryCache();

// Diğer servisler
builder.Services.AddControllersWithViews();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// HTTP İstek İşleme Hattını Yapılandırma
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllers(); // Controller'ları haritala
app.MapFallbackToFile("index.html"); // SPA uygulamaları için

app.Run();

2. Cache Kullanımı (Örnek Bir Web API Controller'ı):

Bir controller içinde IMemoryCache arayüzünü enjekte ederek cache işlemlerini gerçekleştirebilirsiniz.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MyWebApp.Controllers
{
    // Örnek bir veri modeli
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }

    [ApiController]
    [Route("api/[controller]")]
    public class ProductsController : ControllerBase
    {
        private readonly IMemoryCache _cache;

        // IMemoryCache'i constructor injection ile alıyoruz
        public ProductsController(IMemoryCache memoryCache)
        {
            _cache = memoryCache;
        }

        [HttpGet("get-products")]
        public async Task<IActionResult> GetProducts()
        {
            string cacheKey = "ProductList";
            List<Product> products;

            // Cache'te ürün listesi var mı kontrol et
            if (!_cache.TryGetValue(cacheKey, out products))
            {
                // Cache'te yoksa, veritabanından veya harici bir kaynaktan çek
                // Bu kısım normalde pahalı bir veritabanı çağrısı veya API isteği olur.
                // Simülasyon için 3 saniye bekletiyoruz.
                await Task.Delay(3000); 
                products = new List<Product>
                {
                    new Product { Id = 1, Name = "Laptop", Price = 1200, Category = "Electronics" },
                    new Product { Id = 2, Name = "Mouse", Price = 25, Category = "Peripherals" },
                    new Product { Id = 3, Name = "Keyboard", Price = 75, Category = "Peripherals" },
                    new Product { Id = 4, Name = "Monitor", Price = 300, Category = "Electronics" }
                };

                // Veriyi cache'e ekle
                // SetAbsoluteExpiration: Öğenin eklenme anından itibaren belirli bir süre sonra önbellekten kaldırılması.
                // SetSlidingExpiration: Öğeye en son erişilme anından itibaren belirli bir süre içinde tekrar erişilmezse önbellekten kaldırılması.
                _cache.Set(cacheKey, products, new MemoryCacheEntryOptions()
                    .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)) // 5 dakika sonra kesin olarak kaldır
                    .SetSlidingExpiration(TimeSpan.FromMinutes(2))); // 2 dakika içinde erişilmezse kaldır

                return Ok(new { Source = "Database/API", Data = products, FetchedAt = DateTime.Now });
            }
            else
            {
                // Cache'te varsa, doğrudan cache'ten oku
                return Ok(new { Source = "In-Memory Cache", Data = products, FetchedAt = DateTime.Now });
            }
        }

        [HttpGet("clear-products-cache")]
        public IActionResult ClearProductsCache()
        {
            string cacheKey = "ProductList";
            _cache.Remove(cacheKey); // Belirli bir anahtarı önbellekten sil
            return Ok("ProductList cache temizlendi.");
        }
    }
}

Bu örnekte:

  • AddMemoryCache() ile bellek içi önbellek servisini etkinleştiriyoruz.

  • IMemoryCache'i controller'a enjekte ediyoruz.

  • TryGetValue metodu ile verinin önbellekte olup olmadığını kontrol ediyoruz.

  • Veri yoksa, simüle edilmiş bir kaynaktan çekiyor (3 saniye gecikme ile) ve Set metodu ile önbelleğe ekliyoruz. Burada hem AbsoluteExpiration (kesin sona erme) hem de SlidingExpiration (kayan sona erme) kullanarak önbellek öğesinin yaşam süresini yönetiyoruz.

  • Veri varsa, doğrudan önbellekten dönüyoruz.

  • Ayrıca, belirli bir cache anahtarını Remove metodu ile nasıl sileceğinizi de gösteriyoruz.

Sonuç

Bellek içi önbellekleme, .NET uygulamalarınıza hızlı ve kolay bir performans artışı sağlamak için harika bir başlangıç noktasıdır. Özellikle tek sunuculu uygulamalar ve kritik olmayan veri tutarlılığı gereksinimleri olan senaryolar için idealdir. Ancak, uygulamanız ölçeklendikçe veya veri tutarlılığı daha kritik hale geldikçe, dağıtılmış önbellek çözümlerine (Redis, Couchbase gibi) geçiş yapmayı düşünmeniz gerekecektir.

Bu blog yazısı, .NET'te Cache Kullanımı serimizin ilk adımıydı. Serimizin sonraki bölümlerinde dağıtılmış önbellekleme çözümlerini ve gelişmiş önbellekleme stratejilerini daha derinlemesine inceleyeceğiz. Uygulamanızın performansını optimize etme yolculuğunuzda bize katılın!