Aracılığıyla paylaş


ASP.NET Core'da HybridCache kitaplığı

Bu makalede, ASP.NET Core uygulamasında kitaplığın HybridCache nasıl yapılandırılıp kullanılacağı açıklanmaktadır. Kütüphaneye giriş için Önbelleğe Alma Genel Bakış bölümüne bakın.

Kitaplığı al

Microsoft.Extensions.Caching.Hybrid paketini yükleyin.

dotnet add package Microsoft.Extensions.Caching.Hybrid

Hizmeti kaydetme

HybridCache hizmetini bağımlılık enjeksiyonu (DI) kapına çağrılarak ekleyin AddHybridCache:

// Add services to the container.
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthorization();

builder.Services.AddHybridCache();

Yukarıdaki kod, hizmeti varsayılan seçeneklerle kaydeder HybridCache . Kayıt API'si ayrıca seçenekleri ve serileştirmeyi de yapılandırabilir.

Önbellek girdilerini alma ve depolama

HybridCache hizmeti, iki aşırı yüklemeye sahip bir GetOrCreateAsync yöntemi, bir anahtar alarak sağlar.

  • Bir fabrika yöntemi.
  • Durum ve fabrika metodu.

yöntemi, nesneyi birincil önbellekten almayı denemek için anahtarını kullanır. Öğe birincil önbellekte bulunmazsa (önbellek hatası), yapılandırıldıysa ikincil önbelleği denetler. Orada verileri bulamazsa (başka bir önbellek kaçırması durumu), nesneyi veri kaynağından almak için fabrika yöntemini çağırır. Ardından nesneyi hem birincil hem de ikincil önbelleklerde depolar. Nesne birincil veya ikincil önbellekte (önbellek isabeti) bulunursa fabrika yöntemi hiçbir zaman çağrılmaz.

Hizmet, HybridCache belirli bir anahtar için yalnızca bir eşzamanlı çağıranın fabrika yöntemini çağırmasını ve diğer tüm arayanların bu çağrının sonucunu beklemesini sağlar. c1'e geçirilen CancellationToken, tüm eş zamanlı arayanların birleştirilmiş iptalini temsil eder.

Ana GetOrCreateAsync aşırı yük

Çoğu senaryo için durumsuz aşırı yükleme GetOrCreateAsync önerilir. Çağıracak kod nispeten basittir. Bir örnek aşağıda verilmiştir:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            cancellationToken: token
        );
    }

    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

Önbellek anahtarı kılavuzu

key'in GetOrCreateAsync'e geçirildiğinde önbelleğe alınan verileri benzersiz bir şekilde tanımlaması gerekir.

  • Bu verileri kaynağından almak için kullanılan tanımlayıcı değerleri açısından.
  • Uygulamada önbelleğe alınan diğer veriler açısından.

Her iki benzersizlik türü de genellikle tek bir dizede birleştirilmiş farklı parçalardan oluşan tek bir anahtar dize yapmak için dize birleştirme kullanılarak sağlanır. Örneğin:

cache.GetOrCreateAsync($"/orders/{region}/{orderId}", ...);

Veya

cache.GetOrCreateAsync($"user_prefs_{userId}", ...);

Anahtar düzeninin geçerli olduğundan ve verilerin karışmasına yol açmadığından emin olmak çağıranın sorumluluğundadır.

Dış kullanıcı girişini doğrudan önbellek anahtarlarında kullanmaktan kaçının. Örneğin, kullanıcı arabirimlerindeki ham dizeleri önbellek anahtarları olarak kullanmayın. Bunun yapılması, önbelleği rastgele veya anlamsız anahtarlarla doldurmanın neden olduğu yetkisiz erişim veya hizmet reddi saldırıları gibi güvenlik risklerine karşı uygulamanızı kullanıma açabilir. Yukarıdaki geçerli örneklerde , sıra ve kullanıcı tercih verileri açıkça ayrılmıştır ve güvenilen tanımlayıcıları kullanır:

  • orderid ve userId dahili olarak oluşturulan tanımlayıcılardır.
  • region, bilinen bölgelerin önceden tanımlanmış listesinden bir enum veya dize olabilir.

veya /gibi _ belirteçlere hiçbir anlam uygulanmaz. Anahtar değerinin tamamı, opak bir tanımlayıcı dize olarak değerlendirilir. Bu durumda, önbellek işlevlerini değiştirmeden / ve _ atlayabilirsiniz, ancak genellikle belirsizliği önlemek için bir sınırlayıcı kullanılır; örneğin, $"order{customerId}{orderId}" arasında karışıklığa neden olabilir:

  • customerId 123 ile orderId 42
  • customerId 421 ile orderId 23

Yukarıdaki örneklerin her ikisi de önbellek anahtarını order42123oluşturur.

Bu kılavuz, string, HybridCacheve IDistributedCachegibi IMemoryCachetabanlı önbellek API'lerine eşit olarak uygulanır.

Satır içi ilişkilendirilmiş dize söz diziminin (geçerli anahtarların önceki örneklerinde$"...") doğrudan GetOrCreateAsync çağrısının içinde olduğuna dikkat edin. Bu söz dizimi, HybridCachekullanılırken önerilir; pek çok durumda anahtar için bir string ayırma gereksinimini atlayan planlı geliştirmeler yapma imkânı sağlar.

Dikkat edilmesi gereken diğer önemli noktalar

  • Anahtarlar geçerli maksimum uzunluklarla sınırlanabilir. Örneğin, varsayılan HybridCache uygulaması (AddHybridCache(...)aracılığıyla) anahtarları varsayılan olarak 1024 karakterle kısıtlar. Bu sayı, doygunluğu önlemek için önbellek mekanizmalarını atlayan daha uzun anahtarlarla HybridCacheOptions.MaximumKeyLengtharacılığıyla yapılandırılabilir.
  • Anahtarlar geçerli Unicode dizileri olmalıdır. Geçersiz Unicode dizileri geçirilirse, davranış tanımlanmamış olur.
  • gibi IDistributedCacheişlem dışı bir ikincil önbellek kullanırken arka uç uygulaması ek kısıtlamalar uygulayabilir. Varsayımsal bir örnek olarak, belirli bir backend büyük/küçük harfe duyarsız anahtar mantığı kullanabilir. Varsayılan HybridCache (aracılığıyla AddHybridCache(...)), karışıklık saldırılarını veya diğer ad saldırılarını (bit düzeyinde dize eşitliğini kullanarak) önlemek için bu senaryoyu algılar. Ancak bu senaryo yine de çakışan anahtarların üzerine yazılması veya beklenenden daha erken çıkarılmasına neden olabilir.

Alternatif GetOrCreateAsync aşırı yükleme

Alternatif aşırı yükleme, yakalanan değişkenlerden ve örnek başına geri çağırmalardan kaynaklanan bazı ek yükleri azaltabilir, ancak daha karmaşık bir koda neden olabilir. Çoğu senaryoda performans artışı kod karmaşıklığından daha ağır basmıyor. Alternatif aşırı yüklemeyi kullanan bir örnek aşağıda verilmişti:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            (name, id, obj: this),
            static async (state, token) =>
            await state.obj.GetDataFromTheSourceAsync(state.name, state.id, token),
            cancellationToken: token
        );
    }

    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

SetAsync yöntemi

Birçok senaryoda, GetOrCreateAsync gereken tek API'dir. Ancak HybridCache , SetAsync öncelikle almaya çalışmadan bir nesneyi önbellekte depolar.

Anahtara göre önbellek girdilerini kaldırma

Önbellek girdisinin temel verileri süresi dolmadan önce değiştiğinde, girdinin anahtarıyla birlikte çağırarak RemoveAsync girdiyi açıkça kaldırın. Aşırı yükleme, anahtar değerlerin bir koleksiyonunu belirtmenize olanak tanır.

Bir girdi kaldırıldığında, hem birincil hem de ikincil önbelleklerden kaldırılır.

Etikete göre önbellek girdilerini kaldırma

Etiketler, önbellek girdilerini gruplandırmak ve bunları birlikte geçersiz kılmak için kullanılabilir.

çağrısı yaparken GetOrCreateAsyncetiketleri aşağıdaki örnekte gösterildiği gibi ayarlayın:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        var tags = new List<string> { "tag1", "tag2", "tag3" };
        var entryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(1),
            LocalCacheExpiration = TimeSpan.FromMinutes(1)
        };
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            entryOptions,
            tags,
            cancellationToken: token
        );
    }
    
    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

Belirtilen etiketin tüm girdilerini, etiket değeriyle RemoveByTagAsync çağırarak kaldırın. Aşırı yükleme, etiket değerleri koleksiyonu belirtmenize olanak tanır.

Etiket kavramı için ne doğrudan destek ne de IMemoryCacheIDistributedCache vardır, bu nedenle etiket tabanlı geçersiz kılma yalnızca mantıksal bir işlemdir. Yerel veya dağıtılmış önbellekteki değerleri etkin bir şekilde kaldırmaz. Bunun yerine, bu tür etiketlerle veri alırken verilerin hem yerel hem de uzak önbellekten önbellek kaçırma olarak kabul edilmesini sağlar. Değerlerin süresi IMemoryCache ve IDistributedCache'den, yapılandırılan yaşam süresine göre her zamanki gibi tamamlanır.

Tüm önbellek girdilerini kaldırma

Yıldız işareti etiketi (*) joker karakter olarak ayrılmıştır ve tekil değerlere karşı kullanımı yasaktır. Çağırma RemoveByTagAsync("*") , etiket içermeyen veriler bile dahil olmak üzere tümHybridCache verileri geçersiz hale getirme etkisine sahiptir. Tek tek etiketlerde olduğu gibi, bu mantıksal bir işlemdir ve tek tek değerler doğal olarak süresi dolana kadar varolmaya devam eder. Glob stili eşleşmeler desteklenmez. Örneğin, ile RemoveByTagAsync("foo*")başlayan her şeyi kaldırmak için kullanamazsınızfoo.

Etiketle ilgili dikkat edilmesi gereken ek noktalar

  • Sistem kullanabileceğiniz etiket sayısını sınırlamaz, ancak büyük etiket kümeleri performansı olumsuz etkileyebilir.
  • Etiketler boş olamaz, yalnızca boşluk veya ayrılmış değer *olamaz.

Seçenekler

yöntemi genel AddHybridCache varsayılanları yapılandırmak için kullanılabilir. Aşağıdaki örnekte, kullanılabilir seçeneklerden bazılarının nasıl yapılandırılır gösterilmektedir:

// Add services to the container.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
    {
        options.MaximumPayloadBytes = 1024 * 1024;
        options.MaximumKeyLength = 1024;
        options.DefaultEntryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(5),
            LocalCacheExpiration = TimeSpan.FromMinutes(5)
        };
    });

GetOrCreateAsync yöntemi, belirli bir HybridCacheEntryOptions önbellek girdisinin genel varsayılanlarını geçersiz kılmak için bir nesne de alabilir. Bir örnek aşağıda verilmiştir:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        var tags = new List<string> { "tag1", "tag2", "tag3" };
        var entryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(1),
            LocalCacheExpiration = TimeSpan.FromMinutes(1)
        };
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            entryOptions,
            tags,
            cancellationToken: token
        );
    }
    
    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

Seçenekler hakkında daha fazla bilgi için kaynak koduna bakın:

Sınırlar

aşağıdaki özellikleri HybridCacheOptions , tüm önbellek girdilerine uygulanan sınırları yapılandırmanıza olanak sağlar:

  • MaximumPayloadBytes - Önbellek girdisinin en büyük boyutu. Varsayılan değer 1 MB'tır. Bu boyuttaki değerleri depolama girişimleri günlüğe kaydedilir ve değer önbellekte depolanmaz.
  • MaximumKeyLength - Önbellek anahtarının uzunluk üst sınırı. Varsayılan değer 1024 karakterdir. Bu boyuttaki değerleri depolama girişimleri günlüğe kaydedilir ve değer önbellekte depolanmaz.

Serileştirme

İkincil, işlem dışı önbelleğin kullanılması için serileştirme gerekir. Serileştirme, HybridCache servisini kaydetmenin bir parçası olarak yapılandırılır. Türe özgü ve genel amaçlı serileştiriciler, AddSerializer çağrısından zincirlenmiş AddSerializerFactory ve AddHybridCache yöntemleri aracılığıyla yapılandırılabilir. Varsayılan olarak, kütüphane string ve byte[]'i dahili olarak işler ve diğer her şey için System.Text.Json kullanır. HybridCache protobuf veya XML gibi diğer serileştiricileri de kullanabilir.

Aşağıdaki örnek, hizmeti türe özgü bir protobuf serileştiricisi kullanacak şekilde yapılandırır:

// Add services to the container.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
    {
        options.DefaultEntryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromSeconds(10),
            LocalCacheExpiration = TimeSpan.FromSeconds(5)
        };
    }).AddSerializer<SomeProtobufMessage, 
        GoogleProtobufSerializer<SomeProtobufMessage>>();

Aşağıdaki örnek, hizmeti birçok protobuf türünü işleyebilen genel amaçlı bir protobuf seri hale getirici kullanacak şekilde yapılandırır:

// Add services to the container.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
{
    options.DefaultEntryOptions = new HybridCacheEntryOptions
    {
        Expiration = TimeSpan.FromSeconds(10),
        LocalCacheExpiration = TimeSpan.FromSeconds(5)
    };
}).AddSerializerFactory<GoogleProtobufSerializerFactory>();

İkincil önbellek Redis, SQL Server veya Postgres gibi bir veri deposu gerektirir. Azure Cache for Redis kullanmak için, örneğin:

  • Microsoft.Extensions.Caching.StackExchangeRedis paketini yükleyin.

  • bir Redis için Azure Cache örneği oluşturun.

  • Redis örneğine bağlanan bir bağlantı dizesi alın. Azure portalındaki Genel Bakış sayfasında Erişim anahtarlarını göster'i seçerek bağlantı dizesi bulun.

  • bağlantı dizesi uygulamanın yapılandırmasında depolayın. Örneğin, bağlantı dizesinin bölümünde yer aldığı aşağıdaki JSON'a benzeyen bir ConnectionStrings kullanın. <the connection string> ifadesini gerçek bağlantı dizesi ile değiştirin.

    {
      "ConnectionStrings": {
        "RedisConnectionString": "<the connection string>"
      }
    }
    
  • Redis paketinin IDistributedCache sağladığı uygulamayı DI'ye kaydedin. Bunu yapmak için AddStackExchangeRedisCache çağırın ve bağlantı dizesi geçirin. Örneğin:

    builder.Services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = 
            builder.Configuration.GetConnectionString("RedisConnectionString");
    });
    
  • Redis IDistributedCache uygulaması artık uygulamanın DI kapsayıcısından kullanılabilir. HybridCache bunu ikincil önbellek olarak kullanır ve bunun için yapılandırılan seri hale getiriciyi kullanır.

Daha fazla bilgi için bkz . HybridCache serileştirme örnek uygulaması.

Önbellek depolama

Varsayılan olarak HybridCache birincil önbellek depolama alanı için kullanır MemoryCache . Önbellek girdileri işlem içinde depolanır, bu nedenle her sunucu işlemi yeniden başlatıldığında kaybolan ayrı bir önbelleğe sahiptir. Redis, SQL Server veya Postgres gibi ikincil işlem dışı depolama için HybridCache , varsa yapılandırılan IDistributedCache uygulamayı kullanır. Ancak IDistributedCacheuygulaması olmasa bile, HybridCache hizmeti işlem içi önbelleğe alma ve aşırı yüklenme korumasısağlar.

Not

Önbellek girdileri anahtara veya etiketlere göre geçersiz kılındığında, geçerli sunucuda ve ikincil işlem dışı depolamada geçersiz kılınır. Ancak, diğer sunuculardaki bellek içi önbellek etkilenmez.

Performansı iyileştirme

Performansı optimize etmek için HybridCache'ü nesneleri yeniden kullanacak ve byte[] tahsislerinden kaçınacak şekilde yapılandırın.

Nesneleri yeniden kullanma

Örnekleri yeniden kullanarak, HybridCache çağrı başına seri durumdan çıkarmayla ilişkili CPU ve nesne ayırma yükünü azaltabilir. Bu, önbelleğe alınan nesnelerin büyük olduğu veya sık erişildiği senaryolarda performans geliştirmelerine yol açabilir.

Mevcut tipik IDistributedCache kullanan kodda, önbellekten her nesne alındığında seri durumdan çıkarılır. Bu davranış, her eş zamanlı çağıranın nesnenin ayrı bir örneğini aldığı ve diğer örneklerle etkileşim kuramaz olduğu anlamına gelir. Sonuç olarak iş parçacığı güvenliği elde edilir çünkü aynı nesne örneğinde eşzamanlı değişiklik yapılması riski yoktur.

Mevcut HybridCache koddan çok fazla IDistributedCache kullanım uyarlanacağından, HybridCache eşzamanlılık hatalarının oluşmasını önlemek için bu davranışı varsayılan olarak korur. Ancak, aşağıdaki durumlarda nesneler doğal olarak iş parçacığı açısından güvenlidir:

  • Bunlar sabit türler.
  • Kod bunları değiştirmez.

Bu gibi durumlarda, aşağıdaki iki değişikliği de yaparak örnekleri yeniden kullanmanın güvenli olduğunu bildirin HybridCache :

  • Türü sealed olarak işaretliyor. sealed C# dilindeki anahtar sözcük, sınıfın devralınamaz olduğu anlamına gelir.
  • Özniteliği [ImmutableObject(true)] türüne uygulayın. [ImmutableObject(true)] özniteliği, nesne oluşturulduktan sonra nesnenin durumunun değiştirilebileceğini gösterir.

Tahsisatlardan kaçının byte[]

HybridCache ayrıca, tahsislerden kaçınmak için IDistributedCache uygulamaları için byte[] isteğe bağlı API'ler sağlar. Bu özellik, , Microsoft.Extensions.Caching.StackExchangeRedisve Microsoft.Extensions.Caching.SqlServer paketlerinin Microsoft.Extensions.Caching.Postgresönizleme sürümleri tarafından uygulanır. Daha fazla bilgi için bkz. IBufferDistributedCache. Paketleri yüklemek için .NET CLI komutları şunlardır:

dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
dotnet add package Microsoft.Extensions.Caching.SqlServer
dotnet add package Microsoft.Extensions.Caching.Postgres

Özel HybridCache uygulamaları

Soyut sınıfın HybridCache somut bir uygulaması paylaşılan çerçeveye dahil edilir ve bağımlılık ekleme yoluyla sağlanır. Ancak geliştiriciler, örneğin FusionCachegibi API'nin özel uygulamalarını sağlamak veya tüketmekte özgürdür.

Yerel AOT ile Hibrit Önbellek Kullanma

Yerel AOT'ye özgü aşağıdaki hususlar HybridCache için geçerlidir:

  • Serileştirme

    Native AOT, çalışma zamanı yansıma tabanlı serileştirmeyi desteklemez. Özel türleri önbelleğe alırsanız, kaynak oluşturucuları kullanmanız veya kaynak oluşturma gibi System.Text.Json AOT ile uyumlu serileştiricileri açıkça yapılandırmanız gerekir. HybridCache hala geliştirme aşamasındadır ve bunu AOT ile kullanmanın kolaylaştırılması bu geliştirme için yüksek bir önceliktir. Daha fazla bilgi için çekme isteği (pull request) dotnet/extensions#6475 inceleyebilirsiniz.

  • Kırpma

    Önbelleğe aldığınız tüm tiplerin AOT derleyicisi tarafından kırpılmasını engelleyecek şekilde referans edildiğinden emin olun. Serileştirme için kaynak oluşturucuları kullanmak bu gereksinime yardımcı olur. Daha fazla bilgi için bkz. Yerel AOT içinASP.NET Core desteği.

Serileştirmeyi ve kırpmayı doğru ayarlarsanız, HybridCache Yerel AOT'de normal ASP.NET Core uygulamalarında olduğu gibi davranır.

Uyumluluk

Kitaplık HybridCache , .NET Framework 4.7.2 ve .NET Standard 2.0'a kadar eski .NET çalışma zamanlarını destekler.

Ek kaynaklar

Daha fazla bilgi için bkz. HybridCache kaynak kodu