Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Por Mohsin Nasir y smandia
Note
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 10 de este artículo.
Warning
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 10 de este artículo.
Una caché distribuida es una caché compartida por varios servidores de aplicaciones. Normalmente, la memoria caché se mantiene como un servicio externo para los servidores de aplicaciones que acceden a ella. Una caché distribuida puede mejorar el rendimiento y la escalabilidad de una aplicación de ASP.NET Core, especialmente cuando un servicio en la nube o una granja de servidores hospeda la aplicación.
Una caché distribuida tiene varias ventajas sobre otros escenarios de almacenamiento en caché en los que los datos almacenados en caché se almacenan en servidores de aplicaciones individuales.
Cuando se distribuyen los datos almacenados en caché, los datos:
- Son coherentes (consistentes) entre solicitudes a varios servidores.
- Sobreviven a los reinicios del servidor y a las implementaciones de aplicaciones.
- No usan memoria local.
La configuración de caché distribuida es específica de la implementación. En este artículo se describe cómo configurar cachés distribuidas de SQL Server, Redis o Postgres. Las implementaciones no Microsoft también están disponibles, como NCache (NCache en GitHub), Azure Cosmos DB y Postgres. Independientemente de la implementación seleccionada, la aplicación interactúa con la memoria caché mediante la IDistributedCache interfaz .
Vea o descargue el código de ejemplo (cómo descargarlo)
Warning
En este artículo se usa una base de datos local que no requiere que el usuario se autentique. Las aplicaciones de producción deben usar el flujo de autenticación más seguro disponible. Para obtener más información sobre la autenticación para aplicaciones de prueba y producción implementadas, consulta Flujos de autenticación seguros.
Prerequisites
Agregue una referencia de paquete para el proveedor de caché distribuida que se usa:
- Para una caché distribuida de Redis, Microsoft.Extensions.Caching.StackExchangeRedis.
- Para SQL Server, Microsoft.Extensions.Caching.SqlServer.
- Para Postgres, Microsoft.Extensions.Caching.Postgres.
- Para Azure Cosmos DB, Microsoft. Extensions.Caching.Cosmos.
- Para la caché distribuida de NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
Usar la interfaz IDistributedCache
La interfaz IDistributedCache proporciona los métodos siguientes para manipular elementos en la implementación de caché distribuida:
-
Get, GetAsync: acepta una clave de cadena y recupera un elemento almacenado en caché como una matriz de
byte[]si se encuentra en la memoria caché. -
Set, SetAsync: agrega un elemento (como
byte[]matriz) a la memoria caché mediante una clave de cadena. - Refresh, RefreshAsync: actualiza un elemento de la caché en función de su clave, restableciendo su tiempo de expiración deslizante (si lo hubiera).
- Remove, RemoveAsync: quita un elemento de caché basado en su clave de cadena.
Establecimiento de servicios de almacenamiento en caché distribuidos
Registre una implementación de IDistributedCache en el archivo Program.cs . En este artículo se describen las siguientes implementaciones proporcionadas por el marco:
- Caché distribuida de Redis
- Caché de memoria distribuida
- Caché de SQL Server distribuida
- Caché de Postgres distribuida
- Caché de NCache distribuida
- Caché distribuida de Azure Cosmos DB
Caché distribuida de Redis
La caché distribuida de Redis ofrece el mejor rendimiento y se recomienda para las aplicaciones de producción. Redis es un almacén de datos en memoria de origen abierto, que suele usarse como caché distribuida. Puede configurar una instancia de Azure Cache for Redis para una aplicación de ASP.NET Core hospedada en Azure y usar una instancia de Azure Cache for Redis para el desarrollo local. Para obtener más información, consulte Revisión de las recomendaciones de caché.
Una aplicación configura la implementación de caché con una RedisCache instancia llamando al AddStackExchangeRedisCache método . Para caching de salida, use el método AddStackExchangeRedisOutputCache.
Cree una instancia de Azure Cache for Redis.
Copie la cadena de conexión principal (StackExchange.Redis) en el Configuration.
Para el desarrollo local: guarde la cadena de conexión con Secret Manager.
For Azure: guarde el cadena de conexión en un almacén seguro, como Azure Key Vault.
El código siguiente habilita Azure Cache for Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
En el código anterior se supone que la cadena de conexión principal (StackExchange.Redis) se guarda en la configuración con el nombre de la clave MyRedisConStr.
Para obtener más información, consulte Azure Managed Redis.
Para obtener una explicación sobre los enfoques alternativos de una caché local de Redis, consulte GitHub problema /dotnet/aspnetcore #19542.
Caché de memoria distribuida
La caché de memoria distribuida (AddDistributedMemoryCache) es una implementación proporcionada por el marco de IDistributedCache que almacena elementos en memoria. Sin embargo, la caché de memoria distribuida no es una caché distribuida real. La instancia de la aplicación almacena los elementos almacenados en caché en el servidor donde se ejecuta la aplicación.
La caché de memoria distribuida es una implementación útil para escenarios de desarrollo y pruebas. También es útil para un solo servidor en un escenario de producción en el que el consumo de memoria no es un problema. La implementación de la caché de memoria distribuida abstrae el almacenamiento de datos almacenados en caché. Permite implementar una solución de almacenamiento en caché distribuida verdadera en el futuro si se necesitan varios nodos o tolerancia a errores.
La aplicación de ejemplo usa la caché de memoria distribuida cuando la aplicación se ejecuta en el Development entorno en el archivo Program.cs .
builder.Services.AddDistributedMemoryCache();
Caché de SQL Server distribuida
La implementación de caché de SQL Server distribuida (AddDistributedSqlServerCache) permite que la caché distribuida use una base de datos de SQL Server como almacén de respaldo. Para crear una tabla de elementos en caché de SQL Server en una instancia de SQL Server, puede usar la herramienta sql-cache. La herramienta crea una tabla con el nombre y el esquema que especifique.
Cree una tabla en SQL Server ejecutando el comando sql-cache create. Proporcione la instancia de SQL Server (Data Source), la base de datos (Initial Catalog), el esquema (por ejemplo, dbo) y el nombre de tabla (por ejemplo, TestCache):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Cuando la herramienta tiene éxito, se registra un mensaje:
Table and index were created successfully.
La tabla creada por la herramienta sql-cache tiene el esquema siguiente:
Note
Una aplicación debe manipular los valores de caché mediante una instancia de IDistributedCache, no una instancia de SqlServerCache.
La aplicación de ejemplo implementa la SqlServerCache clase en un entorno de no desarrollo (Development) en el archivo Program.cs :
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
Las propiedades como ConnectionString (y, opcionalmente, SchemaName y TableName) se almacenan normalmente fuera del control de código fuente. Por ejemplo, el Administrador de secretos o el appsettings.json o appsettings.{ Environment}.json archivo puede almacenar las propiedades. El cadena de conexión puede contener credenciales que deben mantenerse fuera de los sistemas de control de código fuente.
Para obtener más información, consulte SQL Database on Azure.
Caché de Postgres distribuida
Azure Database for PostgreSQL se puede usar como un almacén de respaldo de caché distribuida a través de la IDistributedCache interfaz . Azure Database for PostgreSQL es una oferta de base de datos como servicio (DBaaS) totalmente administrada y lista para ia basada en el motor postgreSQL de código abierto. El diseño admite cargas de trabajo críticas con rendimiento predecible, seguridad sólida, alta disponibilidad y escalabilidad sin problemas.
Después de instalar el paquete NuGet Microsoft.Extensions.Caching.Postgres , configure la caché distribuida de la siguiente manera:
Registre el servicio.
using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Register the Postgres distributed cache. builder.Services.AddDistributedPostgresCache(options => { options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache"); options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public"); options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache"); options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true); options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false); // Optional: Configure expiration settings. var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval"); if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) { options.ExpiredItemsDeletionInterval = interval; } var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration"); if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) { options.DefaultSlidingExpiration = sliding; } }); var app = builder.Build();Usa la memoria cache.
public class MyService { private readonly IDistributedCache _cache; public MyService(IDistributedCache cache) { _cache = cache; } public async Task<string> GetDataAsync(string key) { var cachedData = await _cache.GetStringAsync(key); if (cachedData == null) { // Fetch the data from source. var data = await FetchDataFromSource(); // Cache the data with options. var options = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30), SlidingExpiration = TimeSpan.FromMinutes(5) }; await _cache.SetStringAsync(key, data, options); return data; } return cachedData; } }
Caché distribuida de NCache
NCache es una caché distribuida en memoria de código abierto desarrollada de forma nativa en .NET. NCache funciona localmente y configurada como un clúster de caché distribuida para una aplicación de ASP.NET Core que se ejecuta en Azure o en otras plataformas de hospedaje.
Para instalar y configurar NCache en el equipo local, consulte la Guía de introducción.
Para configurar NCache:
Instale el paquete NuGet del SDK de NCache, que admite NCache Opensource para .NET Framework y aplicaciones .NET Core.
Configure el clúster de caché en la configuración del cliente (el archivo client.ncconf ).
Agregue el código siguiente al archivo Program.cs :
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
Cache distribuida de Azure Cosmos DB
Azure Cosmos DB se puede configurar en ASP.NET Core como proveedor de estado de sesión mediante la interfaz IDistributedCache. Azure Cosmos DB es una base de datos relacional y NoSQL totalmente administrada para el desarrollo de aplicaciones modernas que ofrece alta disponibilidad, escalabilidad y acceso de baja latencia a los datos para aplicaciones críticas.
Después de instalar el Microsoft. Extensions.Caching.Cosmos paquete NuGet, configure una caché distribuida Azure Cosmos DB. Puede usar un cliente de Azure Cosmos DB existente o crear uno nuevo, como se describe en las secciones siguientes.
Para obtener más información, consulte la Extensión de almacenamiento en caché de Microsoft mediante Azure Cosmos DB, el archivo LÉAME del repositorio de GitHub para el paquete NuGet.
Reutilización de un cliente existente
La manera más fácil de configurar una caché distribuida es reutilizar un cliente de Azure Cosmos DB existente. En este caso, la CosmosClient instancia no se elimina cuando se elimina el proveedor.
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.CosmosClient = existingCosmosClient;
cacheOptions.CreateIfNotExists = true;
});
Creación de un nuevo cliente
Como alternativa, instancie un nuevo cliente. En este caso, la CosmosClient instancia se elimina cuando se elimina el proveedor.
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
cacheOptions.CreateIfNotExists = true;
});
Uso de la caché distribuida
Para usar la interfaz de IDistributedCache, solicite una instancia de IDistributedCache en la aplicación. La instancia se proporciona mediante inyección de dependencias (DI).
Cuando se inicia la aplicación de ejemplo, la IDistributedCache instancia se inserta en el archivo Program.cs . La hora actual se almacena en caché mediante la IHostApplicationLifetime interfaz . (Para obtener más información, vea .NET Host genérico: 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);
});
La aplicación de ejemplo inserta la IDistributedCache instancia en el IndexModel objeto para su uso por parte de la página Índice.
Cada vez que se carga la página Índice, se comprueba la memoria caché para verificar el tiempo en caché mediante el método OnGetAsync. Si el tiempo almacenado en caché no ha expirado, se muestra la hora. Si transcurridos 20 segundos desde la última vez que se accedió a la hora almacenada en caché (la última vez que se cargó esta página), la página muestra el mensaje Tiempo almacenado en caché expirado.
Actualice inmediatamente el tiempo almacenado en caché a la hora actual seleccionando la opción Restablecer hora almacenada en caché . Esta acción desencadena el OnPostResetCachedTime método de controlador.
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string? CachedTimeUTC { get; set; }
public string? ASP_Environment { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (String.IsNullOrEmpty(ASP_Environment))
{
ASP_Environment = "Null, so Production";
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
Note
No es necesario utilizar un ciclo de vida único o por solicitud para instancias de IDistributedCache con una implementación integrada.
También puede crear una instancia de IDistributedCache donde necesite una en lugar de usar la inyección de dependencias. Sin embargo, la creación de una instancia en el código puede hacer que el código sea más difícil de probar y infringir el principio de dependencias explícitas.
Revisión de las recomendaciones de caché
Al decidir qué implementación de la interfaz es la mejor para la IDistributedCache aplicación, tenga en cuenta los siguientes puntos:
- Infraestructura existente
- Requisitos de rendimiento
- Cost
- Experiencia del equipo
Las soluciones de almacenamiento en caché suelen depender del almacenamiento en memoria para proporcionar una recuperación rápida de los datos almacenados en caché, pero la memoria es un recurso limitado y costoso de expandir. Almacene solo los datos usados habitualmente en una memoria caché.
En la mayoría de las aplicaciones, una caché de Redis proporciona un mayor rendimiento y una latencia menor que una caché de SQL Server. Sin embargo, se recomienda realizar pruebas comparativas para determinar las características de rendimiento de las estrategias de almacenamiento en caché.
Si SQL Server es el almacén de respaldo de caché distribuida y la memoria caché y el almacenamiento de datos de la aplicación o la recuperación usan la misma base de datos, se puede reducir el rendimiento. El enfoque recomendado es usar una instancia de SQL Server dedicada para el almacén de respaldo de caché distribuida.
Contenido relacionado
- Redis Cache en Azure
- SQL Database en Azure
- Base de datos de Azure para PostgreSQL
- Proveedor de IDistributedCache de ASP.NET Core para NCache en granjas web (NCache en GitHub)
- Archivo README del repositorio para Microsoft.Extensions.Caching.Cosmos
- Detección de cambios con tokens de cambio en ASP.NET Core
- Asistente de etiquetas de caché en ASP.NET Core MVC
- Asistente de etiquetas de caché distribuida en ASP.NET Core
- Hospedaje de ASP.NET Core en una granja de servidores web
Una caché distribuida es una caché compartida por varios servidores de aplicaciones, que normalmente se mantiene como un servicio externo a los servidores de aplicaciones que acceden a ella. Una caché distribuida puede mejorar el rendimiento y la escalabilidad de una aplicación de ASP.NET Core, especialmente cuando la aplicación está hospedada por un servicio en la nube o una granja de servidores.
Una caché distribuida tiene varias ventajas sobre otros escenarios de almacenamiento en caché en los que los datos almacenados en caché se almacenan en servidores de aplicaciones individuales.
Cuando se distribuyen los datos almacenados en caché, los datos:
- Son coherentes (consistentes) entre solicitudes a varios servidores.
- Sobreviven a los reinicios del servidor y a las implementaciones de aplicaciones.
- No usan memoria local.
La configuración de caché distribuida es específica de la implementación. En este artículo se describe cómo configurar cachés distribuidas de SQL Server, Redis y Postgres. También hay implementaciones de terceros disponibles, como NCache (NCache en GitHub). Independientemente de la implementación seleccionada, la aplicación interactúa con la memoria caché mediante la interfaz de IDistributedCache.
Vea o descargue el código de ejemplo (cómo descargarlo)
Prerequisites
Agregue una referencia de paquete para el proveedor de caché distribuida que se usa:
Para una caché distribuida de Redis, Microsoft.Extensions.Caching.StackExchangeRedis.
Para SQL Server, Microsoft.Extensions.Caching.SqlServer.
Para Postgres, Microsoft.Extensions.Caching.Postgres.
Para la caché distribuida de NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
-
Warning
En este artículo se usa una base de datos local que no requiere que el usuario se autentique. Las aplicaciones de producción deben usar el flujo de autenticación más seguro disponible. Para obtener más información sobre la autenticación para aplicaciones de prueba y producción implementadas, consulta Flujos de autenticación seguros.
Interfaz IDistributedCache
La interfaz IDistributedCache proporciona los métodos siguientes para manipular elementos en la implementación de caché distribuida:
-
Get, GetAsync: acepta una clave de cadena y recupera un elemento almacenado en caché como una matriz de
byte[]si se encuentra en la memoria caché. -
Set, SetAsync: agrega un elemento (como matriz de
byte[]) a la memoria caché mediante una clave de cadena. - Refresh, RefreshAsync: actualiza un elemento de la caché en función de su clave, restableciendo su tiempo de expiración deslizante (si lo hubiera).
- Remove, RemoveAsync: quita un elemento de caché basado en su clave de cadena.
Establecimiento de servicios de almacenamiento en caché distribuidos
Registro de una implementación de IDistributedCache en Program.cs. Entre las implementaciones proporcionadas por el marco que se describen en este tema se incluyen:
- Caché distribuida de Redis
- Caché de memoria distribuida
- Caché de SQL Server distribuida
- Caché de Postgres distribuida
- Caché de NCache distribuida
Caché distribuida de Redis
Se recomienda que las aplicaciones de producción usen Caché distribuida de Redis porque es la más eficaz. Para más información, vea Recomendaciones.
Redis es un almacén de datos en memoria de origen abierto, que suele usarse como caché distribuida. Puede configurar una instancia de Azure Redis Cache para una aplicación de ASP.NET Core hospedada en Azure y usar una instancia de Azure Redis Cache para el desarrollo local.
Una aplicación configura la implementación de la caché usando una instancia de RedisCache (AddStackExchangeRedisCache).
- Cree una instancia de Azure Cache for Redis.
- Copie la cadena de conexión principal (StackExchange.Redis) en Configuración.
- Desarrollo local: guarde la cadena de conexión con Secret Manager.
- Azure: guarda la cadena de conexión en un almacén seguro, como Azure Key Vault
El código siguiente habilita Azure Cache for Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
En el código anterior se supone que la cadena de conexión principal (StackExchange.Redis) se guardó en la configuración con el nombre de clave MyRedisConStr.
Para más información, consulte Azure Cache for Redis.
Consulte este problema de GitHub para obtener una explicación sobre los enfoques alternativos de una caché local de Redis.
Caché de memoria distribuida
La caché de memoria distribuida (AddDistributedMemoryCache) es una implementación proporcionada por el marco de IDistributedCache que almacena los elementos en memoria. La caché de memoria distribuida no es una caché distribuida real. La instancia de la aplicación almacena los elementos almacenados en caché en el servidor donde se ejecuta la aplicación.
La caché de memoria distribuida es una implementación útil:
- En escenarios de desarrollo y pruebas.
- Cuando se usa un único servidor en producción y el consumo de memoria no es un problema. La implementación de la caché de memoria distribuida abstrae el almacenamiento de datos almacenados en caché. Permite implementar una solución de almacenamiento en caché distribuida verdadera en el futuro si se necesitan varios nodos o tolerancia a errores.
La aplicación de ejemplo usa la caché de memoria distribuida cuando la aplicación se ejecuta en el Development entorno en Program.cs:
builder.Services.AddDistributedMemoryCache();
Caché de SQL Server distribuida
La implementación de caché de SQL Server distribuida (AddDistributedSqlServerCache) permite que la caché distribuida use una base de datos de SQL Server como almacén de respaldo. Para crear una tabla de elementos en caché de SQL Server en una instancia de SQL Server, puede usar la herramienta sql-cache. La herramienta crea una tabla con el nombre y el esquema que especifique.
Cree una tabla en SQL Server ejecutando el comando sql-cache create. Proporcione la instancia de SQL Server (Data Source), la base de datos (Initial Catalog), el esquema (por ejemplo, dbo) y el nombre de tabla (por ejemplo, TestCache):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Se registra un mensaje para indicar que la herramienta tuvo éxito:
Table and index were created successfully.
La tabla creada por la herramienta sql-cache tiene el esquema siguiente:
Note
Una aplicación debe manipular los valores de caché mediante una instancia de IDistributedCache, no un SqlServerCache.
La aplicación de ejemplo implementa SqlServerCache en un entorno que no es de Development en Program.cs:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
Un ConnectionString (y opcionalmente, SchemaName y TableName) suelen almacenarse fuera del control de origen (por ejemplo, almacenados por el Administrador de secretos o en archivos appsettings.json/appsettings.{Environment}.json). La cadena de conexión puede contener credenciales que se deben mantener fuera de los sistemas de control de origen.
Caché de Postgres distribuida
Azure Database for PostgreSQL se puede usar como un almacén de respaldo de caché distribuida a través de la IDistributedCache interfaz . Azure Database for PostgreSQL es una oferta de base de datos como servicio (DBaaS) totalmente administrada y lista para inteligencia artificial basada en el motor postgreSQL de código abierto, diseñada para admitir cargas de trabajo críticas con un rendimiento predecible, una seguridad sólida, alta disponibilidad y escalabilidad sin problemas.
Después de instalar el paquete NuGet Microsoft.Extensions.Caching.Postgres , configure la caché distribuida de la siguiente manera:
- Registro del servicio
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();
- Uso de la memoria caché
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;
}
}
Cache distribuido de NCache
NCache es una caché distribuida en memoria código abierto desarrollada de forma nativa en .NET y .NET Core. NCache funciona localmente y configurada como un clúster de caché distribuida para una aplicación de ASP.NET Core que se ejecuta en Azure o en otras plataformas de hospedaje.
Para instalar y configurar NCache en el equipo local, consulte Guía de introducción para Windows (.NET y .NET Core).
Para configurar NCache:
- Instale NuGet de código abierto de NCache.
- Configure el clúster de caché en client.ncconf.
- Agrega el código siguiente a
Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
Uso de la caché distribuida
Para usar la interfaz de IDistributedCache, solicite una instancia de IDistributedCache en la aplicación. La instancia se proporciona mediante inyección de dependencias (DI).
Cuando se inicia la aplicación de ejemplo, IDistributedCache se inserta en Program.cs. La hora actual se almacena en caché mediante IHostApplicationLifetime (para más información, vea Host genérico: 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);
});
La aplicación de ejemplo inserta IDistributedCache en IndexModel para usarla en la página Índice.
Cada vez que se carga la página Índice, la memoria caché se comprueba durante el tiempo almacenado en caché en OnGetAsync. Si el tiempo almacenado en caché no ha expirado, se muestra la hora. Si han transcurrido 20 segundos desde la última vez que se accedió a la hora almacenada en caché (la última vez que se cargó esta página), la página muestra Tiempo almacenado en caché expirado.
Actualice inmediatamente la hora almacenada en caché a la hora actual seleccionando el botón Restablecer tiempo almacenado en caché . El botón desencadena el método manejador OnPostResetCachedTime.
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();
}
}
No es necesario usar una duración singleton o con ámbito para instancias de IDistributedCache con las implementaciones integradas.
También puede crear una instancia de IDistributedCache donde quiera que necesite una en lugar de usar la inserción de dependencias, pero crear una instancia en el código puede hacer que el código sea más difícil de probar e infringir el principio de dependencias explícitas.
Recommendations
Al decidir qué implementación de IDistributedCache es la mejor para la aplicación, tenga en cuenta lo siguiente:
- Infraestructura existente
- Requisitos de rendimiento
- Cost
- Experiencia del equipo
Las soluciones de almacenamiento en caché suelen depender del almacenamiento en memoria para proporcionar una recuperación rápida de los datos almacenados en caché, pero la memoria es un recurso limitado y costoso de expandir. Almacene solo los datos usados habitualmente en una memoria caché.
En la mayoría de las aplicaciones, una caché de Redis proporciona un mayor rendimiento y una latencia menor que una caché de SQL Server. Sin embargo, se recomienda realizar pruebas comparativas para determinar las características de rendimiento de las estrategias de almacenamiento en caché.
Cuando se usa SQL Server como almacén de respaldo de caché distribuida, el uso de la misma base de datos para la memoria caché y el almacenamiento de datos normal de la aplicación y la recuperación pueden afectar negativamente al rendimiento de ambos. Se recomienda usar una instancia de SQL Server dedicada para el almacén de respaldo de caché distribuida.
Recursos adicionales
- Redis Cache en Azure
- SQL Database en Azure
- Base de datos de Azure para PostgreSQL
- Proveedor de IDistributedCache de ASP.NET Core para NCache en granjas web (NCache en GitHub)
- Cache en memoria en ASP.NET Core
- Detección de cambios con tokens de cambio en ASP.NET Core
- Almacenamiento en caché de respuestas de ASP.NET Core
- Middleware de caché de respuestas en ASP.NET Core
- Asistente de etiquetas de caché en ASP.NET Core MVC
- Asistente de etiquetas de caché distribuida en ASP.NET Core
- Hospedaje de ASP.NET Core en una granja de servidores web
Una caché distribuida es una caché compartida por varios servidores de aplicaciones, que normalmente se mantiene como un servicio externo a los servidores de aplicaciones que acceden a ella. Una caché distribuida puede mejorar el rendimiento y la escalabilidad de una aplicación de ASP.NET Core, especialmente cuando la aplicación está hospedada por un servicio en la nube o una granja de servidores.
Una caché distribuida tiene varias ventajas sobre otros escenarios de almacenamiento en caché en los que los datos almacenados en caché se almacenan en servidores de aplicaciones individuales.
Cuando se distribuyen los datos almacenados en caché, los datos:
- Son coherentes (consistentes) entre solicitudes a varios servidores.
- Sobreviven a los reinicios del servidor y a las implementaciones de aplicaciones.
- No usan memoria local.
La configuración de caché distribuida es específica de la implementación. En este artículo se describe cómo configurar cachés distribuidas de SQL Server, Redis y Postgres. También hay implementaciones de terceros disponibles, como NCache (NCache en GitHub). Independientemente de la implementación seleccionada, la aplicación interactúa con la memoria caché mediante la interfaz de IDistributedCache.
Vea o descargue el código de ejemplo (cómo descargarlo)
Prerequisites
Para usar una caché distribuida de SQL Server, agregue una referencia al paquete Microsoft.Extensions.Caching.SqlServer.
Para usar una caché distribuida de Redis, agregue una referencia al paquete Microsoft.Extensions.Caching.StackExchangeRedis.
Para usar una caché distribuida de Postgres, agregue una referencia de paquete al paquete Microsoft.Extensions.Caching.Postgres .
Para usar una caché distribuida de NCache, agregue una referencia al paquete NCache.Microsoft.Extensions.Caching.OpenSource.
Interfaz IDistributedCache
La interfaz IDistributedCache proporciona los métodos siguientes para manipular elementos en la implementación de caché distribuida:
-
Get, GetAsync: acepta una clave de cadena y recupera un elemento almacenado en caché como una matriz de
byte[]si se encuentra en la memoria caché. -
Set, SetAsync: agrega un elemento (como matriz de
byte[]) a la memoria caché mediante una clave de cadena. - Refresh, RefreshAsync: actualiza un elemento de la caché en función de su clave, restableciendo su tiempo de expiración deslizante (si lo hubiera).
- Remove, RemoveAsync: quita un elemento de caché basado en su clave de cadena.
Establecimiento de servicios de almacenamiento en caché distribuidos
Registro de una implementación de IDistributedCache en Startup.ConfigureServices. Entre las implementaciones proporcionadas por el marco que se describen en este tema se incluyen:
- Caché de memoria distribuida
- Caché de SQL Server distribuida
- Caché distribuida de Redis
- Caché de Postgres distribuida
- Caché de NCache distribuida
Caché de memoria distribuida
La caché de memoria distribuida (AddDistributedMemoryCache) es una implementación proporcionada por el marco de IDistributedCache que almacena los elementos en memoria. La caché de memoria distribuida no es una caché distribuida real. La instancia de la aplicación almacena los elementos almacenados en caché en el servidor donde se ejecuta la aplicación.
La caché de memoria distribuida es una implementación útil:
- En escenarios de desarrollo y pruebas.
- Cuando se usa un único servidor en producción y el consumo de memoria no es un problema. La implementación de la caché de memoria distribuida abstrae el almacenamiento de datos almacenados en caché. Permite implementar una solución de almacenamiento en caché distribuida verdadera en el futuro si se necesitan varios nodos o tolerancia a errores.
La aplicación de ejemplo usa la caché de memoria distribuida cuando la aplicación se ejecuta en el Development entorno en Startup.ConfigureServices:
services.AddDistributedMemoryCache();
Caché de SQL Server distribuida
La implementación de caché de SQL Server distribuida (AddDistributedSqlServerCache) permite que la caché distribuida use una base de datos de SQL Server como almacén de respaldo. Para crear una tabla de elementos en caché de SQL Server en una instancia de SQL Server, puede usar la herramienta sql-cache. La herramienta crea una tabla con el nombre y el esquema que especifique.
Cree una tabla en SQL Server ejecutando el comando sql-cache create. Proporcione la instancia de SQL Server (Data Source), la base de datos (Initial Catalog), el esquema (por ejemplo, dbo) y el nombre de tabla (por ejemplo, TestCache):
dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Se registra un mensaje para indicar que la herramienta tuvo éxito:
Table and index were created successfully.
La tabla creada por la herramienta sql-cache tiene el esquema siguiente:
Note
Una aplicación debe manipular los valores de caché mediante una instancia de IDistributedCache, no un SqlServerCache.
La aplicación de ejemplo implementa SqlServerCache en un entorno que no es de Development en Startup.ConfigureServices:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
Un ConnectionString (y opcionalmente, SchemaName y TableName) suelen almacenarse fuera del control de origen (por ejemplo, almacenados por el Administrador de secretos o en archivos appsettings.json/appsettings.{Environment}.json). La cadena de conexión puede contener credenciales que se deben mantener fuera de los sistemas de control de origen.
Caché distribuida de Redis
Redis es un almacén de datos en memoria de origen abierto, que suele usarse como caché distribuida. Puede configurar una instancia de Azure Redis Cache para una aplicación de ASP.NET Core hospedada en Azure y usar una instancia de Azure Redis Cache para el desarrollo local.
Una aplicación configura la implementación de la caché usando una instancia de RedisCache (AddStackExchangeRedisCache).
- Cree una instancia de Azure Cache for Redis.
- Copie la cadena de conexión principal (StackExchange.Redis) en Configuración.
- Desarrollo local: guarde la cadena de conexión con Secret Manager.
- Azure: guarda la cadena de conexión en un almacén seguro, como Azure Key Vault
El código siguiente habilita 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();
}
En el código anterior se supone que la cadena de conexión principal (StackExchange.Redis) se guardó en la configuración con el nombre de clave MyRedisConStr.
Para más información, consulte Azure Cache for Redis.
Consulte este problema de GitHub para obtener una explicación sobre los enfoques alternativos de una caché local de Redis.
Caché de Postgres distribuida
Azure Database for PostgreSQL se puede usar como un almacén de respaldo de caché distribuida a través de la IDistributedCache interfaz . Azure Database for PostgreSQL es una oferta de base de datos como servicio (DBaaS) totalmente administrada y lista para inteligencia artificial basada en el motor postgreSQL de código abierto, diseñada para admitir cargas de trabajo críticas con un rendimiento predecible, una seguridad sólida, alta disponibilidad y escalabilidad sin problemas.
Después de instalar el paquete NuGet Microsoft.Extensions.Caching.Postgres , configure la caché distribuida de la siguiente manera:
- Registro del servicio
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();
- Uso de la memoria caché
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;
}
}
Cache distribuido de NCache
NCache es una caché distribuida en memoria código abierto desarrollada de forma nativa en .NET y .NET Core. NCache funciona localmente y configurada como un clúster de caché distribuida para una aplicación de ASP.NET Core que se ejecuta en Azure o en otras plataformas de hospedaje.
Para instalar y configurar NCache en el equipo local, consulte Guía de introducción para Windows (.NET y .NET Core).
Para configurar NCache:
Instale NuGet de código abierto de NCache.
Configure el clúster de caché en client.ncconf.
Agrega el código siguiente a
Startup.ConfigureServices:services.AddNCacheDistributedCache(configuration => { configuration.CacheName = "demoClusteredCache"; configuration.EnableLogs = true; configuration.ExceptionsEnabled = true; });
Uso de la caché distribuida
Para usar la interfaz de IDistributedCache, solicite una instancia de IDistributedCache a cualquier constructor de la aplicación. La instancia se proporciona mediante inyección de dependencias (DI).
Cuando se inicia la aplicación de ejemplo, IDistributedCache se inserta en Startup.Configure. La hora actual se almacena en caché mediante IHostApplicationLifetime (para más información, vea Host genérico: 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);
});
La aplicación de ejemplo inserta IDistributedCache en IndexModel para usarla en la página Índice.
Cada vez que se carga la página Índice, se revisa la memoria caché para verificar la hora en caché en OnGetAsync. Si el tiempo almacenado en caché no ha expirado, se muestra la hora. Si han transcurrido 20 segundos desde la última vez que se accedió a la hora almacenada en caché (la última vez que se cargó esta página), la página muestra Tiempo almacenado en caché expirado.
Actualice inmediatamente la hora almacenada en caché a la hora actual seleccionando el botón Restablecer tiempo almacenado en caché . El botón desencadena el método de controlador OnPostResetCachedTime.
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
No es necesario usar una duración singleton o con ámbito para instancias de IDistributedCache (al menos para las implementaciones integradas).
También puede crear una instancia de IDistributedCache donde quiera que necesite una en lugar de usar la inserción de dependencias, pero crear una instancia en el código puede hacer que el código sea más difícil de probar e infringir el principio de dependencias explícitas.
Recommendations
Al decidir qué implementación de IDistributedCache es la mejor para la aplicación, tenga en cuenta lo siguiente:
- Infraestructura existente
- Requisitos de rendimiento
- Cost
- Experiencia del equipo
Las soluciones de almacenamiento en caché suelen depender del almacenamiento en memoria para proporcionar una recuperación rápida de los datos almacenados en caché, pero la memoria es un recurso limitado y costoso de expandir. Almacene solo los datos usados habitualmente en una memoria caché.
Por lo general, una caché de Redis proporciona un mayor rendimiento y una latencia menor que una caché de SQL Server. Sin embargo, suele ser necesario realizar pruebas comparativas para determinar las características de rendimiento de las estrategias de almacenamiento en caché.
Cuando se usa SQL Server como almacén de respaldo de caché distribuida, el uso de la misma base de datos para la memoria caché y el almacenamiento de datos normal de la aplicación y la recuperación pueden afectar negativamente al rendimiento de ambos. Se recomienda usar una instancia de SQL Server dedicada para el almacén de respaldo de caché distribuida.
Recursos adicionales
- Redis Cache en Azure
- SQL Database en Azure
- Base de datos de Azure para PostgreSQL
- Proveedor de IDistributedCache de ASP.NET Core para NCache en granjas web (NCache en GitHub)
- Cache en memoria en ASP.NET Core
- Detección de cambios con tokens de cambio en ASP.NET Core
- Almacenamiento en caché de respuestas de ASP.NET Core
- Middleware de caché de respuestas en ASP.NET Core
- Asistente de etiquetas de caché en ASP.NET Core MVC
- Asistente de etiquetas de caché distribuida en ASP.NET Core
- Hospedaje de ASP.NET Core en una granja de servidores web