All software project struggle to cope with the demand as the size and density of the application increases. Database performance is often a key player and it is critical to design the the database with performance in mind.
One way to make the database run faster, is not to use it. Well, to use it only when needed and cache the data, which has not yet changed.
Regardless of the language you use, there are always many caching tools. Runtime.Caching is one of them.
If you are in the .NET world, this may be the quickest way to get started with caching. By default, the cache is stored locally in the memory of the web server.
However, if you have multiple web servers and wish to keep the cache instances consistent across the servers, it gets complicated with Runtime.Caching. Memcached is one of the options to tackle this problem.
“Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.”
Here is a blog about how to install memcached on a 64 bit windows machine. Here is the version of memcached I used.
Once installed and started, memcached can be accessed via telnet on port 11211, if you have installed with the default settings.
telnet localhost 11211
The next part is to access memcached from a C# application. I used EnyimMemcached in this part. Their wiki page is handy.
Briefly, the NuGet package needs being installed, the rest is straight forward and the code is self-explanatory.
One thing to keep in mind, is that Enyim serializes the objects before storing them in memcached, so make sure the classes that you cache have the [Serializable()] and [DataContract()] attributes.
By default EnyimMemcached does not trigger exception, if it can not store an item to the cache. This makes debugging a little bit difficult, especially if you are not sure which one of the 100 classes is not serializable. Hence, the logging features are your friend during development. If I get enough time, I will explain the logging part as well.
It turned out that Memcached gets unresponsive after a big number of active clusterclients; a few hundred or thousands, depending on your infrastructure. Hence, in this project, I tried to preserve and re-use the clusterclient.
When more caching space is needed, more memcached clusters can be added. It is not difficult to manage several memcached clusters in multiple servers. Yet, Amazon has made it even easier with Amazon ElastiCache. It is basically, memcached on the cloud. Amazon’s getting started page is very useful, if you are not familiar with ElastiCache.
It does not take much to switch a memcached application to ElastiCache, just changing the endpoint is enough. Beware that ElastiCache can be accessed only from within the Amazon Web Services! In my case the application is hosted on an AWS EC2.
Later, I found it difficult to track all the log messages in a text file. Logentries is good fit for this situation, its web interface makes it easy to find the exact log message, when you need it.
I used Logentries as a new Nlog target. Logentries has an easy to follow document about how to do this. Again, it is about installing the NuGet package and some configuration.
In conclusion, this C# project stores cache items either in local memory with Runtime.Caching, a memcached server or a ElastiCahe endpoint. The diagnostic data can be logged into a text file or Logentries.
I added some MSUnit tests and also a few methods to push the cache servers a little bit and check how they perform under pressure. Guess who is the winner!
If you still feel like you want to see the code, download or clone it on Github.