DotNetCore

Redis InMemory Cache in ASP.net MVC Core





A fundamental component of any Data Driven web or mobile application is the ability to access, manipulate and utilise data. The average application will require access data from a number of different data repositories using a number of different data access techniques. These techniques may consist of direct database access , reading, transforming and manipulating XML, CSV, JSON and Text Files , access to SOAP and Restful web services.

Each of these data access techniques and strategies each have their own impact on the performance on a website. In a lot of instances it makes sense to cache data to the memory to either the memory of the web server and in some instances to memory of the client machine.

What is Cache Memory

Caching is a technique of storing frequently used data/ information in memory in order for the same data/information can be accessed quicker and more efficiently by accessing directly form computer memory instead of being re-generated by the application the next time it is needed.

Caching can significantly boost your application performance in ASP.net MVC applications as pages and controls are dynamically generated. It can also enhance data related transaction speeds because these are often expensive in terms of response time.

The primary purpose of caching in applications is to eliminate unnecessary requests to external data sources for data that does not change frequently or store operational user data that does not need to be persisted for future reference.

Caching provides a copy of the data and the copy is maintained for defined duration which is configured by the application

InMemory caching is a simple form of cache data stored in the memory of the local web server.

Why Cache

Enabling Cache into your application certainly does add some additional complexity and therefore most developers are weary of introducing cache into their application stack.

However, Caching does provide 3 benefits that are vitally important for the success of your website:

  • Makes your site faster
  • Provides a better customer experience
  • Saves Money eliminating unnecessary bandwidth costs and server spend

If your web pages require database calls to render in order to get data that does not change all that often, then caching that page data will improve the response times of your page in order of magnitudes.

What to Cache

Identifying and implementing the right caching strategy for your application is purely dependent on the needs and requirements. However, if you’re after the best response possible and want to maximize the performance of your application, then it’s a great idea to go for the highest level possible.

There are several different caching strategies

Browser Caching

Downloading web page assets the network is both slow and expensive. Large responses may require several roundtrips between the client and server, resulting in delays between when they are available and when the browser can process them, and also incurs data costs for the visitor.

The ability to cache and reuse previous resources is a critical aspect of optimizing for performance.

There are several limitations to browser caching :

  • It’s not possible to invalidate cache entries therefore you’ll need to be cautious of setting cache durations
  • You can’t set data dependent cache

HTTP Caching

Content Delivery Network

A Content Delivery Network (CDN) works by providing alternative server nodes for users to download resources (usually static content like images and JavaScript). These nodes spread throughout the world, therefore being geographically closer to your users, ensuring a faster response and download time of content due to reduced latency.

Why use a CDN

InMemory Caching

The in-memory caching system is designed to increase application performance by holding frequently-requested data in memory, reducing the need for database queries to get that data.
The caching system is optimized for use in a clustered installation, where you set up and configure a separate external cache server. In a single-machine installation, the application will use a local cache in the application’s server’s process, rather than a cache server.

Types of In-Memory Cache

Application server. The application manages the relationship between user requests, the near cache, the cache server, and the database.
Near cache. Each application server has its own near cache for the data most recently requested from that cluster node. The near cache is the first place the application looks, followed by the cache server, then the database.

Cache server The cache server is installed on a machine separate from application server nodes in the cluster. It’s available to all nodes in the cluster (in fact, you can’t create a cluster without declaring the address of a cache server).

Local cache The local cache exists mainly for single-machine installations, where a cache server might not be present. Like the near cache, it lives with the application server. The local cache should only be used for single-machine installations or for data that should not be available to other nodes in a cluster. An application server’s local cache does not participate in synchronization across the cluster.

Clustering system The clustering system reports near cache changes across the application server nodes. As a result, although data is not fully replicated across nodes, all nodes are aware when the content of their near caches must be updated from the cache server or the database.




What is Redis

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Why is Redis popular

Redis is extremely fast, effective and simple to use. Getting started with Redis is relatively quick, and it usually takes only a few minutes to get set up and working within an application. Thus, a small investment of time and effort can have an immediate, dramatic impact on performance of the application.

Install Redis

There are a number of different means to install Redis depending on your Development environment and intended deployment Environment.

Windows

Install via msi

The Microsoft Open Tech group develops and maintains Windows port targeting Win64 available. Download the latest .msi and install

Install via chocolatey

if you haven’t installed chocolatey yet I suggest you do. If you come from a Linux environment you can think of chocolatey as a package manager for the Operating system much like apt, yum or dnf

You can also install redis using chocolatey package manager, using choco install redis-64 command.

Linux

Installing Redis on Ubuntu 16.04 is simple

or if you want to build it from the source code you can follow the instructions Redis.io

Mac OSX

The easiest way to install Redis on Mac OSX is via Homebrew

Docker

Check out the official Redis Docker Repository  or check it out in the Docker Store.

It’s also worth checking out Containers & Redis – Running Redis on Windows with Docker

Once you install redis you can run redis-server command to start the redis server.

redis server

Learning Redis

I recommend spending some time following the free Redis Tutorial – try redis and just reviewing the full list of commands available. Although as a Dotnet developer you may not need to interact directly with Redis, it’s still good to understand what is happening under the hood.

Redis UI Tools

Although you can easily use the Redis-Cli to query and extract data from Redis, personally I found it quicker and easier to use GUI during development to see what is going on and check my data.

I found a couple of handy free GUI tools

Redis Persistence

A great advantage of Redis over other InMemory Data Stores, is that Redis can actually persist it’s Data to Disk, and there are 4 options to choose from:

  • RDB (Redis Database File) most common option, it takes a snapshot of your database and stores it on disk in .rdb files. The snapshots can be configured to save after so many requests or at timed intervals. Useful for scheduling timed backups. Drawback of using this method is if your server goes down you should expect some data loss.
  • AOF (Append Only File) – creates a store of all of the Redis Commands, when Redis restarts it executes these commands bringing the database back recent state. This is a much slower solution and the files can grow to large sizes
  • RDB & AOF – A hybrid best of both worlds solution with scheduled backups from RDB and the reliability of AOF.
  • Nothing – use it as a cache and rely on an alternate database for persistent data.



Using Redis in ASP.net MVC Core

Using Redis in ASP.net MVC Core is incredibily easy and you could literally be up and running with Redis in matter of minutes. In my sample project we are going to use Redis for Session Store.

In my example I created a standard ASP.net MVC Core Project. You could of course use any of the other Dotnet core project templates, as the steps for configuration and using will be exactly the same.

Can’t wait to see it in action ?

Check out the code on GitHub

Code

Once the project has been created, we will need to use Nuget to add 2 addtional packages to our project.

We’re now pretty much set up to go, we can now start add some settings to our appsettings.Development.json , these are custom configuration settings we have set them explicitly for our development machine. These settings may change for Production Environment and you will have a different appsettings file for that environment.

 

We are now ready to go configure our application to use Redis for Session store. We just need to edit out Startup.cs

Then we just need to instruct our Application to use the session object.

Adding the AddDistributedCache option enables an Interface IDistributedCache that we can use to add and retrieve values. This also enables controller dependency injection by default, so we can make use of IDistributedCache throughout our web application.

We have now completed most of our configuration required for using Redis.  You can now add some code to the HomeController.cs

 

Updating your Index.cshtml with

Then running the application it should work as expected and your application will now be using Redis for it’s session store.  If you we use our Redis Desktop manager to review our results in Redis Cache we’ll see our results as follows.

Redis Desktop ManagerHowever, you may be thinking to yourself that this is a clunky approach to interacting with the session object. This may be OK on small projects but when you start working on bigger projects or as your project grows this method is going to be become even more awkward and your code will start to look messy!

There has to be a better way!  Well there is, lets implement that.

 

Designing Data-Intensive Applications

Data is at the center of many challenges in system design today. Difficult issues need to be figured out, such as scalability, consistency, reliability, efficiency, and maintainability. In addition, we have an overwhelming variety of tools, including relational databases, NoSQL datastores, stream or batch processors, and message brokers
Buy

Redis is more than just a session cache

Redis stores data in [Key, Value] pairs, enabling the developer to use and store values in efficient ways using a number of different data structures:

  • Strings
  • Lists
  • Hashes
  • Sets
  • Sorted Sets
  • HyperLog

A typical web application needs to be able to store a lot more information in a session or in memory store for users. At the same time applications need to be fast and responsive.

IDistributedCache

All distributed cache implementations should adhere to the IDistributedCache interface, which contains contracts for both Synchronous and Asynchronous methods. It is up to the developer to implement these methods.

For the most part we have already configured the IDistributedCache interface in Startup.cs. We go ahead and Dependency Inject that into our HomeController and start using it right away.
Add the Following line code to your

IDistributedCache has async methods, which are great as you can utlise these to interact with cache repository asynchronously which will also have speed and response improvements.

IDistributedCache allows for storing either string values or byte values. If you want to serialize an object and store the entire thing, you can either serialize it to bytes and save it as bytes, or serialize it to JSON and save it as a string if you prefer.

More cache

Redis is great for expanding the capabilities for session store, but it’s not all it can do.

What if we want to store frequently accessed but not refequently changing data. We may want to store things like json files or even a users shopping basket in memory as they move through your website.

StackExchange Redis

We can very quickly extend our application to make full use of Redis by very quickly integrating the Stackexchange Redis library. We’ll just quickly install the nuget package

In my sample application I have added a new class library project and called it RedisConfig.

The StackExchange.Redis library is a great library and simple to use as it abstracts and simplifies working with Redis making it simpler for DotNet Developers to work efficiently with Redis.

I created a RedisConnectionFactory class which implements a very simple interface

I then registered the ConnectionFactory for Dependency Injection in the Startup.cs as singleton.

Then injected it to the controller.  We can now make use of is as follows

When we run our application we’ll now see the new key being added to our Redis Cache. Our value is now accessible to all users regardless of session, so this may be a good place to store commonly accessed data, which may or may not be a good idea depending on your views and needs. However, from my experience elaborating on this approach has provided some significant performance improvements in some applications.

Obviously we don’t want to be polluting our Controller methods with db.StringSet("somekey", "somevalue"); statements, we’ll want to wrap this to some kind of helper or service we can inject into the controller.

We’ll also possibly want to expand this is include storing of commonly accessed json files etc.

Summary

Making use of Redis as a in memory cache repository can seriously improve the performance of your website, mobile application or even Api Service.

Redis as a caching solution has great advantages over traditional memory caching, as it persists to disk and its data is available across applications rather than a single server process.

If you’ve made it this far, then you certainly are ready to read my follow up Why, When and How to use Redis in ASP.net MVC Core

Gary Woodfine

Freelance Full Stack Developer at threenine.co.uk
Helps businesses by improving their technical proficiencies and eliminating waste from the software development pipelines.

A unique background as business owner, marketing, software development and business development ensures that he can offer the optimum business consultancy services across a wide spectrum of business challenges.
π