Dela via


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. För den nuvarande utgåvan, se .NET 9-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. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Important

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

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- eller Postgres-cacheminnen. Implementeringar från tredje part är också tillgängliga, till exempel NCache (NCache på GitHub), Cosmos DB och Postgres. 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)

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:

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 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.

En app konfigurerar cacheimplementeringen med hjälp av en RedisCache instans genom att anropa AddStackExchangeRedisCache. För cachelagring av utdata använder du AddStackExchangeRedisOutputCache.

  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 utvecklingsmiljö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 implementerar SqlServerCache i en annan miljö än utveckling 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 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 för Windows och Linux.

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;
});

Distribuerad Azure Cosmos DB Cache

Azure Cosmos DB kan användas i ASP.NET Core som sessionstillståndsprovider med hjälp IDistributedCache av gränssnittet. 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 NuGet-paketet Microsoft.Extensions.Caching.Cosmos konfigurerar du en distribuerad Azure Cosmos DB-cache enligt följande:

Återanvänd en befintlig klient

Det enklaste sättet att konfigurera 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, 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

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 utvecklingsmiljö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 implementerar SqlServerCache i en annan miljö än utveckling 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 utvecklingsmiljö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 implementerar SqlServerCache i en annan miljö än utveckling 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