Distribuerad cachelagring i ASP.NET Core

Av Mohsin Nasir och smandia

Note

Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i .NET 10-versionen av den här artikeln.

Warning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. Den aktuella versionen finns i .NET 10-versionen av den här artikeln.

En distribuerad cache är en cache som delas av flera appservrar. Cachen underhålls vanligtvis som en extern tjänst för de appservrar som har åtkomst till den. En distribuerad cache kan förbättra prestanda och skalbarhet för en ASP.NET Core app, särskilt när en molntjänst eller en servergrupp är värd för appen.

En distribuerad cache har flera fördelar jämfört med andra cachelagringsscenarier där cachelagrade data lagras på enskilda appservrar.

När cachelagrade data distribueras, data:

  • Är sammanhängande (konsekvent) mellan begäranden till flera servrar.
  • Överlever omstarter av servern och appdistributioner.
  • Använder inte lokalt minne.

Konfiguration av distribuerad cache är implementeringsspecifik. Den här artikeln beskriver hur du konfigurerar distribuerade SQL Server-, Redis- eller Postgres-cacheminnen. Implementeringar som inte är Microsoft är också tillgängliga, till exempel NCache (NCache på GitHub), Azure Cosmos DB och Postgres. Oavsett vilken implementering som väljs interagerar appen med cachen med hjälp IDistributedCache av gränssnittet.

Visa eller ladda ned exempelkod (hur du laddar ned)

Warning

Den här artikeln använder en lokal databas som inte kräver att användaren autentiseras. Produktionsappar bör använda det säkraste tillgängliga autentiseringsflödet. Mer information om autentisering för distribuerade test- och produktionsappar finns i Säkra autentiseringsflöden.

Prerequisites

Lägg till en paketreferens för den distribuerade cacheprovidern som används:

Använda IDistributedCache-gränssnittet

Gränssnittet IDistributedCache innehåller följande metoder för att manipulera objekt i implementeringen av distribuerad cache:

  • Get, GetAsync: Accepterar en strängnyckel och hämtar ett cachelagrat objekt som en byte[] matris om det finns i cacheminnet.
  • Set, SetAsync: Lägger till ett objekt (som byte[] matris) i cachen med hjälp av en strängnyckel.
  • Refresh, RefreshAsync: Uppdaterar ett objekt i cacheminnet baserat på dess nyckel och återställer den glidande tidsgränsen för förfallotid (om någon).
  • Remove, RemoveAsync: Tar bort ett cacheobjekt baserat på dess strängnyckel.

Upprätta distribuerade cachelagringstjänster

Registrera en implementering av IDistributedCache i filen Program.cs . Följande ramverksbaserade implementeringar beskrivs i den här artikeln:

Distribuerad Redis-cache

Den distribuerade Redis-cachen ger bästa prestanda och rekommenderas för produktionsappar. Redis är ett minnesinternt datalager med öppen källkod, som ofta används som en distribuerad cache. Du kan konfigurera en Azure Cache for Redis för en Azure-värdbaserad ASP.NET Core-app och använda en Azure Cache for Redis för lokal utveckling. För mer information, se Översikt över cacherekommendationer.

En app konfigurerar cacheimplementeringen med en RedisCache instans genom att anropa AddStackExchangeRedisCache metoden. Använd metoden för cachelagring av AddStackExchangeRedisOutputCache utdata.

  1. Skapa en instans av Azure Cache for Redis.

  2. Kopiera den primära anslutningssträngen (StackExchange.Redis) till Konfiguration.

    • För lokal utveckling: Spara anslutningssträngen med Secret Manager.

    • För Azure: Spara reťazec pripojenia i ett säkert arkiv, till exempel Azure Key Vault.

Följande kod aktiverar Azure Cache for Redis:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

Koden ovan förutsätter att den primära anslutningssträngen (StackExchange.Redis) sparas i konfigurationen med det nyckelnamnet MyRedisConStr.

Mer information finns i Azure Managed Redis.

En diskussion om alternativa metoder för en lokal Redis-cache finns i GitHub /dotnet/aspnetcore-problem #19542.

Distribuerad minnescache

Den distribuerade minnescachen (AddDistributedMemoryCache) är en ramverksbaserad implementering av IDistributedCache som lagrar objekt i minnet. Den distribuerade minnescachen är dock inte en faktisk distribuerad cache. Appinstansen lagrar de cachelagrade objekten på servern där appen körs.

Den distribuerade minnescachen är en användbar implementering för utvecklings- och testscenarier. Det är också användbart för en enskild server i ett produktionsscenario där minnesförbrukning inte är ett problem. Implementering av den distribuerade minnescachen abstraherar cachelagrad datalagring. Det gör det möjligt att implementera en sann distribuerad cachelagringslösning i framtiden om flera noder eller feltolerans blir nödvändiga.

Exempelappen använder det distribuerade minnescachen när appen körs i Development miljön i Program.cs-filen .

builder.Services.AddDistributedMemoryCache();

Distribuerad SQL Server cache

Den distribuerade SQL Server cacheimplementeringen (AddDistributedSqlServerCache) gör att den distribuerade cachen kan använda en SQL Server databas som lagringsplats. Om du vill skapa en SQL Server-cachelagrad objekttabell i en SQL Server-instans kan du använda sql-cache verktyget. Verktyget skapar en tabell med det namn och schema som du anger.

Skapa en tabell i SQL Server genom att sql-cache create köra kommandot . Ange SQL Server-instansen (Data Source), databasen (Initial Catalog), schemat (till exempel dbo) och tabellnamnet (till exempel TestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

När verktyget lyckas loggas ett meddelande:

Table and index were created successfully.

Tabellen som skapades av sql-cache verktyget har följande schema:

Screenshot som visar schemat för en SQL Server cachetabell som skapats med kommandot sql-cache create.

Note

En app bör ändra cachevärden med hjälp av en instans av IDistributedCache, inte en instans av SqlServerCache.

Exempelappen SqlServerCache implementerar klassen i en icke-utvecklingsmiljö (Development) i filen Program.cs :

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

Egenskaper som ConnectionString (och valfritt SchemaName och TableName) lagras vanligtvis utanför källkontrollen. Till exempel Secret Manager eller appsettings.json eller appsettings.{ Environment}.json fil kan lagra egenskaperna. Connection string kan innehålla autentiseringsuppgifter som ska hållas borta från källkontrollsystem.

Mer information finns i SQL Database on Azure.

Distribuerad Postgres-cache

Azure Database for PostgreSQL kan användas som ett distribuerat cachelagringslager via IDistributedCache gränssnittet. Azure Database for PostgreSQL är ett fullständigt hanterat, AI-redo DBaaS-erbjudande (Database-as-a-Service) som bygger på PostgreSQL-motorn med öppen källkod. Designen stöder verksamhetskritiska arbetsbelastningar med förutsägbar prestanda, robust säkerhet, hög tillgänglighet och sömlös skalbarhet.

När du har installerat NuGet-paketet Microsoft.Extensions.Caching.Postgres konfigurerar du din distribuerade cache enligt följande:

  1. Registrera tjänsten.

    using Microsoft.Extensions.DependencyInjection;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Register the Postgres distributed cache.
    builder.Services.AddDistributedPostgresCache(options => {
       options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
       options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
       options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
       options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
       options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
    
       // Optional: Configure expiration settings.
    
       var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
       if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
           options.ExpiredItemsDeletionInterval = interval;
       }
    
       var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
       if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
           options.DefaultSlidingExpiration = sliding;
       }
    });
    
    var app = builder.Build();
    
  2. Använd cachen.

    public class MyService {
        private readonly IDistributedCache _cache; 
    
        public MyService(IDistributedCache cache) {
            _cache = cache;
        }
    
        public async Task<string> GetDataAsync(string key) {
            var cachedData = await _cache.GetStringAsync(key);
    
            if (cachedData == null) {
    
                // Fetch the data from source.
                var data = await FetchDataFromSource();
    
                // Cache the data with options.
                var options = new DistributedCacheEntryOptions {
                   AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                   SlidingExpiration = TimeSpan.FromMinutes(5)
                };
    
                await _cache.SetStringAsync(key, data, options);
                return data;
            }
    
            return cachedData;
        }
    }
    

Distribuerad NCache-cache

NCache är en distribuerad cache med öppen källkod som utvecklats internt i .NET. NCache fungerar både lokalt och konfigurerat som ett distribuerat cachekluster för en ASP.NET Core-app som körs i Azure eller på andra värdplattformar.

Information om hur du installerar och konfigurerar NCache på den lokala datorn finns i komma igång-guiden.

Så här konfigurerar du NCache:

  1. Installera nuget-paketet NCache SDK, som stöder NCache Opensource för .NET Framework- och .NET Core-appar.

  2. Konfigurera cacheklustret i klientkonfigurationen (filen client.ncconf ).

  3. Lägg till följande kod i filen Program.cs :

builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Distribuerad Azure Cosmos DB cache

Azure Cosmos DB kan konfigureras i ASP.NET Core som en sessionstillståndsprovider med hjälp av gränssnittet IDistributedCache. Azure Cosmos DB är en fullständigt hanterad NoSQL- och relationsdatabas för modern apputveckling som erbjuder hög tillgänglighet, skalbarhet och åtkomst till data med låg svarstid för verksamhetskritiska program.

När du har installerat Microsoft. Extensions.Caching.Cosmos NuGet-paketet konfigurerar du en Azure Cosmos DB distribuerad cache. Du kan använda en befintlig Azure Cosmos DB-klient eller skapa en ny, enligt beskrivningen i följande avsnitt.

Mer information finns i Microsoft Caching Extension med Azure Cosmos DB, GitHubs lagringsplats README-fil för NuGet-paketet.

Återanvänd en befintlig klient

Det enklaste sättet att konfigurera en distribuerad cache är genom att återanvända en befintlig Azure Cosmos DB-klient. I det här fallet tas inte instansen CosmosClient bort när providern tas bort.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.CosmosClient = existingCosmosClient;
    cacheOptions.CreateIfNotExists = true;
});

Skapa en ny klient

Alternativt kan du instansiera en ny klient. I det här fallet tas instansen CosmosClient bort när providern tas bort.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
    cacheOptions.CreateIfNotExists = true;
});

Använda den distribuerade cachen

Om du vill använda IDistributedCache gränssnittet begär du en instans av IDistributedCache i appen. Instansen tillhandahålls av beroendeinmatning (DI).

När exempelappen startar matas instansen IDistributedCache in i filen Program.cs . Den aktuella tiden cachelagras genom att använda gränssnittet IHostApplicationLifetime. (Mer information finns i .NET Allmän värd: IHostApplicationLifetime.)

app.Lifetime.ApplicationStarted.Register(() =>
{
    var currentTimeUTC = DateTime.UtcNow.ToString();
    byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
    var options = new DistributedCacheEntryOptions()
        .SetSlidingExpiration(TimeSpan.FromSeconds(20));
    app.Services.GetService<IDistributedCache>()
                              .Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

Exempelappen injicerar instansen IDistributedCache i objektet IndexModel för att användas av Index-sidan.

Varje gång indexsidan läses in kontrolleras cacheminnet för den cachelagrade tiden med hjälp av OnGetAsync metoden. Om den cachelagrade tiden inte har upphört att gälla visas tiden. Om 20 sekunder har förflutit sedan den senaste gången den cachelagrade tiden användes (senaste gången den här sidan lästes in) visar sidan meddelandet Cached Time Expired (Cached Time Expired).

Uppdatera omedelbart den cachelagrade tiden till den aktuella tiden genom att välja alternativet Återställ cachelagrad tid . Den här åtgärden utlöser OnPostResetCachedTime hanteringsmetoden.

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string? CachedTimeUTC { get; set; }
    public string? ASP_Environment { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }

        ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        if (String.IsNullOrEmpty(ASP_Environment))
        {
            ASP_Environment = "Null, so Production";
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Note

Du behöver inte använda en livstid av Singleton eller Scoped för IDistributedCache-instanser med en inbyggd implementering.

Du kan också skapa en IDistributedCache instans där du kan behöva en i stället för att använda DI. Att skapa en instans i kod kan dock göra koden svårare att testa och strider mot principen explicita beroenden.

Granska cacherekommendationer

När du bestämmer vilken implementering av IDistributedCache gränssnittet som är bäst för din app bör du tänka på följande:

  • Befintlig infrastruktur
  • Prestandakrav
  • Cost
  • Teamupplevelse

Cachelagringslösningar förlitar sig vanligtvis på minnesintern lagring för att ge snabb hämtning av cachelagrade data, men minnet är en begränsad resurs och kostsamt att expandera. Lagra endast vanliga data i en cache.

För de flesta appar ger en Redis-cache högre dataflöde och lägre svarstid än en SQL Server-cache. Benchmarking rekommenderas dock för att fastställa prestandaegenskaperna för cachelagringsstrategier.

Om SQL Server är det distribuerade cachelagringsarkivet, och cache- och appdatalagringen/hämtningen använder samma databas, kan prestandan minskas. Den rekommenderade metoden är att använda en dedikerad SQL Server instans för det distribuerade cachelagringsarkivet.

En distribuerad cache är en cache som delas av flera appservrar, som vanligtvis underhålls som en extern tjänst till de appservrar som har åtkomst till den. En distribuerad cache kan förbättra prestanda och skalbarhet för en ASP.NET Core-app, särskilt när appen hanteras av en molntjänst eller en servergrupp.

En distribuerad cache har flera fördelar jämfört med andra cachelagringsscenarier där cachelagrade data lagras på enskilda appservrar.

När cachelagrade data distribueras, data:

  • Är sammanhängande (konsekvent) mellan begäranden till flera servrar.
  • Överlever omstarter av servern och appdistributioner.
  • Använder inte lokalt minne.

Konfiguration av distribuerad cache är implementeringsspecifik. Den här artikeln beskriver hur du konfigurerar distribuerade SQL Server-, Redis- och Postgres-cacheminnen. Implementeringar från tredje part är också tillgängliga, till exempel NCache (NCache på GitHub). Oavsett vilken implementering som väljs interagerar appen med cachen med hjälp av IDistributedCache gränssnittet.

Visa eller ladda ned exempelkod (hur du laddar ned)

Prerequisites

Lägg till en paketreferens för den distribuerade cacheprovidern som används:

IDistributedCache-gränssnitt

Gränssnittet IDistributedCache innehåller följande metoder för att manipulera objekt i implementeringen av distribuerad cache:

  • Get, GetAsync: Accepterar en strängnyckel och hämtar ett cachelagrat objekt som en byte[] matris om det finns i cacheminnet.
  • Set, SetAsync: Lägger till ett objekt (som byte[] matris) i cacheminnet med hjälp av en strängnyckel.
  • Refresh, RefreshAsync: Uppdaterar ett objekt i cacheminnet baserat på dess nyckel och återställer den glidande tidsgränsen för förfallotid (om någon).
  • Remove, RemoveAsync: Tar bort ett cacheobjekt baserat på dess strängnyckel.

Upprätta distribuerade cachelagringstjänster

Registrera en implementering av IDistributedCache i Program.cs. Exempel på ramverksbaserade implementeringar som beskrivs i det här avsnittet är:

Distribuerad Redis Cache

Vi rekommenderar att produktionsappar använder Distributed Redis Cache eftersom det är den mest högpresterande. Mer information finns i Rekommendationer.

Redis är ett minnesinternt datalager med öppen källkod, som ofta används som en distribuerad cache. Du kan konfigurera en Azure Redis Cache för en Azure-värdbaserad ASP.NET Core-app och använda en Azure Redis Cache för lokal utveckling.

En app konfigurerar cacheimplementeringen med hjälp av en RedisCache instans (AddStackExchangeRedisCache).

  1. Skapa en Azure Cache for Redis.
  2. Kopiera den primära anslutningssträngen (StackExchange.Redis) till Konfiguration.
    • Lokal utveckling: Spara anslutningssträngen med Secret Manager.
    • Azure: Spara anslutningssträngen i ett säkert arkiv, till exempel Azure Key Vault

Följande kod aktiverar Azure Cache for Redis:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

Föregående kod förutsätter att den primära anslutningssträngen (StackExchange.Redis) sparades i konfigurationen med nyckelnamnet MyRedisConStr.

Mer information finns i Azure Cache for Redis.

Se det här GitHub-problemet för en diskussion om alternativa metoder för en lokal Redis-cache.

Distribuerad minnescache

Distributed Memory Cache (AddDistributedMemoryCache) är en ramverksbaserad implementering av IDistributedCache som lagrar objekt i minnet. Den distribuerade minnescachen är inte en faktisk distribuerad cache. Cachelagrade objekt lagras av appinstansen på servern där appen körs.

Den distribuerade minnescachen är en användbar implementering:

  • I utvecklings- och testscenarier.
  • När en enskild server används i produktion och minnesförbrukning är inte ett problem. Implementering av Distributed Memory Cache abstrakterar lagringen av cachad data. Det gör det möjligt att implementera en sann distribuerad cachelagringslösning i framtiden om flera noder eller feltolerans blir nödvändiga.

Exempelappen använder distribuerad minnescache när appen körs i Development miljön i Program.cs:

builder.Services.AddDistributedMemoryCache();

Distribuerad SQL Server Cache

Implementeringen av distribuerad SQL Server Cache (AddDistributedSqlServerCache) gör att den distribuerade cachen kan använda en SQL Server-databas som stödarkiv. Om du vill skapa en SQL Server-cachelagrad objekttabell i en SQL Server-instans kan du använda sql-cache verktyget. Verktyget skapar en tabell med det namn och schema som du anger.

Skapa en tabell i SQL Server genom att sql-cache create köra kommandot . Ange SQL Server-instansen (Data Source), databasen (Initial Catalog), schemat (till exempel dbo) och tabellnamnet (till exempel TestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

Ett meddelande loggas för att indikera att verktyget lyckades:

Table and index were created successfully.

Tabellen som skapades av sql-cache verktyget har följande schema:

SqlServer Cache Table

Note

En app bör ändra cachevärden med hjälp av en instans av IDistributedCache, inte en SqlServerCache.

Exempelappen implementeras SqlServerCache i en icke-Development miljö i Program.cs:

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

A ConnectionString (och valfritt, SchemaName och TableName) lagras vanligtvis utanför källkontrollen (till exempel lagras av Secret Manager eller i appsettings.json/appsettings.{Environment}.json filer). Anslutningssträngen kan innehålla autentiseringsuppgifter som ska hållas borta från källkontrollsystem.

Distribuerad Postgres Cache

Azure Database for PostgreSQL kan användas som ett distribuerat cachelagringslager via IDistributedCache gränssnittet. Azure Database for PostgreSQL är ett fullständigt hanterat, AI-redo DBaaS-erbjudande (Database-as-a-Service) som bygger på PostgreSQL-motorn med öppen källkod, utformad för att stödja verksamhetskritiska arbetsbelastningar med förutsägbar prestanda, robust säkerhet, hög tillgänglighet och sömlös skalbarhet.

När du har installerat NuGet-paketet Microsoft.Extensions.Caching.Postgres konfigurerar du din distribuerade cache enligt följande:

  1. Registrera tjänsten
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
    options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
    options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
    options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
    options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
    options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);

    // Optional: Configure expiration settings

    var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
    if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
        options.ExpiredItemsDeletionInterval = interval;
    }

    var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
    if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
        options.DefaultSlidingExpiration = sliding;
    }
});

var app = builder.Build();
  1. Använda cachen
public class MyService {
    private readonly IDistributedCache _cache; 

    public MyService(IDistributedCache cache) {
        _cache = cache;
    }

    public async Task<string> GetDataAsync(string key) {
        var cachedData = await _cache.GetStringAsync(key);

        if (cachedData == null) {
            // Fetch data from source
            var data = await FetchDataFromSource();

            // Cache the data with options
            var options = new DistributedCacheEntryOptions {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                SlidingExpiration = TimeSpan.FromMinutes(5)
            };

            await _cache.SetStringAsync(key, data, options);
            return data;
        }

        return cachedData;
    }
}

Distribuerad NCache Cache

NCache är en distribuerad cache med öppen källkod i minnet som utvecklats internt i .NET och .NET Core. NCache fungerar både lokalt och konfigurerat som ett distribuerat cachekluster för en ASP.NET Core-app som körs i Azure eller på andra värdplattformar.

Information om hur du installerar och konfigurerar NCache på den lokala datorn finns i Komma igång-guiden för Windows (.NET och .NET Core).

Så här konfigurerar du NCache:

  1. Installera NuGet med öppen källkod i NCache.
  2. Konfigurera cacheklustret i client.ncconf.
  3. Lägg till följande kod i Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Använda den distribuerade cachen

Om du vill använda IDistributedCache gränssnittet begär du en instans av IDistributedCache i appen. Instansen tillhandahålls av beroendeinmatning (DI).

När exempelappen startar, injiceras IDistributedCache i Program.cs. Den aktuella tiden cachelagras med IHostApplicationLifetime (för mer information, se Generic Host: IHostApplicationLifetime):

app.Lifetime.ApplicationStarted.Register(() =>
{
    var currentTimeUTC = DateTime.UtcNow.ToString();
    byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
    var options = new DistributedCacheEntryOptions()
        .SetSlidingExpiration(TimeSpan.FromSeconds(20));
    app.Services.GetService<IDistributedCache>()
                              .Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});

Exempelappen injicerar IDistributedCache i IndexModel för att användas på indexsidan.

Varje gång Index-sidan läses in kontrolleras cacheminnet för den cachade tiden i OnGetAsync. Om den cachelagrade tiden inte har upphört att gälla visas tiden. Om 20 sekunder har förflutit sedan den senaste gången den cachelagrade tiden användes (den senaste gången den här sidan lästes in) visar sidan Cachelagrad tid har upphört att gälla.

Uppdatera omedelbart den cachelagrade tiden till den aktuella tiden genom att välja knappen Återställ cachelagrad tid . Knappen utlöser OnPostResetCachedTime hanteringsmetoden.

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string? CachedTimeUTC { get; set; }
    public string? ASP_Environment { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }

        ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        if (String.IsNullOrEmpty(ASP_Environment))
        {
            ASP_Environment = "Null, so Production";
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Du behöver inte använda en singleton- eller scoped-livslängd för -instanser med de inbyggda implementeringarna.

Du kan också skapa en IDistributedCache instans där du kan behöva en i stället för att använda DI, men att skapa en instans i kod kan göra koden svårare att testa och strider mot principen explicita beroenden.

Recommendations

När du bestämmer vilken implementering av IDistributedCache som är bäst för din app bör du tänka på följande:

  • Befintlig infrastruktur
  • Prestandakrav
  • Cost
  • Teamupplevelse

Cachelagringslösningar förlitar sig vanligtvis på minnesintern lagring för att ge snabb hämtning av cachelagrade data, men minnet är en begränsad resurs och kostsamt att expandera. Lagra endast vanliga data i en cache.

För de flesta appar ger en Redis-cache högre dataflöde och lägre svarstid än en SQL Server-cache. Benchmarking rekommenderas dock för att fastställa prestandaegenskaperna för cachelagringsstrategier.

När SQL Server används som ett distribuerat cachelagringslager kan användningen av samma databas för cachen och appens vanliga datalagring och hämtning påverka bådas prestanda negativt. Vi rekommenderar att du använder en dedikerad SQL Server-instans för det distribuerade cachelagringsarkivet.

Ytterligare resurser

En distribuerad cache är en cache som delas av flera appservrar, som vanligtvis underhålls som en extern tjänst till de appservrar som har åtkomst till den. En distribuerad cache kan förbättra prestanda och skalbarhet för en ASP.NET Core-app, särskilt när appen hanteras av en molntjänst eller en servergrupp.

En distribuerad cache har flera fördelar jämfört med andra cachelagringsscenarier där cachelagrade data lagras på enskilda appservrar.

När cachelagrade data distribueras, data:

  • Är sammanhängande (konsekvent) mellan begäranden till flera servrar.
  • Överlever omstarter av servern och appdistributioner.
  • Använder inte lokalt minne.

Konfiguration av distribuerad cache är implementeringsspecifik. Den här artikeln beskriver hur du konfigurerar distribuerade SQL Server-, Redis- och Postgres-cacheminnen. Implementeringar från tredje part är också tillgängliga, till exempel NCache (NCache på GitHub). Oavsett vilken implementering som väljs interagerar appen med cachen med hjälp av IDistributedCache gränssnittet.

Visa eller ladda ned exempelkod (hur du laddar ned)

Prerequisites

Om du vill använda en distribuerad SQL Server-cache lägger du till en paketreferens till paketet Microsoft.Extensions.Caching.SqlServer .

Om du vill använda en Redis-distribuerad cache lägger du till en paketreferens till paketet Microsoft.Extensions.Caching.StackExchangeRedis .

Om du vill använda en Postgres-distribuerad cache lägger du till en paketreferens till paketet Microsoft.Extensions.Caching.Postgres .

Om du vill använda NCache-distribuerad cache lägger du till en paketreferens till paketet NCache.Microsoft.Extensions.Caching.OpenSource .

IDistributedCache-gränssnitt

Gränssnittet IDistributedCache innehåller följande metoder för att manipulera objekt i implementeringen av distribuerad cache:

  • Get, GetAsync: Accepterar en strängnyckel och hämtar ett cachelagrat objekt som en byte[] matris om det finns i cacheminnet.
  • Set, SetAsync: Lägger till ett objekt (som byte[] matris) i cacheminnet med hjälp av en strängnyckel.
  • Refresh, RefreshAsync: Uppdaterar ett objekt i cacheminnet baserat på dess nyckel och återställer den glidande tidsgränsen för förfallotid (om någon).
  • Remove, RemoveAsync: Tar bort ett cacheobjekt baserat på dess strängnyckel.

Upprätta distribuerade cachelagringstjänster

Registrera en implementering av IDistributedCache i Startup.ConfigureServices. Exempel på ramverksbaserade implementeringar som beskrivs i det här avsnittet är:

Distribuerad minnescache

Distributed Memory Cache (AddDistributedMemoryCache) är en ramverksbaserad implementering av IDistributedCache som lagrar objekt i minnet. Den distribuerade minnescachen är inte en faktisk distribuerad cache. Cachelagrade objekt lagras av appinstansen på servern där appen körs.

Den distribuerade minnescachen är en användbar implementering:

  • I utvecklings- och testscenarier.
  • När en enskild server används i produktion och minnesförbrukning är inte ett problem. Implementering av Distributed Memory Cache abstrakterar lagringen av cachad data. Det gör det möjligt att implementera en sann distribuerad cachelagringslösning i framtiden om flera noder eller feltolerans blir nödvändiga.

Exempelappen använder distribuerad minnescache när appen körs i Development miljön i Startup.ConfigureServices:

services.AddDistributedMemoryCache();

Distribuerad SQL Server Cache

Implementeringen av distribuerad SQL Server Cache (AddDistributedSqlServerCache) gör att den distribuerade cachen kan använda en SQL Server-databas som stödarkiv. Om du vill skapa en SQL Server-cachelagrad objekttabell i en SQL Server-instans kan du använda sql-cache verktyget. Verktyget skapar en tabell med det namn och schema som du anger.

Skapa en tabell i SQL Server genom att sql-cache create köra kommandot . Ange SQL Server-instansen (Data Source), databasen (Initial Catalog), schemat (till exempel dbo) och tabellnamnet (till exempel TestCache):

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

Ett meddelande loggas för att indikera att verktyget lyckades:

Table and index were created successfully.

Tabellen som skapades av sql-cache verktyget har följande schema:

SqlServer Cache Table

Note

En app bör ändra cachevärden med hjälp av en instans av IDistributedCache, inte en SqlServerCache.

Exempelappen implementeras SqlServerCache i en icke-Development miljö i Startup.ConfigureServices:

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = 
        _config["DistCache_ConnectionString"];
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

A ConnectionString (och valfritt, SchemaName och TableName) lagras vanligtvis utanför källkontrollen (till exempel lagras av Secret Manager eller i appsettings.json/appsettings.{Environment}.json filer). Anslutningssträngen kan innehålla autentiseringsuppgifter som ska hållas borta från källkontrollsystem.

Distribuerad Redis Cache

Redis är ett minnesinternt datalager med öppen källkod, som ofta används som en distribuerad cache. Du kan konfigurera en Azure Redis Cache för en Azure-värdbaserad ASP.NET Core-app och använda en Azure Redis Cache för lokal utveckling.

En app konfigurerar cacheimplementeringen med hjälp av en RedisCache instans (AddStackExchangeRedisCache).

  1. Skapa en Azure Cache for Redis.
  2. Kopiera den primära anslutningssträngen (StackExchange.Redis) till Konfiguration.
    • Lokal utveckling: Spara anslutningssträngen med Secret Manager.
    • Azure: Spara anslutningssträngen i ett säkert arkiv, till exempel Azure Key Vault

Följande kod aktiverar Azure Cache for Redis:

public void ConfigureServices(IServiceCollection services)
{
    if (_hostContext.IsDevelopment())
    {
        services.AddDistributedMemoryCache();
    }
    else
    {
        services.AddStackExchangeRedisCache(options =>
        {
            options.Configuration = _config["MyRedisConStr"];
            options.InstanceName = "SampleInstance";
        });
    }

    services.AddRazorPages();
}

Föregående kod förutsätter att den primära anslutningssträngen (StackExchange.Redis) sparades i konfigurationen med nyckelnamnet MyRedisConStr.

Mer information finns i Azure Cache for Redis.

Se det här GitHub-problemet för en diskussion om alternativa metoder för en lokal Redis-cache.

Distribuerad Postgres Cache

Azure Database for PostgreSQL kan användas som ett distribuerat cachelagringslager via IDistributedCache gränssnittet. Azure Database for PostgreSQL är ett fullständigt hanterat, AI-redo DBaaS-erbjudande (Database-as-a-Service) som bygger på PostgreSQL-motorn med öppen källkod, utformad för att stödja verksamhetskritiska arbetsbelastningar med förutsägbar prestanda, robust säkerhet, hög tillgänglighet och sömlös skalbarhet.

När du har installerat NuGet-paketet Microsoft.Extensions.Caching.Postgres konfigurerar du din distribuerade cache enligt följande:

  1. Registrera tjänsten
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
    options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
    options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
    options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
    options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
    options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);

    // Optional: Configure expiration settings

    var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
    if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
        options.ExpiredItemsDeletionInterval = interval;
    }

    var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
    if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
        options.DefaultSlidingExpiration = sliding;
    }
});

var app = builder.Build();
  1. Använda cachen
public class MyService {
    private readonly IDistributedCache _cache; 

    public MyService(IDistributedCache cache) {
        _cache = cache;
    }

    public async Task<string> GetDataAsync(string key) {
        var cachedData = await _cache.GetStringAsync(key);

        if (cachedData == null) {
            // Fetch data from source
            var data = await FetchDataFromSource();

            // Cache the data with options
            var options = new DistributedCacheEntryOptions {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                SlidingExpiration = TimeSpan.FromMinutes(5)
            };

            await _cache.SetStringAsync(key, data, options);
            return data;
        }

        return cachedData;
    }
}

Distribuerad NCache Cache

NCache är en distribuerad cache med öppen källkod i minnet som utvecklats internt i .NET och .NET Core. NCache fungerar både lokalt och konfigurerat som ett distribuerat cachekluster för en ASP.NET Core-app som körs i Azure eller på andra värdplattformar.

Information om hur du installerar och konfigurerar NCache på den lokala datorn finns i Komma igång-guiden för Windows (.NET och .NET Core).

Så här konfigurerar du NCache:

  1. Installera NuGet med öppen källkod i NCache.

  2. Konfigurera cacheklustret i client.ncconf.

  3. Lägg till följande kod i Startup.ConfigureServices:

    services.AddNCacheDistributedCache(configuration =>    
    {        
        configuration.CacheName = "demoClusteredCache";
        configuration.EnableLogs = true;
        configuration.ExceptionsEnabled = true;
    });
    

Använda den distribuerade cachen

Om du vill använda IDistributedCache gränssnittet begär du en instans av IDistributedCache från en konstruktor i appen. Instansen tillhandahålls av beroendeinmatning (DI).

När exempelappen startar, injiceras IDistributedCache i Startup.Configure. Den aktuella tiden cachelagras med IHostApplicationLifetime (för mer information, se Generic Host: IHostApplicationLifetime):

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
    IHostApplicationLifetime lifetime, IDistributedCache cache)
{
    lifetime.ApplicationStarted.Register(() =>
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
    });

Exempelappen injicerar IDistributedCache i IndexModel för att användas på indexsidan.

Varje gång Index-sidan läses in kontrolleras cacheminnet för den cachade tiden i OnGetAsync. Om den cachelagrade tiden inte har upphört att gälla visas tiden. Om 20 sekunder har förflutit sedan den senaste gången den cachelagrade tiden användes (den senaste gången den här sidan lästes in) visar sidan Cachelagrad tid har upphört att gälla.

Uppdatera omedelbart den cachelagrade tiden till den aktuella tiden genom att välja knappen Återställ cachelagrad tid . Knappen utlöser OnPostResetCachedTime hanteringsmetoden.

public class IndexModel : PageModel
{
    private readonly IDistributedCache _cache;

    public IndexModel(IDistributedCache cache)
    {
        _cache = cache;
    }

    public string CachedTimeUTC { get; set; }

    public async Task OnGetAsync()
    {
        CachedTimeUTC = "Cached Time Expired";
        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");

        if (encodedCachedTimeUTC != null)
        {
            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
        }
    }

    public async Task<IActionResult> OnPostResetCachedTime()
    {
        var currentTimeUTC = DateTime.UtcNow.ToString();
        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(20));
        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);

        return RedirectToPage();
    }
}

Note

Det finns inget behov av att använda en Singleton eller Scoped lifetime för IDistributedCache-instanser (åtminstone för de inbyggda implementationerna).

Du kan också skapa en IDistributedCache instans där du kan behöva en i stället för att använda DI, men att skapa en instans i kod kan göra koden svårare att testa och strider mot principen explicita beroenden.

Recommendations

När du bestämmer vilken implementering av IDistributedCache som är bäst för din app bör du tänka på följande:

  • Befintlig infrastruktur
  • Prestandakrav
  • Cost
  • Teamupplevelse

Cachelagringslösningar förlitar sig vanligtvis på minnesintern lagring för att ge snabb hämtning av cachelagrade data, men minnet är en begränsad resurs och kostsamt att expandera. Lagra endast vanliga data i en cache.

I allmänhet ger en Redis-cache högre dataflöde och lägre svarstid än en SQL Server-cache. Benchmarking krävs dock vanligtvis för att fastställa prestandaegenskaperna för cachelagringsstrategier.

När SQL Server används som ett distribuerat cachelagringslager kan användningen av samma databas för cachen och appens vanliga datalagring och hämtning påverka bådas prestanda negativt. Vi rekommenderar att du använder en dedikerad SQL Server-instans för det distribuerade cachelagringsarkivet.

Ytterligare resurser