In this article, we are going to do a small demo on integrating Azure Redis Cache into the AspNetCore Application using Distributed cache technique.Let's understand the flow of Redis cache in a web application:
(4)The 'Tags', name/value pairs is an optional section.
(5)Finally, select 'Review+ Create', on successful validation, select 'create', on success in a few minutes our Redis instance will be ready.
(4) Now under 'Settings' select 'Access Keys', then copy the connection string either primary or secondary connection string.
Now copied Redis connection string needs to add to our Web API project.
Now for the second request, the 'LoadedFromRedis' property returns true, which confirms data coming from the Redis-store.
Redis Cache:
Redis is an open-source in-memory data structure store, used as a database, cache. It supports data structures such as strings, hashes, lists, sets, stored sets with range queries, etc.
- Users request a page from the web application.
- Web application queries the Redis store, if the data exists, then fetches the data and returns the response directly to the user.
- If no data is in the Redis store, the application queries the database and fetches the data, next save the same data into the Redis store so that subsequent user request can consume the data from the Redis store directly, finally returns the response to the users.
Create A Azure Redis Cache:
Step:1
Create and sign-in into the Azure portal(https://portal.azure.com/)
Step:2
On the Azure portal home page click on 'Create a resource'.
Step:3On the 'Create a resource' page select the 'Databases' and then select 'Azure Cache for Redis'.
Step4:(1)On the 'New Redis Cache' page, enter the project details.
- Subscription- Choose your subscription plan from the dropdown.
- Resource group - Either create a new resource group or select an existing group from the drop-down.
- DNS name- Enter the name of your Redis instance subdomain name.
- Location- Choose your server location from the dropdown.
- Cache type- Select pricing plans for Redis usage. no free plans on it.
(4)The 'Tags', name/value pairs is an optional section.
(5)Finally, select 'Review+ Create', on successful validation, select 'create', on success in a few minutes our Redis instance will be ready.
IDistributedCache Interface:
IDistributedCache interface is implemented from the 'Microsoft.Extensions.Caching.Distributed' library. IDistributedCache is not specific to Redis Cache, but it was implemented like generic which supports all kinds of Distributed Cache like Redis, SQL Server Cache, etc. IDistributedCache supports the default dependency injection of .NET Core, so it can be easily injected into the application where ever needed. IDistributedCache Interface holds a set of methods that helps to work with cache, some of the methods like as below.
- Get, GetAsync - fetches the cached data by the key passed.
- Set, SetAsync - saves the data to the cache-store.
- Remove, RemoveAsync - removes the cached data specific to key passed.
Create A .NET6 Web API Project:
Let's create a .Net6 Web API sample application to accomplish our demo. We can use either Visual Studio 2022 or Visual Studio Code(using .NET CLI commands) to create any.Net6 application. For this demo, I'm using the 'Visual Studio Code'(using the .NET CLI command) editor.
CLI command
dotnet new webapi -o Your_Project_Name
dotnet new webapi -o Your_Project_Name
Install NuGet Package:
Package Manager:
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis -Version 6.0.1
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis -Version 6.0.1
.NET CLI:
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --version 6.0.1
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --version 6.0.1
Configure Azure Redis ConnectionString:
(1)On the Azure portal home page click on 'Resource groups'.
(2) On the 'Resource groups' page, select the resource group that has our Azure cache for Redis.(3) Now click 'Azure Cache for Redis' instance.(4) Now under 'Settings' select 'Access Keys', then copy the connection string either primary or secondary connection string.
appsettings.Development.json:
"ConnectionStrings": { "AzureRedisConnection":"Your_Azure_Redis_Connection_Value" }Now register the Redis Cache service into the 'Program.cs' file.
Program.cs:
builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("AzureRedisConnection"); });
- Here registered the 'AddStackExchangeRedisCache' service.
- The 'Configuration' property is assigned with the Azure Redis connection string value.
Create A Sample API Response Model:
Let's create a sample class that will be our response object model like the 'Car.cs' file in the 'Models' folder.
Models/Cars.cs:
namespace Dot6.AzureRedis.Learn.Models; public class Car { public int Id { get; set; } public int Year { get; set; } public string Manufacturer { get; set; } public string Model { get; set; } }
Create A Sample API Controller:
Let's create a sample API controller like 'CarController.cs'.
Controllers/CarController.cs:
using System.Text; using System.Text.Json; using Dot6.AzureRedis.Learn.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; namespace Dot6.AzureRedis.Learn.Controllers; [ApiController] [Route("[controller]")] public class CarController : ControllerBase { private readonly List<Car> fakeDatabase = new List<Car> { new Car { Id = 1, Manufacturer = "Honda", Model = "Civic", Year = 2021 }, new Car { Id = 2, Manufacturer = "Kia", Year = 2021, Model ="Seltos" } }; private readonly IDistributedCache _cache; public CarController(IDistributedCache cache) { _cache = cache; } }
- (Line: 13-29) The 'fakeDatabase' variable contains mock or test data for our demo, in real-time application data will be fetched from the database.
- (Line: 31) The 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' interface is injected into the controller.
Use GetAsync And SetAsync:
GetAsync - This asynchronous method fetches the byte array of data from the Redis-store for a specified key.
SetAsync - This asynchronous method saves the byte array of data with a key for it like a dictionary. If we intended to save any object or collection of objects into the Redis-store then we serialize our data to a string, then string to byte array of data.
Let's create a sample API action method that uses our Redis-store.
Controllers/CarController.cs:
[HttpGet] public async Task<IActionResult> Get() { var carsFromRedis = await _cache.GetAsync("carstore"); if ((carsFromRedis?.Count() ?? 0) > 0) { var carsString = Encoding.UTF8.GetString(carsFromRedis); var cars = JsonSerializer.Deserialize<List<Car>>(carsString); return Ok(new { LoadedFromRedis = true, Data = cars }); } var fakeDatabaseString = JsonSerializer.Serialize(fakeDatabase); var fakeDatabaseByteArray = Encoding.UTF8.GetBytes(fakeDatabaseString); await _cache.SetAsync("carstore", fakeDatabaseByteArray); return Ok(new { LoadedFromRedis = false, Data = fakeDatabase }); }
- (Line: 4) Using 'GetAsync("key")' trying to fetch byte array of data from the store.
- (Line: 5) Checking whether we got a response from the Redis store.
- (Line: 7) Converting the byte array of data into the string.
- (Line: 8) Converting the string to the collection of 'Car' types.
- (Line: 9) Returning API response, here for our understanding added a flag property like 'LoadedFromRedis' to our response.
- (Line: 12) If the data does not exist in the Redis store this line of code starts executing. Here serializing the collection of 'car' types to string.
- (Line: 13) Converting string result to byte array.
- (Line: 14) Using 'SetAsync' with help of 'key' and 'value'(byte array of data) stored into the Redis store so that the next client request to API endpoint can return a response directly from Redis store.
Now for the second request, the 'LoadedFromRedis' property returns true, which confirms data coming from the Redis-store.
Cache Expiration:
The cache should have an expiry date. To define expiration we have two options that are mandatory for a good coding approach.
- Absolute Expiration
- Sliding Expiration
Absolute Expiration - Maximum time period to store in the cache After expiration Redis will automatically delete all keys and their values automatically.
Sliding Expiration - Maximum time period to store data without consuming by the application. If an application not using any particular keys for a specific time it is always good to clear them from the cache before its Absolute Expiration. This type of expiration will be called a Sliding Expiration. One important thing to remember sliding expiration is always less than Absolute Expiration time if you set Sliding Expiration more than Absolute Expiration id doesn't make any sense because data will be cleared after the Absolute expiration time.
Let's update our action method logic to use expiration.
Controllers/CarController.cs:
[HttpGet] public async Task<IActionResult> Get() { var carsFromRedis = await _cache.GetAsync("carstore"); if ((carsFromRedis?.Count() ?? 0) > 0) { var carsString = Encoding.UTF8.GetString(carsFromRedis); var cars = JsonSerializer.Deserialize<List<Car>>(carsString); return Ok(new { LoadedFromRedis = true, Data = cars }); } var fakeDatabaseString = JsonSerializer.Serialize(fakeDatabase); var fakeDatabaseByteArray = Encoding.UTF8.GetBytes(fakeDatabaseString); var expiration = new DistributedCacheEntryOptions{ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20), SlidingExpiration = TimeSpan.FromSeconds(19) }; await _cache.SetAsync("carstore", fakeDatabaseByteArray, expiration); return Ok(new { LoadedFromRedis = false, Data = fakeDatabase }); }
- (Line: 14-17) Defined 'Absolute Expiraiton' and 'Sliding Expiration' for our Redis-store.
- (Line: 18) The 'SetAsync' had an overloaded method that can accept the expiration object.
Use RemoveAsync:
It is always good to have an endpoint to clear the data in Redis-store. The 'RemoveAsync' method will remove our cached data with respect to the key passed to it.
Controllers/CarController.cs:
[HttpGet] [Route("remove")] public async Task<IActionResult> Remove() { await _cache.RemoveAsync("carstore"); return Ok(); }
Support Me!
Buy Me A Coffee
PayPal Me
Video Session:
Wrapping Up:
Hopefully, I think this article delivered some useful information on Use Azure Cache For Redis in the AspNetCore Application Distributed Cache technique. using I love to have your feedback, suggestions, and better techniques in the comment section below.
Comments
Post a Comment