¿Qué es Hybrid Cache?
Hybrid Cache en .NET 9 une lo mejor del caché en memoria (acceso rápido y local) y el caché distribuido (durabilidad y estado compartido entre servidores). Introduce una clase abstracta, HybridCache, y su implementación por defecto, DefaultHybridCache, que permite una integración fluida de diversas capas de caché. Sus características principales incluyen:
- Caché multinivel: Combina caché en memoria y distribuido para un rendimiento óptimo.
- Evicción por etiquetas: Soporta escenarios avanzados como la eliminación selectiva de entradas de caché.
- Flexibilidad en serialización: Permite usar serializadores personalizados para claves y valores de caché.
- Operaciones asíncronas: Diseñado para flujos de trabajo exclusivamente asíncronos, acorde con patrones modernos de aplicaciones.
Casos de Uso en el Mundo Real
- Plataformas de comercio electrónico: Hybrid Cache es ideal para aplicaciones de venta en línea que necesitan acceso rápido a datos frecuentemente usados, como detalles de productos y sesiones de usuarios.
- Redes de entrega de contenido (CDNs): Benefician al cachear activos estáticos localmente para una entrega rápida, mientras mantienen un caché distribuido para contenido dinámico y personalizado.
- Aplicaciones críticas: En este tipo de apliaciones, la consistencia y velocidad de datos son cruciales. Hybrid Cache soporta un caché seguro y de alto rendimiento.
- Arquitecturas de microservicios: En aplicaciones basadas en microservicios, Hybrid Cache proporciona caché en memoria local para servicios individuales y un caché distribuido compartido para la comunicación entre servicios.
Ventajas de Hybrid Cache en .NET 9
- Optimización del rendimiento: Reduce el número de accesos a la base de datos y la latencia de la red al utilizar caché en memoria para datos frecuentes.
- Eficiencia de costos: Minimiza los costos de infraestructura en la nube optimizando los mecanismos de almacenamiento y recuperación de datos.
- Productividad del desarrollador: Simplifica la implementación con una API de caché unificada, reduciendo el código repetitivo.
- Flexibilidad: Permite un control granular sobre estrategias de caché, como políticas de evicción por niveles y opciones de serialización.
Configuración de Hybrid Cache
Prerrequisitos
- Tener instalado el SDK de .NET 9.
- Un proyecto donde se requiera caché (por ejemplo, una aplicación ASP.NET Core).
- Paquetes NuGet para proveedores de caché distribuido, como Microsoft.Extensions.Caching.StackExchangeRedis.
Instalar Paquetes NuGet Necesarios
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
dotnet add package Microsoft.Extensions.Caching.Memory
Ejemplo: Almacenar y Recuperar Datos de Países con Hybrid Cache
Modelo de Datos de País
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
public int Population { get; set; }
}
Program.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Caching.Hybrid;
var builder = WebApplication.CreateBuilder(args);
// Añadir caché en memoria
builder.Services.AddMemoryCache();
// Añadir caché distribuido Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
// Reemplaza con tu cadena de conexión del servidor Redis
options.Configuration = "localhost:5000";
});
// Añadir Hybrid Cache
builder.Services.AddHybridCache(options =>
{
// Establecer duración de caché predeterminada
options.DefaultCacheDuration = TimeSpan.FromMinutes(5);
});
// Configurar Hybrid Cache
builder.Services.Configure<HybridCacheOptions>(options =>
{
options.DefaultCacheDuration = TimeSpan.FromMinutes(10); // Duración personalizada
options.Serializer = new JsonHybridCacheSerializer(); // Usar serialización JSON
options.EvictionPolicy = HybridCacheEvictionPolicy.FirstLevel |
HybridCacheEvictionPolicy.SecondLevel; // Políticas de evicción
});
var app = builder.Build();
app.MapGet("/country/{code}", async (string code, CountryService countryService) =>
{
var country = await countryService.GetCountryAsync(code);
return country is not null ? Results.Ok(country) : Results.NotFound();
});
app.Run();
Servicio
using Microsoft.Extensions.Caching.Hybrid;
public class CountryService
{
private readonly IHybridCache _hybridCache;
public CountryService(IHybridCache hybridCache)
{
_hybridCache = hybridCache;
}
public async Task<Country> GetCountryAsync(string countryCode)
{
// Clave de caché
string cacheKey = $"Country_{countryCode}";
// Intentar obtener el país del caché
var country = await _hybridCache.GetAsync<Country>(cacheKey);
if (country == null)
{
// Simular la obtención de datos de la base de datos
country = new Country
{
Code = countryCode,
Name = "País de Ejemplo",
Population = 1000000
};
// Almacenar el país en caché
await _hybridCache.SetAsync(cacheKey, country, TimeSpan.FromMinutes(5));
}
return country;
}
}
Conclusion
La novedad es que prácticamente solo cambia la inyección de dependencias, por lo que migrar es muy sencillo. Recuerda que, por ejemplo, para intentar obtener información de la caché distribuida sería algo así: var cachedCountry = await _distributedCache.GetStringAsync(cacheKey);
y para la caché en memoria sería algo así: _memoryCache.TryGetValue(cacheKey, out Country country)
.
Además, si mezclas ambos en un servicio tipo L1 y L2, te ahorrarás codigo para la búsquedas en dos sitios, con el sistema híbriro solo tienes código para buscar en un solo sitio. Como veis, no tiene ningún misterio; en 5 minutos ya sabes todo lo necesario sobre caché híbrida.
¿Dónde guardar los datos?
Esta observación es muy importante. No puedes especificar dónde guardar los datos, se almacenan tanto en memoria como distribuido.
var builder = WebApplication.CreateBuilder(args);
// Agrega servicios al contenedor.
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
// Configuración de opciones globales para HybridCache
options.MaximumPayloadBytes = 1024 * 1024; // Tamaño máximo de una entrada de caché
options.MaximumKeyLength = 1024; // Longitud máxima de la clave de caché
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(5), // Expiración para la caché distribuida
LocalCacheExpiration = TimeSpan.FromMinutes(1) // Expiración para la caché en memoria
};
});
Como se puede observar en el ejemplo anterior, la biblioteca HybridCache
en ASP.NET Core está diseñada para gestionar automáticamente múltiples niveles de caché. Esto significa que intenta guardar y recuperar datos tanto de la caché en memoria como de la caché distribuida según la configuración predeterminada.
Si necesitas un control más granular para decidir explícitamente si un dato debe ser almacenado en la caché en memoria o en la caché distribuida, es necesario utilizar directamente tanto la caché en memoria (IMemoryCache
) como la caché distribuida (IDistributedCache
).
Es importante tener mucho cuidado si decides eliminar tu configuración de caché actual, ya que podrías perder esa granularidad. Además, en entornos de microservicios, el uso de IMemoryCache
puede provocar problemas en los Pods si estás utilizando Kubernetes (K8s), debido a que la caché en memoria es local a cada instancia del servicio y no se comparte entre Pods.