Memorizzazione nella cache in ASP.NET Core distribuitaDistributed caching in ASP.NET Core

Dal Luke Latham e Steve SmithBy Luke Latham and Steve Smith

Una cache distribuita è una cache condivisa da più server di app, in genere gestito come un servizio esterno per i server di app che vi accedono.A distributed cache is a cache shared by multiple app servers, typically maintained as an external service to the app servers that access it. Una cache distribuita può migliorare le prestazioni e scalabilità di un'app ASP.NET Core, soprattutto quando l'app è ospitata da un servizio cloud o una server farm.A distributed cache can improve the performance and scalability of an ASP.NET Core app, especially when the app is hosted by a cloud service or a server farm.

Una cache distribuita presenta diversi vantaggi rispetto altri scenari di memorizzazione nella cache in cui sono archiviati dati memorizzati nella cache nei server delle singole app.A distributed cache has several advantages over other caching scenarios where cached data is stored on individual app servers.

Quando i dati memorizzati nella cache sono distribuiti, i dati:When cached data is distributed, the data:

  • Viene coerente (coerente) in tutte le richieste a più server.Is coherent (consistent) across requests to multiple servers.
  • Può essere ripristinato dopo il riavvio del server e le distribuzioni di app.Survives server restarts and app deployments.
  • Non utilizza memoria locale.Doesn't use local memory.

Configurazione di cache distribuita è specifico dell'implementazione.Distributed cache configuration is implementation specific. Questo articolo descrive come configurare SQL Server e le cache distribuite Redis.This article describes how to configure SQL Server and Redis distributed caches. Le implementazioni di terze parti sono anche disponibili, ad esempio NCache (NCache su GitHub).Third party implementations are also available, such as NCache (NCache on GitHub). Indipendentemente dalla scelta dell'implementazione è selezionata, l'app interagisce con la cache usando il IDistributedCache interfaccia.Regardless of which implementation is selected, the app interacts with the cache using the IDistributedCache interface.

Visualizzare o scaricare il codice di esempio (procedura per il download)View or download sample code (how to download)

PrerequisitiPrerequisites

Per usare un Server SQL distribuito cache, riferimento il metapacchetto Microsoft.AspNetCore.App o aggiungere un riferimento al pacchetto le Microsoft.Extensions.Caching.SqlServer pacchetto.To use a SQL Server distributed cache, reference the Microsoft.AspNetCore.App metapackage or add a package reference to the Microsoft.Extensions.Caching.SqlServer package.

Per usare un Redis cache, riferimento distribuita il metapacchetto Microsoft.AspNetCore.App e aggiungere un riferimento al pacchetto le Microsoft.Extensions.Caching.StackExchangeRedis pacchetto.To use a Redis distributed cache, reference the Microsoft.AspNetCore.App metapackage and add a package reference to the Microsoft.Extensions.Caching.StackExchangeRedis package. Il pacchetto di Redis non è incluso nel Microsoft.AspNetCore.App creare un pacchetto, pertanto è necessario fare riferimento a pacchetto Redis separatamente nel file di progetto.The Redis package isn't included in the Microsoft.AspNetCore.App package, so you must reference the Redis package separately in your project file.

Per usare un Server SQL distribuito cache, riferimento il metapacchetto Microsoft.AspNetCore.App o aggiungere un riferimento al pacchetto le Microsoft.Extensions.Caching.SqlServer pacchetto.To use a SQL Server distributed cache, reference the Microsoft.AspNetCore.App metapackage or add a package reference to the Microsoft.Extensions.Caching.SqlServer package.

Per usare un Redis cache, riferimento distribuita il metapacchetto Microsoft.AspNetCore.App e aggiungere un riferimento al pacchetto le Microsoft.Extensions.Caching.Redis pacchetto.To use a Redis distributed cache, reference the Microsoft.AspNetCore.App metapackage and add a package reference to the Microsoft.Extensions.Caching.Redis package. Il pacchetto di Redis non è incluso nel Microsoft.AspNetCore.App creare un pacchetto, pertanto è necessario fare riferimento a pacchetto Redis separatamente nel file di progetto.The Redis package isn't included in the Microsoft.AspNetCore.App package, so you must reference the Redis package separately in your project file.

Interfaccia IDistributedCacheIDistributedCache interface

Il IDistributedCache interfaccia fornisce i metodi seguenti per modificare gli elementi nell'implementazione di cache distribuita:The IDistributedCache interface provides the following methods to manipulate items in the distributed cache implementation:

  • Get, GetAsync – Accetta una chiave di stringa e recupera un elemento memorizzato nella cache come un byte[] matrice se trovato nella cache.Get, GetAsync – Accepts a string key and retrieves a cached item as a byte[] array if found in the cache.
  • Set, SetAsync – Aggiunge un elemento (come byte[] matrice) alla cache usando una chiave di stringa.Set, SetAsync – Adds an item (as byte[] array) to the cache using a string key.
  • Refresh, RefreshAsync – Viene aggiornato un elemento nella cache in base alla chiave, reimpostare il timeout di scadenza scorrevole (se presente).Refresh, RefreshAsync – Refreshes an item in the cache based on its key, resetting its sliding expiration timeout (if any).
  • Remove, RemoveAsync – Rimuove un elemento della cache basato sulla relativa chiave di stringa.Remove, RemoveAsync – Removes a cache item based on its string key.

Stabilire i servizi di memorizzazione nella cache distribuitiEstablish distributed caching services

Registrare un'implementazione di IDistributedCache in Startup.ConfigureServices.Register an implementation of IDistributedCache in Startup.ConfigureServices. Implementazioni forniti dal Framework, descritte in questo argomento includono:Framework-provided implementations described in this topic include:

Cache distribuita in memoriaDistributed Memory Cache

La Cache di memoria distribuita (AddDistributedMemoryCache) è un'implementazione fornita dal framework di IDistributedCache che archivia gli elementi in memoria.The Distributed Memory Cache (AddDistributedMemoryCache) is a framework-provided implementation of IDistributedCache that stores items in memory. La Cache di memoria distribuita non è un'istanza di cache distribuita effettivo.The Distributed Memory Cache isn't an actual distributed cache. Gli elementi memorizzati nella cache vengono archiviati per l'istanza dell'app nel server in cui viene eseguita l'app.Cached items are stored by the app instance on the server where the app is running.

La Cache distribuita di memoria è un'implementazione utile:The Distributed Memory Cache is a useful implementation:

  • Negli scenari di test e sviluppo.In development and testing scenarios.
  • Quando si usa un singolo server in termini di consumo di memoria e di produzione non è un problema.When a single server is used in production and memory consumption isn't an issue. Implementazione della Cache in memoria distribuita riassunti memorizzati nella cache di archiviazione dei dati.Implementing the Distributed Memory Cache abstracts cached data storage. Consente di implementare che un vero e proprio distribuite soluzioni di memorizzazione nella cache nel futuro se più nodi o la tolleranza di errore diventano necessari.It allows for implementing a true distributed caching solution in the future if multiple nodes or fault tolerance become necessary.

L'app di esempio vengono utilizzate le Cache in memoria distribuita quando l'app viene eseguita nell'ambiente di sviluppo in Startup.ConfigureServices:The sample app makes use of the Distributed Memory Cache when the app is run in the Development environment in Startup.ConfigureServices:

services.AddDistributedMemoryCache();

Cache del Server SQL distribuitoDistributed SQL Server Cache

L'implementazione di Cache distribuita di Server SQL (AddDistributedSqlServerCache) consente alla cache distribuita di utilizzare un database di SQL Server come archivio di backup.The Distributed SQL Server Cache implementation (AddDistributedSqlServerCache) allows the distributed cache to use a SQL Server database as its backing store. Per creare una tabella di elemento memorizzato nella cache di SQL Server in un'istanza di SQL Server, è possibile usare il sql-cache dello strumento.To create a SQL Server cached item table in a SQL Server instance, you can use the sql-cache tool. Lo strumento crea una tabella con il nome e allo schema specificato.The tool creates a table with the name and schema that you specify.

Creare una tabella in SQL Server eseguendo il sql-cache create comando.Create a table in SQL Server by running the sql-cache create command. Specificare l'istanza di SQL Server (Data Source), database (Initial Catalog), lo schema (ad esempio, dbo) e il nome di tabella (ad esempio, TestCache):Provide the SQL Server instance (Data Source), database (Initial Catalog), schema (for example, dbo), and table name (for example, TestCache):

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

Un messaggio viene registrato per indicare che lo strumento ha esito negativo:A message is logged to indicate that the tool was successful:

Table and index were created successfully.

La tabella creata dal sql-cache strumento presenta lo schema seguente:The table created by the sql-cache tool has the following schema:

Tabella della Cache di SQL Server

Nota

Un'app deve modificare i valori della cache usando un'istanza di IDistributedCache, non un SqlServerCache.An app should manipulate cache values using an instance of IDistributedCache, not a SqlServerCache.

L'app di esempio implementa SqlServerCache in un ambiente non di sviluppo in Startup.ConfigureServices:The sample app implements SqlServerCache in a non-Development environment in Startup.ConfigureServices:

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

Nota

Oggetto ConnectionString (e, facoltativamente, SchemaName e TableName) vengono in genere archiviate all'esterno di controllo del codice sorgente (ad esempio, archiviati per il Secret Manager o nella appSettings. JSON / appsettings. {ENVIRONMENT}. JSON file).A ConnectionString (and optionally, SchemaName and TableName) are typically stored outside of source control (for example, stored by the Secret Manager or in appsettings.json/appsettings.{ENVIRONMENT}.json files). La stringa di connessione può contenere le credenziali che devono essere mantenute all'esterno di sistemi di controllo di origine.The connection string may contain credentials that should be kept out of source control systems.

Cache distribuite RedisDistributed Redis Cache

Redis è un archivio dati in memoria open source, che viene spesso usato come una cache distribuita.Redis is an open source in-memory data store, which is often used as a distributed cache. È possibile usare Redis in locale, ed è possibile configurare un Cache Redis di Azure per un'app ASP.NET Core ospitate in Azure.You can use Redis locally, and you can configure an Azure Redis Cache for an Azure-hosted ASP.NET Core app.

Consente di configurare un'app per l'implementazione della cache mediante un RedisCache istanza (AddStackExchangeRedisCache) in un ambiente non di sviluppo in Startup.ConfigureServices:An app configures the cache implementation using a RedisCache instance (AddStackExchangeRedisCache) in a non-Development environment in Startup.ConfigureServices:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost";
    options.InstanceName = "SampleInstance";
});

Consente di configurare un'app per l'implementazione della cache mediante un RedisCache istanza (AddDistributedRedisCache):An app configures the cache implementation using a RedisCache instance (AddDistributedRedisCache):

services.AddDistributedRedisCache(options =>
{
    options.Configuration = "localhost";
    options.InstanceName = "SampleInstance";
});

Per installare Redis in locale:To install Redis on your local machine:

Usare la cache distribuitaUse the distributed cache

Usare la IDistributedCache l'interfaccia, richiedere un'istanza di IDistributedCache da qualsiasi altro costruttore nell'app.To use the IDistributedCache interface, request an instance of IDistributedCache from any constructor in the app. L'istanza viene fornita dalla inserimento delle dipendenze (dipendenze).The instance is provided by dependency injection (DI).

All'avvio dell'app, IDistributedCache viene inserito nelle Startup.Configure.When the app starts, IDistributedCache is injected into Startup.Configure. L'ora corrente viene memorizzato nella cache usando IApplicationLifetime (per altre informazioni, vedere Host Web: Interfaccia IApplicationLifetime):The current time is cached using IApplicationLifetime (for more information, see Web Host: IApplicationLifetime interface):

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    IApplicationLifetime 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);
    });

L'app di esempio inserisce IDistributedCache nella IndexModel da utilizzare per la pagina di indice.The sample app injects IDistributedCache into the IndexModel for use by the Index page.

Ogni volta che viene caricata la pagina di indice, la cache è selezionata per la volta memorizzati nella cache in OnGetAsync.Each time the Index page is loaded, the cache is checked for the cached time in OnGetAsync. Se l'ora memorizzati nella cache non è ancora scaduto, viene visualizzata l'ora.If the cached time hasn't expired, the time is displayed. Se sono trascorsi 20 secondi dall'ultima volta l'ora memorizzati nella cache è stato eseguito (l'ultima è stata caricata in questa pagina), la pagina viene visualizzata tempo scaduto memorizzato nella cache.If 20 seconds have elapsed since the last time the cached time was accessed (the last time this page was loaded), the page displays Cached Time Expired.

Aggiornare immediatamente il tempo memorizzato nella cache all'ora corrente selezionando il reimpostare memorizzato nella cache ora pulsante.Immediately update the cached time to the current time by selecting the Reset Cached Time button. Le attivazioni di pulsanti di OnPostResetCachedTime metodo del gestore.The button triggers the OnPostResetCachedTime handler method.

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

Nota

Non è necessario usare una durata Singleton o con ambito per IDistributedCache istanze (almeno per le implementazioni predefinite).There's no need to use a Singleton or Scoped lifetime for IDistributedCache instances (at least for the built-in implementations).

È anche possibile creare un IDistributedCache ogni volta che si potrebbe essere necessario uno invece di usare l'inserimento delle dipendenze, ma la creazione di un'istanza nel codice possono rendere più difficile da testare il codice dell'istanza e viola il principio delle dipendenze esplicite.You can also create an IDistributedCache instance wherever you might need one instead of using DI, but creating an instance in code can make your code harder to test and violates the Explicit Dependencies Principle.

SuggerimentiRecommendations

Quando si decide quale implementazione di IDistributedCache è ideale per l'app, tenere presente quanto segue:When deciding which implementation of IDistributedCache is best for your app, consider the following:

  • Infrastruttura esistenteExisting infrastructure
  • Requisiti relativi alle prestazioniPerformance requirements
  • CostiCost
  • Esperienza del teamTeam experience

Soluzioni di memorizzazione nella cache di solito si basano sull'archiviazione in memoria per fornire il recupero veloce dei dati memorizzati nella cache, ma la memoria è una risorsa limitata e costosi da espandere.Caching solutions usually rely on in-memory storage to provide fast retrieval of cached data, but memory is a limited resource and costly to expand. Unico archivio dati comunemente utilizzati in una cache.Only store commonly used data in a cache.

In generale, una cache Redis offre una maggiore velocità effettiva e latenza più bassa rispetto a una cache di SQL Server.Generally, a Redis cache provides higher throughput and lower latency than a SQL Server cache. Tuttavia, il benchmarking è in genere obbligatorie per determinare le caratteristiche delle prestazioni delle strategie di memorizzazione nella cache.However, benchmarking is usually required to determine the performance characteristics of caching strategies.

Quando SQL Server viene usato come archivio di backup di cache distribuita, utilizzare dello stesso database per la cache e l'archiviazione di dati normale dell'app e il recupero può influire negativamente sulle prestazioni di entrambi.When SQL Server is used as a distributed cache backing store, use of the same database for the cache and the app's ordinary data storage and retrieval can negatively impact the performance of both. È consigliabile usare un'istanza di SQL Server dedicata per la cache distribuita di archivio di backup.We recommend using a dedicated SQL Server instance for the distributed cache backing store.

Risorse aggiuntiveAdditional resources