Jun 18 2009

Using Memcached with NHibernate

Category: zvolkov @ 13:35

Memcached is a data caching system used by such giants as YouTube, Facebook, Digg, Twitter, Wikipedia, SourceForge and others. Since it's free and open source you can use it for many purposes, either directly from C#, or as a SQL-backed distributed ASP.NET session provider, but in this post, I'll focus on how to configure Memcached as a 2nd level cache provider for NHibernate.

If you don't know what 2nd level caching is, read this post on Hibernating Rhinos blog, plus check out related section in NHibernate documentation. You may also want to check this post on Pragmatic Developer's Blog to see how to unit-test that your queries and entities actually use 2nd level cache. Assuming you're beyond that, and have your cache working with SysCache provider, let's move on!

First of all you'll need Memcached provider for NHibernate. If you worked with SysCache provider, you already received all available providers, including Memcached, as a part of NHibernate.Caches package from NHContrib project on SourceForge. And of course, you'll need the Memcached itself. Besides getting it from its native web site where it's only available in its Linux form, you can also get a windows version here (version 1.2.6) or here (version 1.4.4) and configure it like so.

However, a much better option is to get it as a part of MemCacheD Manager, a free app that automates installation and configuration of Memcached on Windows servers. The good part about MemCacheD Manager (MM), you don't need to manually install the Memcached. Instead, MM can remotely connect to a Windows server, install Memcached as a windows service, and configure it to listen on a port! It even works on 64-bit platform, at least on my Windows Server 2008 development machine.

The MM includes same 1.2.6 version of Memcached, but if you choose to get a newer version from here, you can easily upgrade it remotely by copying the new memcached.exe over to MM folder. Then, simply right click on each server and select "Redeploy / Update MemCacheD" and your specified version will be copied to the remote machine, and the Memcached service will be restarted!

Once you have Memcached up and running, it's time to configure NHibernate to use it. I use NHibernate version 2.0.1.GA and NHibernate Caches version 2.0.0.GA, so all the config details below are specific to those versions. As this thread illustrates, different versions of NHibernate Caches may use different configuration settings.

If you worked with SysCache you know that the first thing to do is to specify provider class in your NHibernate config. Depending on how exactly you configure your application (using Spring Framework's NH extensions, using App.Config, or programmatically) the exact syntaxis may vary, but essentially all you need to do is to set property cache.provider_class to NHibernate.Caches.MemCache.MemCacheProvider, NHibernate.Caches.MemCache. This requires that at run-time, your application is able to find the DLLs, and indeed, you'll need to add ICSharpCode.SharpZipLib.dll, Memcached.ClientLibrary.dll and NHibernate.Caches.MemCache.dll to your build script or add them as references to your project (the last option is not recommended as you may want to change the cache provider w/o having to recompile the app). Don't forget to unblock the downloaded DLLs, otherwise Visual Studio will freak out and refuse to load them:

Next step is to add memcache section to your App.Config. That will tell Memcache NH Provider which server/port to connect to. Please note that in the current version this must be done in App.Config, not in Spring config, nor programmatically. Here's what you need to add to your App.Config:

<configuration>
      <configSections>
            <section name="memcache" type="NHibernate.Caches.MemCache.MemCacheSectionHandler, NHibernate.Caches.MemCache"/>
      </configSections>
      <memcache>
            <memcached host="127.0.0.1" port="11211" weight="1" />
            <memcached host="X.Y.Z.Q" port="11211" weight="3" />
      </memcache>
</configuration>

As this post indicates, the optional weight attribute should be set proportionaly to load handling ability of the Memcached server. In the above example server X.Y.Z.Q can handle 3 times more requests than our localhost, so Memcached client will distribute its requests accordingly. If you didn't get it still, Memcached does not replicate data between the instances (unlike its twin brother repcached), nor does it have any keyspace partitioning mechanism (unlike a real DHT) that would decide which item goes to which instance. Both put and get requests are distributed randomly accross all servers, with distribution controlled on each client with the weight parameter. Correction: it turns out Memcached does implement a key partitioning algorithm as explained in this 2004 article; it is responsibility of the client library to ensure that for a given key, the same Memcached node will be consistently picked to handle that key. In the example above, entire space of all possible item keys is split into 4 "buckets" with 3 of them going to X.Y.Z.Q and only 1 to localhost.

If everything is configured correctly, you should be able to hit the cache with your app and see the stats getting updated on MM status tab:

Two important settings that you set in NHibernate properties are "expiration" (in seconds) and "failover" -- a boolean value that tells the client whether to try another server if this one fails to respond (true by default). Finally, if you're crazy enough to share the same cache farm between the applications (e.g. multi-tenant scenarios), remember to set "cache.region_prefix" to a unique value for each application.

One convenient way to troubleshoot your caching, is to use Memcached telnet interface. Simply telnet to the port the Memcached runs on, and use memcached protocol to access stats, get/set cached values etc.

I believe this is enough information to get you started.

Rephrasing the classic, in near future there's gonna be no theater, nor television, just one eternal cache! Enjoy it while you can!

Tags:

Comments

1.
pingback thesavvyguideto.com says:

Pingback from thesavvyguideto.com

MemCached round up | TheBlogGuideTo HPC,Grid, DataGrid, Virtualisation and Cloud Computing

2.
Socratees Socratees says:

That's a very good article man. Thanks for sharing the information.

3.
trackback Yesterday's news says:

Memcached for NHibernate configuration attributes

Memcached for NHibernate configuration attributes

4.
pingback ducdigital.com says:

Pingback from ducdigital.com

Memcached and Asp.net mvc « DucDigital

Add comment


(Will show your Gravatar icon)

biuquote
  • Comment
  • Preview
Loading