Caching is essential for optimizing application performance by lowering data retrieval latency and reducing the number of database or API calls. In .NET 9.0, Microsoft has introduced improved caching strategies, including Hybrid Caching, which merges the advantages of in-memory and distributed caching. This blog delves into Hybrid Caching in .NET 9.0, covering its benefits, implementation, and best practices.

What is Hybrid Caching?

Hybrid Caching is a strategy that combines in-memory and distributed caching to optimize performance and scalability. It leverages the speed of in-memory caching while maintaining persistence and scalability through distributed caching solutions like Redis or SQL Server.

Advantages of Hybrid Caching

Cache Stampede. Issue and Solution


What is Cache Stampede?

A cache stampede occurs when multiple concurrent requests attempt to access the same data from the cache but encounter a cache miss. As a result, all requests simultaneously query the original data source, potentially overwhelming it with excessive load.

How Hybrid Caching Prevents Cache Stampede?

Hybrid Caching in .NET 9.0 helps mitigate cache stampede through:

Implementing Hybrid Caching in .NET 9.0

The source code can be downloaded from GitHub

Hybrid Caching in .NET 9.0 can be implemented using Microsoft.Extensions.Caching.Hybrid is currently an experimental package that is under preview. Below is a step-by-step guide to integrating it into your application:

1. Install the Required Package

Begin by installing the required NuGet package:

Microsoft.Extensions.Caching.StackExchangeRedis 
Microsoft.Extensions.Caching.Hybrid

Browse

Note: I installed the Redis from this gitHub

2. Configure Caching Service

Modify the Program.cs file to configure Hybrid Caching.

using HybridCachingIndotNET9._0;
using Microsoft.Extensions.Caching.Hybrid;
using Scalar.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddSingleton<HybridCacheService>();

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "your redis connection string";
    options.InstanceName = "HybridCache";


});

#pragma warning disable EXTEXP0018 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
builder.Services.AddHybridCache(options =>
{
    // Maximum size of cached items
    options.MaximumPayloadBytes = 1024 * 1024 * 10; // 10MB
    options.MaximumKeyLength = 512;

    // Default timeouts
    options.DefaultEntryOptions = new HybridCacheEntryOptions
    {
        Expiration = TimeSpan.FromMinutes(30),
        LocalCacheExpiration = TimeSpan.FromMinutes(30)
    };

});
#pragma warning restore EXTEXP0018 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

3. Implement Hybrid Caching Logic

using Microsoft.Extensions.Caching.Hybrid;

namespace HybridCachingIndotNET9._0
{
    public class HybridCacheService
    {
        private readonly HybridCache _hybridCache;
        private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(30);

        public HybridCacheService(HybridCache hybridCache)
        {
            _hybridCache = hybridCache;
        }

        public async Task<string> GetCachedDataAsync(
            string key,
            CancellationToken ct)
        {
            var product = await _hybridCache.GetOrCreateAsync(
         $"product-{key}",
         async token =>
                         {
                             return await FetchData(key, token);
                         },
         cancellationToken: ct
            );
         return product;

        }

        private async Task<string> FetchData(string key, CancellationToken ct)
        {
            // Simulate a long-running operation
            await Task.Delay(5000, ct);
            return $"Product {key}";
        }

    }
}

4. Inject and Use HybridCachingService

Register the HybridCachingService in the Program.cs

builder.Services.AddSingleton<HybridCacheService>();

Use this service in the Controller.

using Microsoft.AspNetCore.Mvc;

namespace HybridCachingIndotNET9._0.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class DataController : ControllerBase
    {
        private readonly HybridCacheService _hybridCacheService;
        public DataController(HybridCacheService hybridCacheService)
        {
            _hybridCacheService = hybridCacheService;
        }
        
        [HttpGet("get-data")]
        public async Task<IActionResult> Get(CancellationToken ct)
        {
            var data = await _hybridCacheService.GetCachedDataAsync("test", ct);
            return Ok(data);
        }
    }
}

5. Execute the code and see the result

Execute

Effective Hybrid Caching Practices

Ina addition to this, there is a concept, Tags, which help categorize or group cache entries, making cache invalidation, eviction, and management more efficient, particularly in a hybrid setup. Please refer the Microsoft learning for more details.

When Redis is added as a caching solution in a hybrid setup, it usually serves as the L2 (Level 2) cache by default.

How Redis Becomes L2 in Hybrid Caching?

In a hybrid caching setup, Redis is often used to manage larger datasets that need to be persistent and accessible across multiple application instances. As a distributed, high-performance caching solution, Redis operates outside of the application's memory, typically storing data in a separate service, which classifies it as a Level 2 (L2) cache.

Data Flow Process

Example Workflow in Hybrid Caching

Conclusion

Hybrid Caching in .NET 9.0 provides a powerful solution for improving application performance, minimizing latency, and optimizing resource usage. With Microsoft.Extensions.Caching.Hybrid developers can achieve enhanced speed and scalability in a more efficient manner. By following best practices for cache management, applications become more resilient and performant. Moreover, Hybrid Caching includes built-in features to prevent cache stampede, ensuring a stable and effective caching strategy for contemporary applications.

Happy Coding!