NET 7 and Redis
A Quick Guide
This article’ll dive into Redis
a distributed caching technology and how to wield it in your .NET application.
If you’re new to the world of memory cache, check out this article for the basics.
This piece will also house the example we will embark on.
All set? Awesome, let’s jump right in!
Get your hands on the source code here.
Understanding Redis
Redis
is an in-memory data structure store that can serve as a database, cache, and message broker. It's a Jack of all trades!
Famous for its high performance (because it operates in memory), Redis
also packs a punch with features such as:
- Transactions
- Replication
- Failure recovery
- Messaging
- Data expiration times
Compared to the conventional memory cache discussed in our previous article, Redis
is an excellent choice for distributed systems as it centralizes the storage of objects in memory with supreme performance. It also provides systems with fault tolerance and replication, making it a resilient alternative for distributed systems.
Starting a Redis
Instance
For maximum convenience, I’m employing Docker
to fire up a local Redis
server instance. Here's the command I used:
docker container run -d -p 6379:6379 --name redis redis
Connecting with Docker Container running Redis
For interacting with the Redis
server, the RedisInsight comes in handy.
Configuration
The next step is to install the necessary NuGet Package(s). To install the required packages into your project, right-click on the solution and the select Manage NuGet Packages for Solution, Now search the two packages named Microsoft.Extensions.Caching.StackExchangeRedis
and StackExchange.redis
in the search box and install these packages one at a time. Alternatively, you can type the commands shown below at the NuGet Package Manager Command Prompt:
PM> Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
PM> Install-Package StackExchange.Redis
You need to provide a configuration (similar to a connection string) and the instance name when calling this method at the class Program
builder.Services.AddStackExchangeRedisCache(options =>
{
options.InstanceName = "My Redis Instance";
options.Configuration = "localhost:6379";
});
builder.Services.AddHttpClient();
The instance name comes into play when creating the key name in Redis
.
Implementing a Solution Using Redis
Based on our previous example, we’re going to use the public RestCountry API to retrieve data about the world’s countries.
The Country
class, which represents the data to be saved, is implemented as follows:
public class Country
{
public string Name { get; set; }
public string Capital { get; set; }
public string Region { get; set; }
public string Demonym { get; set; }
}
Post defining the Country
class, we'll create the CountriesController
. Next, we'll implement the GetCountries
action, which can be accessed by the HTTP GET method at the api/countries
path.
[Route("api/[controller]")]
public class CountriesController : ControllerBase
{
private readonly IDistributedCache _distributedCache;
private readonly IHttpClientFactory _httpClientFactory;
private const string CountriesKey = "Countries";
private const string RestCountriesUrl = "https://restcountries.eu/rest/v2/all";
public CountriesController(IDistributedCache distributedCache, IHttpClientFactory httpClientFactory)
{
_distributedCache = distributedCache;
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<IActionResult> GetCountries()
{
var countriesObject = await _distributedCache.GetStringAsync(CountriesKey);
if (!string.IsNullOrWhiteSpace(countriesObject))
{
return Ok(countriesObject);
}
var httpClient = _httpClientFactory.CreateClient();
var response = await httpClient.GetAsync(RestCountriesUrl);
var responseData = await response.Content.ReadAsStringAsync();
var countries = JsonConvert.DeserializeObject<List<Country>>(responseData);
var memoryCacheEntryOptions = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3600),
SlidingExpiration = TimeSpan.FromSeconds(1200)
};
await _distributedCache.SetStringAsync(CountriesKey, responseData, memoryCacheEntryOptions);
return Ok(countries);
}
}
In this example, the flow follows:
- Fetch data from
Redis
with a key specified in theCountriesKey
constant. - If it’s not empty or null, return OK with the cached data. This is the quickest path.
- If not, create a
HttpClient
using theHttpClientFactory
. - Make the call to the
RestCountriesUrl
. - Get the return as a string and deserialize it into a list of
Country
. - Instantiate the
Redis
cache settings, defining an absolute expiration time (of 1 hour, or 3600 seconds), and a relative time which resets with each access (of 20 minutes, or 1200). - Save the returned API object in the
Redis
cache. - Return OK with the list.
The DistributedCacheEntryOptions
class handles the configuration, and the IDistributedCache
interface performs the operations.
And there you have it! Your key in Redis
is created after an API call, bearing a concatenation of the InstanceName
and the key defined at the time of insertion.
The Pros and Cons of Using Redis
Every coin has two sides, and Redis
is no exception. So, buckle up and let's embark on a joyride to explore both the scenic landscapes and the bumpy terrains of Redis
!
Pros
Super Speedy Gonzalez
Redis
lives in memory, and we all know that memory is like the superhero Flash when compared to the snail-paced disk storage. This allows Redis
to fetch and store data at warp speed.
The Data Type Dynamo
Unlike your garden-variety databases, Redis
boasts a robust arsenal of data types. List, Set, Sorted Set, Hash, you name it! So, whether you're organizing a potluck or plotting world domination, Redis
has you covered!
Expiration Dates aren’t Just for Milk
With Redis
, you can set a time-to-live on any piece of data. So, unlike that bowl of leftover spaghetti in your fridge, your data will know when it's time to leave gracefully.
Clustering and Replication
Redis
allows for data sharding and master-slave replication, making it the Batman and Robin of the database world – an unbeatable team-up when it comes to fighting against data loss and ensuring high availability.
Cons
Forgetful Fred
Since Redis
primarily relies on memory; if there's a power outage or the system crashes, Redis
might lose more recent data, behaving like your friend Fred who can never remember where he put his keys.
Not a Big Fan of Complex Queries
Redis
is all about speed, and complex queries are like speed bumps on its racetrack. While Redis
does support basic operations, don't expect it to perform complex joins or subqueries like a relational database would.
Size Matters
With Redis
, your data must fit into memory, so if you have more data than memory, you will have a problem. It's like trying to squeeze a hippo into a Mini Cooper – something's gotta give!
It’s All about the Money, Honey!
Yes, memory is fast. But it’s also more expensive than disk space. The cost might be a significant hurdle if your budget looks more like a student’s lunch money than a CEO’s bonus.
So, there you have it, folks! The highs and lows, the yays and nays of Redis
. Remember, like any technology, Redis
isn't a silver bullet. It's all about finding the right tool for the job. So, weigh these pros and cons, and make your choice wisely.
Final Thoughts
Well, folks, we’ve embarked on quite a journey today, haven’t we? From the dizzying heights of in-memory data structures to the practicalities of Docker, we’ve traversed the dynamic landscapes of Redis
and the ASP.NET Core
applications. And let's not forget the high-speed chase through the HTTP corridors with HttpClient
.
Like any unforgettable adventure, we’ve had our share of thrills and chills. We discovered that Redis
could be both a speed demon and a forgetful friend. But, hey, nobody's perfect, right? Just like your favorite superhero, Redis
too has its strengths and weaknesses.
Just remember this: Use Redis
where it shines brightest, but don't forget its limitations. Sometimes, the fastest car isn't the best choice for a scenic drive. And sometimes, that same car is exactly what you need to win the race.
So, keep exploring, keep experimenting, and most importantly, keep coding. Because in this ever-evolving world of technology, there’s always something new to learn and a problem that needs a solution.
Happy coding!
If you like the article and would like to support me, make sure to:
- 👏 Clap for the story (50 claps) to help this article be featured
- 👉 Follow me on Medium
- 📰 View more content on my medium profile
- 🔔 Get in Touch: LinkedIn
Take advantage of my other stories! 👇🔽