Delen via


Gedistribueerde caching in ASP.NET Core

Door Mohsin Nasir en smandia

Note

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Warning

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Important

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers, die doorgaans worden onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer de app wordt gehost door een cloudservice of een serverfarm.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- of Postgres-caches configureert. Er zijn ook implementaties van derden beschikbaar, zoals NCache (NCache op GitHub), Cosmos DB en Postgres. Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache via de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Warning

In dit artikel wordt een lokale database gebruikt waarvoor de gebruiker niet hoeft te worden geverifieerd. Productie-apps moeten gebruikmaken van de veiligste verificatiestroom die beschikbaar is. Zie Beveiligde verificatiestromenvoor meer informatie over verificatie voor geïmplementeerde test- en productie-apps.

Prerequisites

Voeg een pakketverwijzing toe voor de gedistribueerde cacheprovider die wordt gebruikt:

IDistributedCache-interface

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in Program.cs. Door framework geleverde implementaties die in dit onderwerp worden beschreven, zijn onder andere:

Gedistribueerde Redis-cache

We raden aan productie-apps de gedistribueerde Redis-cache te gebruiken, omdat deze het meest presterende is. Zie Aanbevelingen voor meer informatie.

Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Cache voor Redis configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Cache voor Redis gebruiken voor lokale ontwikkeling.

Een app configureert de cache-implementatie met behulp van een RedisCache exemplaar door aan te roepen AddStackExchangeRedisCache. Gebruik voor AddStackExchangeRedisOutputCache.

  1. Maak een Azure Cache voor Redis.
  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.
    • Lokale ontwikkeling: Sla de connectiestring op met Secret Manager.
    • Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

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

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) is opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Cache voor Redis voor meer informatie.

Bekijk dit GitHub-probleem voor een discussie over alternatieve benaderingen voor een lokale Redis-cache.

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is geen werkelijke gedistribueerde cache. Items in de cache worden opgeslagen door het app-exemplaar op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie:

  • In ontwikkelings- en testscenario's.
  • Wanneer één server wordt gebruikt in productie en geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de ontwikkelomgeving in Program.cs:

builder.Services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de implementatie van gedistribueerde SQL Server-cache (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

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

Er wordt een bericht geregistreerd om aan te geven dat het hulpprogramma is geslaagd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

SqlServer Cache-tabel

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een SqlServerCache.

De voorbeeld-app implementeert SqlServerCache in een niet-ontwikkelomgeving in Program.cs:

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

Note

A ConnectionString (en optioneel SchemaName en TableName) wordt meestal buiten broncodebeheer opgeslagen (bijvoorbeeld opgeslagen door Secret Manager of in appsettings.json/appsettings.{Environment}.json bestanden). De verbindingsreeks kan referentiegegevens bevatten die buiten bereik moeten blijven van broncodebeheersystemen.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready Database-as-a-Service (DBaaS) die is gebouwd op de opensource PostgreSQL-engine, ontworpen ter ondersteuning van bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. De service registreren
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. De cache gebruiken
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;
    }
}

Gedistribueerde NCache-cache

NCache is een open source in-memory gedistribueerde cache die in .NET native is ontwikkeld. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Als u NCache op uw lokale computer wilt installeren en configureren, raadpleegt u De handleiding Aan de slag voor Windows & Linux.

NCache configureren:

  1. Installeer NCache open source NuGet.
  2. Configureer het cachecluster in client.ncconf.
  3. Voeg de volgende code toe aan Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Gedistribueerde Azure Cosmos DB-cache

Azure Cosmos DB kan worden gebruikt in ASP.NET Core als sessiestatusprovider met behulp van de IDistributedCache interface. Azure Cosmos DB is een volledig beheerde NoSQL- en relationele database voor moderne app-ontwikkeling die hoge beschikbaarheid, schaalbaarheid en toegang met lage latentie tot gegevens biedt voor bedrijfskritieke toepassingen.

Nadat u het Pakket Microsoft.Extensions.Caching.Cosmos NuGet hebt geïnstalleerd, configureert u als volgt een gedistribueerde Azure Cosmos DB-cache:

Een bestaande client opnieuw gebruiken

De eenvoudigste manier om gedistribueerde cache te configureren, is door een bestaande Azure Cosmos DB-client opnieuw te gebruiken. In dit geval wordt de CosmosClient instantie niet verwijderd wanneer de provider wordt verwijderd.

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

Een nieuwe client maken

U kunt ook een nieuwe client instantiëren. In dit geval wordt het CosmosClient exemplaar verwijderd wanneer de provider wordt verwijderd.

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

De gedistribueerde cache gebruiken

Als u de IDistributedCache interface wilt gebruiken, vraagt u in de app een exemplaar van IDistributedCache aan. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt IDistributedCache in Program.cs geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van IHostApplicationLifetime (zie Generic Host: IHostApplicationLifetime) voor meer informatie:

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

De voorbeeld-app injecteert IDistributedCache in de IndexModel voor gebruik door de Index-pagina.

Telkens wanneer de Indexpagina wordt geladen, wordt de cache gecontroleerd op de gecachete tijd in OnGetAsync. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina de verlopen tijd in de cache weergegeven.

Werk de gecachede tijd onmiddellijk bij naar de huidige tijd door de knop Gecachede Tijd Resetten te selecteren. Met de knop wordt de OnPostResetCachedTime handlermethode geactiveerd.

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

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren met de ingebouwde implementaties.

U kunt ook een IDistributedCache exemplaar maken waar u er mogelijk een nodig hebt in plaats van di te gebruiken, maar door een exemplaar in code te maken, kan uw code moeilijker worden getest en in strijd zijn met het principe expliciete afhankelijkheden.

Recommendations

Wanneer u besluit welke implementatie IDistributedCache het beste is voor uw app, moet u rekening houden met het volgende:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Voor de meeste apps biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking wordt echter aanbevolen om de prestatiekenmerken van cachestrategieën te bepalen.

Wanneer SQL Server wordt gebruikt als een gedistribueerde cache-backendopslag, kan het gebruik van dezelfde database voor zowel de cache als de gewone gegevensopslag en -opvraging van de app de prestaties van beide negatief beïnvloeden. U wordt aangeraden een dedicated SQL Server-instance te gebruiken voor de gedistribueerde cache opslag.

Aanvullende bronnen

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers, die doorgaans worden onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer de app wordt gehost door een cloudservice of een serverfarm.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- en Postgres-caches configureert. Implementaties van derden zijn ook beschikbaar, zoals NCache (NCache op GitHub). Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache via de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Prerequisites

Voeg een pakketverwijzing toe voor de gedistribueerde cacheprovider die wordt gebruikt:

IDistributedCache-interface

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in Program.cs. Door framework geleverde implementaties die in dit onderwerp worden beschreven, zijn onder andere:

Gedistribueerde Redis-cache

We raden aan productie-apps de gedistribueerde Redis-cache te gebruiken, omdat deze het meest presterende is. Zie Aanbevelingen voor meer informatie.

Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Redis Cache configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Redis Cache gebruiken voor lokale ontwikkeling.

Een app configureert de cache-implementatie met behulp van een RedisCache exemplaar (AddStackExchangeRedisCache).

  1. Maak een Azure Cache voor Redis.
  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.
    • Lokale ontwikkeling: Sla de connectiestring op met Secret Manager.
    • Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

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

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) is opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Cache voor Redis voor meer informatie.

Bekijk dit GitHub-probleem voor een discussie over alternatieve benaderingen voor een lokale Redis-cache.

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is geen werkelijke gedistribueerde cache. Items in de cache worden opgeslagen door het app-exemplaar op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie:

  • In ontwikkelings- en testscenario's.
  • Wanneer één server wordt gebruikt in productie en geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de ontwikkelomgeving in Program.cs:

builder.Services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de implementatie van gedistribueerde SQL Server-cache (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

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

Er wordt een bericht geregistreerd om aan te geven dat het hulpprogramma is geslaagd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

SqlServer Cache-tabel

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een SqlServerCache.

De voorbeeld-app implementeert SqlServerCache in een niet-ontwikkelomgeving in Program.cs:

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

Note

A ConnectionString (en optioneel SchemaName en TableName) wordt meestal buiten broncodebeheer opgeslagen (bijvoorbeeld opgeslagen door Secret Manager of in appsettings.json/appsettings.{Environment}.json bestanden). De verbindingsreeks kan referentiegegevens bevatten die buiten bereik moeten blijven van broncodebeheersystemen.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready Database-as-a-Service (DBaaS) die is gebouwd op de opensource PostgreSQL-engine, ontworpen ter ondersteuning van bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. De service registreren
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. De cache gebruiken
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;
    }
}

Gedistribueerde NCache-cache

NCache is een open source gedistribueerde cache die systeemeigen is ontwikkeld in .NET en .NET Core. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Zie Introductiehandleiding voor Windows (.NET en .NET Core) als u NCache op uw lokale computer wilt installeren en configureren.

NCache configureren:

  1. Installeer NCache open source NuGet.
  2. Configureer het cachecluster in client.ncconf.
  3. Voeg de volgende code toe aan Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

De gedistribueerde cache gebruiken

Als u de IDistributedCache interface wilt gebruiken, vraagt u in de app een exemplaar van IDistributedCache aan. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt IDistributedCache in Program.cs geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van IHostApplicationLifetime (zie Generic Host: IHostApplicationLifetime) voor meer informatie:

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

De voorbeeld-app injecteert IDistributedCache in de IndexModel voor gebruik door de Index-pagina.

Telkens wanneer de Indexpagina wordt geladen, wordt de cache gecontroleerd op de gecachete tijd in OnGetAsync. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina de verlopen tijd in de cache weergegeven.

Werk de gecachede tijd onmiddellijk bij naar de huidige tijd door de knop Gecachede Tijd Resetten te selecteren. Met de knop wordt de OnPostResetCachedTime handlermethode geactiveerd.

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

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren met de ingebouwde implementaties.

U kunt ook een IDistributedCache exemplaar maken waar u er mogelijk een nodig hebt in plaats van di te gebruiken, maar door een exemplaar in code te maken, kan uw code moeilijker worden getest en in strijd zijn met het principe expliciete afhankelijkheden.

Recommendations

Wanneer u besluit welke implementatie IDistributedCache het beste is voor uw app, moet u rekening houden met het volgende:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Voor de meeste apps biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking wordt echter aanbevolen om de prestatiekenmerken van cachestrategieën te bepalen.

Wanneer SQL Server wordt gebruikt als een gedistribueerde cache-backendopslag, kan het gebruik van dezelfde database voor zowel de cache als de gewone gegevensopslag en -opvraging van de app de prestaties van beide negatief beïnvloeden. U wordt aangeraden een dedicated SQL Server-instance te gebruiken voor de gedistribueerde cache opslag.

Aanvullende bronnen

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers, die doorgaans worden onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer de app wordt gehost door een cloudservice of een serverfarm.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- en Postgres-caches configureert. Implementaties van derden zijn ook beschikbaar, zoals NCache (NCache op GitHub). Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache via de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Prerequisites

Als u een gedistribueerde SQL Server-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.SqlServer .

Als u een gedistribueerde Redis-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.StackExchangeRedis .

Als u een gedistribueerde Postgres-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.Postgres .

Als u NCache gedistribueerde cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket NCache.Microsoft.Extensions.Caching.OpenSource .

IDistributedCache-interface

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in Startup.ConfigureServices. Door framework geleverde implementaties die in dit onderwerp worden beschreven, zijn onder andere:

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is geen werkelijke gedistribueerde cache. Items in de cache worden opgeslagen door het app-exemplaar op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie:

  • In ontwikkelings- en testscenario's.
  • Wanneer één server wordt gebruikt in productie en geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de ontwikkelomgeving in Startup.ConfigureServices:

services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de implementatie van gedistribueerde SQL Server-cache (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

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

Er wordt een bericht geregistreerd om aan te geven dat het hulpprogramma is geslaagd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

SqlServer Cache-tabel

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een SqlServerCache.

De voorbeeld-app implementeert SqlServerCache in een niet-ontwikkelomgeving in Startup.ConfigureServices:

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

Note

A ConnectionString (en optioneel SchemaName en TableName) wordt meestal buiten broncodebeheer opgeslagen (bijvoorbeeld opgeslagen door Secret Manager of in appsettings.json/appsettings.{Environment}.json bestanden). De verbindingsreeks kan referentiegegevens bevatten die buiten bereik moeten blijven van broncodebeheersystemen.

Gedistribueerde Redis-cache

Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Redis Cache configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Redis Cache gebruiken voor lokale ontwikkeling.

Een app configureert de cache-implementatie met behulp van een RedisCache exemplaar (AddStackExchangeRedisCache).

  1. Maak een Azure Cache voor Redis.
  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.
    • Lokale ontwikkeling: Sla de connectiestring op met Secret Manager.
    • Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

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

    services.AddRazorPages();
}

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) is opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Cache voor Redis voor meer informatie.

Bekijk dit GitHub-probleem voor een discussie over alternatieve benaderingen voor een lokale Redis-cache.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready Database-as-a-Service (DBaaS) die is gebouwd op de opensource PostgreSQL-engine, ontworpen ter ondersteuning van bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. De service registreren
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. De cache gebruiken
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;
    }
}

Gedistribueerde NCache-cache

NCache is een open source gedistribueerde cache die systeemeigen is ontwikkeld in .NET en .NET Core. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Zie Introductiehandleiding voor Windows (.NET en .NET Core) als u NCache op uw lokale computer wilt installeren en configureren.

NCache configureren:

  1. Installeer NCache open source NuGet.

  2. Configureer het cachecluster in client.ncconf.

  3. Voeg de volgende code toe aan Startup.ConfigureServices:

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

De gedistribueerde cache gebruiken

Als u de IDistributedCache-interface wilt gebruiken, vraagt u een exemplaar van IDistributedCache aan vanuit elke constructor in de app. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt IDistributedCache in Startup.Configure geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van IHostApplicationLifetime (zie Generic Host: IHostApplicationLifetime) voor meer informatie:

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

De voorbeeld-app injecteert IDistributedCache in de IndexModel voor gebruik door de Index-pagina.

Telkens wanneer de Indexpagina wordt geladen, wordt de cache gecontroleerd op de gecachete tijd in OnGetAsync. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina de verlopen tijd in de cache weergegeven.

Werk de gecachede tijd onmiddellijk bij naar de huidige tijd door de knop Gecachede Tijd Resetten te selecteren. Met de knop wordt de OnPostResetCachedTime handlermethode geactiveerd.

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

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren (ten minste voor de ingebouwde implementaties).

U kunt ook een IDistributedCache exemplaar maken waar u er mogelijk een nodig hebt in plaats van di te gebruiken, maar door een exemplaar in code te maken, kan uw code moeilijker worden getest en in strijd zijn met het principe expliciete afhankelijkheden.

Recommendations

Wanneer u besluit welke implementatie IDistributedCache het beste is voor uw app, moet u rekening houden met het volgende:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Over het algemeen biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking is echter meestal vereist om de prestatiekenmerken van cachestrategieën te bepalen.

Wanneer SQL Server wordt gebruikt als een gedistribueerde cache-backendopslag, kan het gebruik van dezelfde database voor zowel de cache als de gewone gegevensopslag en -opvraging van de app de prestaties van beide negatief beïnvloeden. U wordt aangeraden een dedicated SQL Server-instance te gebruiken voor de gedistribueerde cache opslag.

Aanvullende bronnen