Click here to Skip to main content
Click here to Skip to main content

Implementing Local MemoryCache Invalidation with Redis

, 1 Jan 2014
Rate this:
Please Sign up or sign in to vote.
We need to use all the tools at our disposal to develop faster and more robust applications. One of the ways we can achieve this is by using caching. Previously, under the System.Web.Caching.Cache namespace, the new  -4.0- System.Runtime.Caching.Memory is more…Read more ›

We need to use all the tools at our disposal to develop faster and more robust applications. One of the ways we can achieve this is by using caching. Previously, under the System.Web.Caching.Cache namespace, the new  -4.0- System.Runtime.Caching.Memory is more mature and still as powerful as its ancestor. It’s really easy to use and I think that every asp.net programmers have already used it. So, I won’t speak too much about this here.

The default caching strategy is the cache-aside programming pattern: This means that if your data is not present in the cache, your application, and not something else, must reload data into the cache from the original data source.

This works very well for most common use cases, but there is a hidden trade-off: caching means working with stale data. Should I increase the cache duration? Should I keep short TTL value? It’s never easy to answer to these questions, because it simply depends on your context: number of clients, user load, database activity…

Another common problem is how to update/remove instantly something from the cache on all your cache clients, such as this typical request from Product Owner ” I want a parameter to be instantly updated on all our XXX servers, but do not fear, I will only change it a few times per year”

I will investigate a not so new concept in this post: setup local cache invalidation using Redis.

What is Local Cache invalidation ?

Cache invalidation is a process whereby entries in a cache are removed/deleted.
This concept is not specific to .net but to all technologies.
The idea here is to send invalidation message to each server and do not wait –as usual- item expiration.

Why Redis ?

Redis is an open-source, networked, in-memory, key-value data store with optional durability. (Note familiar? Read the great documentation here). It’s now the most popular NoSql database, and many internet  leaders are using it (Instagram, Stackoverflow, Twitter, GitHub, Tumblr, Pinterest, …). For the joke, nothing will be stored in Redis, and we will only use the PubSub feature.

And yes, since I discovered Redis, I’m a big fan :-)

Implementation

Requires : .net, Redis & Booksleeve (high perf C# redis client).

The concept is quite handy :  Redis events (pub/sub) give us  an easy way to broadcast something to all nodes (lossely coupled), so they can drop their local copy – meaning: next time it is needed we’ll pick up the new copy from the data tier.

So, The redis pub/sub events are used to invalidate the cache for a given key from one node (the one that knows the state has changed) immediately to all nodes. A node could be a front web site, a back app or any redis client.

Local cache invalidation is done with ChangeMonitor class : “Provides a base class for a derived custom type that monitors changes in the state of the data which a cache item depends on”. It’s the base class of FileChangeMonitor and SqlChangeMonitor.

redisinvalidation

A few details:

  • A single connection is opened to redis, as BookSleeve is a thread-safe multiplexer
  • As there is a single connection to redis and possibly many monitors, I use a topic-based observer pattern to manage notification inside the application
  • I send only invalidation message following this format :  channel = “invalidate”, and message = “keytoremove”.

Here is a possible implementation in an asp.net application

  • Redis Configuration Configuration
// somewhere in your global.asax (for an asp.net application)
// be sure a redis instance is running on localhost
// check /tools/redis-server.exe
CacheInvalidation.UseRedis(new RedisConnectionInfo() {
     Host = "localhost"
});
  • How to create a redis changemonitor
// somewhere in your code
var cacheItem = new CacheItem("onekey", "onevalue");
var policy = new CacheItemPolicy();
policy.ChangeMonitors.Add(CacheInvalidation.CreateChangeMonitor(cacheItem));
// just to create not expirable item
policy.AbsoluteExpiration = DateTime.Now.AddYears(1);
MemoryCache.Default.Add(cacheItem, policy);

Various Benefits

  • Not limited to .net, and any redis client could invalidate cache item on subscribers
  • Multi-Memory Cache support and not only the default
  • Supports out-of-process invalidation
  • Fully compatible with existing applications, as the invalidation is done by a separate piece of code, in another thread in asp.net
  • Allow you to invalidate a list of items
  • Redis connection unavailable ?
    • Temporary failure : Not a problem as the bus will try to reconnect automatically
    • Redis server not available : No-op, and your application will run without any problems

Knowing how to invalidate, will not resolve all your problems :-)

“There are only two hard problems in Computer Science: cache invalidation and naming things.”, Phil Karlton.

Further considerations …

What about combining local cache invalidation with an out-of-Process caching system?

There is where thing gets interesting: Keep the best of the two worlds and implement a 2-tier cache – i.e. using local memory and the out-of-process cache (distributed).

This is well explained by Marc Gravell, creator of BookSleeve,

“Going off to another system is never faster than querying local memory (as long as it is keyed); (@Stackoverflow) we use both!”

Finally, this also a funny way to introduce Redis in a non-critical scenario. So do not hesitate.

The GitHub Repo is available here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Betclic Tech
Chief Technology Officer Betclic
France France
I am Head of Software Development at Betclic France. I manage the Paris Dev Team, consisting of 35+ talented people, in various technical and functional projects in the fields of sports betting, poker, casino or horse betting.
 
Check out our technical blog at https://techblog.betclicgroup.com
Group type: Organisation

3 members

Follow on   Twitter

Comments and Discussions

 
QuestionWhy subscribe does'nt received publish message? PinmemberMember 1023216313-Apr-14 22:30 
QuestionVery good article! PinmemberVolynsky Alex1-Jan-14 8:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 1 Jan 2014
Article Copyright 2014 by Betclic Tech
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid