In this previous post I discussed the case for separating functions typically combined into a single out-of-the-box Sitecore instance into distinct parts, supporting better scalability, performance, availability, etc. I concluded that piece with a reference to using Redis cache for Sitecore caches, instead of the default IIS in-memory cache. Prior to Sitecore 8.2, this wasn’t entirely possible (although one could alter some Sitecore caching aspects through extensive customization of certain Sitecore assemblies). Implementations looking to free up IIS resources, to get more out of their limited Sitecore IIS licenses, might consider swapping the in-memory caches for Redis.
Major caveat: This specific blog post doesn’t analyze the performance implications of doing this; my focus here is to cover how to accomplish the swap of the in-memory cache instead of examining all the nuances of why or why not to do it. That being said, I do expect the use of Redis for Sitecore caches to be a surgical decision made based on the particulars of each project. It’s not a one-size-fits-all solution. There are also questions of which caches to put into Redis, and where Redis should be running (considerations of connectivity, Redis perf, and the whole landscape of Redis can also be brought into this conversation). This will make for future material I cover, probably in conjunction with the big time Redis pros at ObjectRocket (who, conveniently, are part of my family at Rackspace). I hope and expect others in the greater Sitecore community will expand on this topic, too!
Customizing Cache Configuration with Sitecore 8.2 +
Sitecore 8.2 includes a new .config file at App_Config\Include\CacheContainers.config — as the name suggests, this is where one can identify cache containers that will replace the default ones Sitecore uses. For my example, I’m going to specify a custom container for the website[html] cache; any cache can be included here (I refer you to the old reliable /sitecore/admin/cache.aspx
page — the name column enumerates all the Sitecore caches):
With my customization, my CacheContainers.config file looks like this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<cacheContainerConfiguration>
<cacheContainer name="website[html]" type="Rackspace.Sc.Caching.ReferenceRedisCache, Rackspace.Sc.Caching">
<param desc="name">$(0)</param>
<param desc="maxSize">$(1)</param>
<cacheSizeCalculationStrategy type="Sitecore.Caching.DefaultCacheSizeCalculationStrategy, Sitecore.Kernel" />
</cacheContainer>
</cacheContainerConfiguration>
</sitecore>
</configuration>
I’m not going to regurgitate the comments from the default CacheContainers.config file, but it’s certainly worth reviewing.
Once the CacheContainers.config is pointing to the custom class and assembly (in my case type=”Rackspace.Sc.Caching.ReferenceRedisCache, Rackspace.Sc.Caching”) it’s necessary to create the custom assembly to provide the Redis cache behaviour. The foundation for this is to implement the new Sitecore.Caching.ICache interface (which requires Sitecore.Caching.ICacheInfo and Sitecore.Caching.Generics.ICache<string> interfaces. It can look like a lot of work, but it actually isn’t so bad.
One way I found to make it easier was to reference the out-of-the-box Sitecore Sitecore.Caching.MemoryCacheAdapter in the Sitecore.Kernel assembly. One can consider the MemoryCacheAdapter for an example of the implementation of these interfaces:
Reflector, or whatever your preferred decompilation tool of choice, for the win!
In my case, I create a ReferenceRedisCache for this. . .
public class ReferenceRedisCache : Sitecore.Caching.ICache
. . . and the nuts and bolts come down to swapping Redis in place of the System.Runtime.Caching.MemoryCache object from the MemoryCacheAdapter implementation. There are other considerations, of course, but this is the big picture.
I’m not going to post all the code here as mine is still a bit of a work in progress, and I need to evaluate it in terms of performance etc. You’re much safer using the decompiled Sitecore source as a guide, at this point. With this post, I did want to share how one can approach this powerful Sitecore customization; you can selectively change from Sitecore’s in-memory caching to just about any option you’d like this way.
There is another avenue that I’ve not explored with this. Sitecore provides a Sitecore.Caching.BaseCacheConfiguration class that can be overridden to introduce customizations. Sitecore.Caching.DefaultCacheConfiguration is the standard approach you could use as an example; this is an alternative way of substituting your own caching logic, but I haven’t dug into it yet.
I’ll clean up my code, do some profiling and evaluations, and come back with the full details of my custom Rackspace.Sc.Caching.ReferenceRedisCache implementation soon.