Daniel Ansari’s blog Random software musings

February 12, 2010

NHibernate caching solution for web farms

Filed under: NHibernate,Open Source — Tags: , , , — admin @ 11:08 am

If your application uses NHibernate in a web farm, there is already a second-level cache provider that you ought to be familiar with: NHibernate.Caches.SysCache2, which supports expiration based on SQL table or command-based dependencies.  Whilst this is a decent solution, it does cause your whole cache region to be invalidated when data changes in the table.

It may be more ideal for you to invalidate the cache on a per-object basis, i.e., if one web server in the farm receives a request that causes a cached object to change, the portion of the application running on that server should be able to expire that object from the cache of all other servers within that farm.

A technique that I have used somewhat successfully is a shared disk cache invalidation mechanism called FileSysCache, similar to the “File Update Model” discussed in this MSDN library article.  Unlike the technique in that article, however, ours does not suffer from the issues arising from SQL Server trying to access the file system.  Our method creates a zero-length file on the shared disk, together with a CacheDependency to that file, for each cacheable object.  It deletes that file when the cache is invalidated for that object.  Thus, any other servers holding a cached copy of that object will have a CacheDependency on the same file, and their cached copies will expire.

This happens behind the scenes for you as an application developer.  NHibernate will call the relevant methods in the caching provider; all you need to know is that to expire the object across the web farm, you just need to evict it from the second level cache, using:

session.Evict(obj)

To configure FileSysCache, put the following into your web.config:

  <configSections>
...
    <section name="filesyscache" type="NHibernate.Caches.FileSysCache.FileSysCacheSectionHandler, NHibernate.Caches.FileSysCache" />

and also:

  <filesyscache path="C:\Projects\NHibernate.Caches.FileSysCache.Tests\bin\Debug\Cache">
    <cache region="foo" expiration="500" priority="4" />
  </filesyscache>

I meant to make this post a few years ago, so I hope the information here is still relevant, and I hope it’s better late than never.

The code, including unit tests, may be found here.

Powered by WordPress