Replacing Sitefinity Cache
with Azure Redis

Dec 20

Introduction

Sitefinity uses a In Memory cache. It is an implementation of the Enterprise Library Caching Application Block. This works fine but its a bit slack when in a multi server environment. You are effectively caching the same data on every server and thus, I think, a bit redundant. But you can create your own implementation of the CacheManger using the ICacheManager interface. I have done this and used the Azure Redis Cache, a leader in distributed cache systems.

Sitefinity uses a custom implementation of the Enterprise library Caching Application Block. I have used this in the past and it is really good. But today you will note that the current release 6 of the Enterprise Library that this block does not exist anymore. Overall they decided that there were plenty of other offerings around and this block was not required anymore. The primary offering is the built in ASP.NET cache released with .NET 4.0.

One issue I have with the current Sitefinity cache is the fact that it is InMemory only. And local memory at that. One of the primary reasons for the Sitefinity Load Balancing module is to set up a message queue between all the nodes and send around "Clear cache items" messages to each box. Downside every node has to build the cached item and store it locally so if you have a page that takes 60 seconds to load and 6 servers. 6 people have to suffer a 60 second load time.

Also, you are now storing the same 6 items on the 6 servers. Not ideal in resource management. If you are running multiple Sitefinity instances on your box you have a memory limit and the cache, depending on your site, can take a varying amount of that memory.

Today there are a few Distributed Caches out there and I set about looking to implement one of them. The Azure Redis Cache. I looked at several options this weekend. Tried the implementation and below are the results. I was optimistic but in a nut shell it didn't work. This will really take some effort on the Sitefinity team to look at enabling such an extension.

Setup

I went to the Azure portal and created a new Redis Cache. You can start on the Microsoft documentation. On my project I implemented a Session and Output cache providers. This took all of 10 minutes. Its straight forward so I won't repeat what they have perfectly doco'd there except to say that the password is your primary or secondary management key.

After testing those I looked at implementing my own ICacheManager are registering this over the Sitefinity supplied one. Again not too hard you just create your own implementation of the interface and then register it in the Bootstrapper_Initialized event on start up.

I am not going to show off any code as overall I wouldn't recommend to use any of it but if someone is interested just let me know and I will be happy to pass it own and discuss it a bit further. In the meantime I will push the topic with Sitefinity and support, (Atanas - the helpful - has been assisting), and I have also created a feature request so if you also think that this topic should be escalated then go and vote. (Otherwise you are not allowed to whinge about it!)

Session Cache

Perhaps start with some good news. I implemented the Redis Session State provider and this worked fine. In the past I have always avoided using Session State because I didn't consider it scale-able. Especially if you needed to centralise it on a SQL database. But I wanted to try it out especially because I wanted to save the ViewState there.

If you didn't know you don't have to save your view state in the page. ASP.NET, for some time has offered you the ability to save it in session so you never had to send it across the wire. There is still a ViewState hidden field but it becomes about 30 characters long and thus hardly a latency issue any more. To do this you need to override the PageStatePersister usually best done in a BasePage which inherits from Page.

public class BasePage : Page
{
    protected override PageStatePersister PageStatePersister
    {
        get
        {
            return new SessionPageStatePersister(Page);   
        }
    }
}

With the Redis cache option I a trust the performance and scalability much more and so in those cases where Session or using ViewState just makes life much easier I am much happier to use it.

Just.... How do I implement a BasePage in Sitefinity? I will have to chase Sitefinity on that one. I will update this post if I find the answer.

Output Cache

The next provider is the Output Cache Provider. Again, all of a minute to set up. But this one did not have such a good outcome. I personally thought this was going to be an easy win. Change the output cache to my Redis Cache, save heaps of local memory and negate the need to worry about the Sitefinity Load Balancing module.

But unfortunately Sitefinity uses Cache Dependencies and when using the Redis cache, (A custom provider), you get an error raised stating that custom cache providers only support x, y and z. I am making an assumption that this is the issue. I have seen the cache dependency requirements and I read a post on EpiServer where someone had the same problem.

So using the Output cache option is totally out.

Custom CacheManger

I implemented my own class on ICacheManager it all worked and I was quite excited. But one issue. Items are passed to the Cache Manager as objects but when submitting an object to the Redis cache they need to be of primitive types and any objects need to be turned into a byte array. Easy peesy! Use a BinaryFormater and away you go. The actual code is even supplied in the Microsoft documentation. The big but is that to Serialize any object it must be decorated with the [Serializable()] attribute. I put a little catch to say if anything couldn't be serialized then to not cache it. It all runs! No problems! But nothing is cached because none of the passed through objects could be serialized.

So overall my day has been a bit sunk. In hindsight I was a bit optimistic. I do believe that the ability to use a Distributed Cache and not the InMemory option is an important one, (being an ex infrastructure guy). I also think that Redis is one of the leading options and though Sitefinity may have to adjust some of its caching strategy internally I think it will be worth it in regards to performance and scaleability.

Don't forget, if you agree, (or don't), go and voice your thoughts and the feature request I started.


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

Please type the code above