Utilising
Azure Redis Cache

Jan 10

Introduction

If your site is running on the Azure platform then you may be interested in leveraging the Azure Redis Cache to help reduce and improve your sites performance.

This is more of a follow up post from my last post on storing the ViewState of a page in the Session rather than the default of a hidden field in the web page. I also want to promote an option when looking at caching.

Sitefinity, as of 8.2, supports multiple nodes running yoru site on Azure Web Sites by utilising the Azure Redis Cache as the central point of communication between nodes to manage its local cached items.

Sitefinity Memory

Sitefinity is quite a memory hungry application. Just to start it requires a few hundred MB of memory. Run it for a while and you may find it averages out at 500MB. If you look in the bin folder you will find 200MB of dlls. Some are only loaded when required and you can turn off modules that you don't need in the back-end but still, a lot of files.

There are a lot of utility files in there, AjaxControlToolKit, HtmlAgility, etc. They provide a lot instant functionality but if you only want one piece of functionality you still have to load the whole dll. Then there is the multiple of web service options. WCF, ServiceStack, WebApi. Good to have options I guess. My personal preference is to remove excess stuff. Settle on one web service method rather than using and loading them all. But I also know the impracticality of this. Once you add something its very hard to remove it without customers causing a stink. "What?!?, you wish to remove support for IE8!".

For most people who are running one Sitefinity site on one box, or multiple, then memory isn't often a biggie but sometimes you may be running multiple sites and then you have a care factor.

Move Cache Storage Away

Sitefinity stores all its cache in local memory. It's the only option but it is the easiest and fastest. Downside is that it is local for every server so if you have 5 web servers that means you are caching each object 5 times. One on each server. Sitefinity has to implement communication between all servers and manage those cached items. Not very efficient. I have always been voicing my request to have the option to implement a distributed cache option so we can store one version of the cached page that each server can access and invalidate for the group. Though not implemented yet we do have some options available.

In my last article I talked about moving the ViewState to the Session State. In there I voiced my opinion of using Azure Redis Cache and I will show you how to set up that and take advantage of it.

Azure Redis Cache

First thing to do is go to your Azure subscription and set up a Redis Cache service.

You may already be using Azure Redis Cache to load balance your Sitefinity site so feel free to use the same instance.

We will start with putting our Session State data there first. Go to Nuget and install Microsoft.Web.RedisSessionStateProvider. Once done it is just a matter of updating the web config with your host and access key details. That's it. All your session data, (and ViewState data if you implemented my last article), are now being stored in your Redis Cache and not your local memory.

Microsoft Redis Cache Session State Provider

Now this won't save you much in memory unless you are heavily using it. But one thing you can now do is use this cache for your application.

Think about places where you are pulling data from the database or making web requests to other services or even computational functions. Can the results be stored in our cache as accessing the cache is most likely to be faster than re-accessing a database or web service.

I usually encourage people to use Sitefinity's own cache implementation to store data and results. But that is all local memory and now we can push this off to our new Azure Redis Cache.

First start with Nuget and installing the StackExchnage.Redis. I then create a static class from which to call it. In the class I have a simple test to see if I am in debug mode and if so then the application uses the ASP.NET Cache class which is local memory. (While developing I don't won't to be making data calls across the globe.).

StackExchange Redis

public static class RedisCacheManager
{
    private static readonly IDatabase cache = Connection.GetDatabase();
    private static readonly System.Web.Caching.Cache localCache = new System.Web.Caching.Cache();
    private static readonly Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
    {
        return ConnectionMultiplexer.Connect(ConfigurationManager.AppSettings["RedisConnectionString"]);
    });
 
    private static ConnectionMultiplexer Connection
    {
        get
        {
            return lazyConnection.Value;
        }
    }
 
    public static Object Get(String key)
    {
        Boolean debug = false;
 
        #if DEBUG
        debug = true;
        #endif
 
        if(debug)
        {
            return localCache.Get(key);
        }
            
        return cache.StringGet(key);
    }
    public static void Set(String key, String data, Int32 durationMinutes)
    {
        Boolean debug = false;
 
        #if DEBUG
        debug = true;
        #endif
 
        if (debug)
        {
            localCache.Insert(key, data, nullDateTime.MaxValue, TimeSpan.FromMinutes(durationMinutes));
            return;
        }
 
        cache.StringSet(key, data, TimeSpan.FromMinutes(durationMinutes));
    }

It is all pretty basic and though there is much more functionality available I am just interested in the basics for now but if I wish too I can expand this class and add more functions.

Output Cache

There is an Nuget package to push any cached pages output in the Redis store as well. This, I think, will make the most impact to the amount of memory consumed by Sitefinity. But due to Sitefinity's cache dependency implementation if you install the package your pages will error indicating this issue.

Overall these are only minor improvements to reduce your sites memory footprint. But it does give you an option.

Note you can also set up and use Redis cache on AWS so the above should also be applicable.


Darrin Robertson - Sitefinity Developer

Thanks for reading and feel free to comment - Darrin Robertson

If I was really helpful and you would buy me a coffee if you could, yay! You can.


Leave a comment
Load more comments

Make a Comment

recapcha code