{"id":71,"date":"2010-02-12T11:08:24","date_gmt":"2010-02-12T16:08:24","guid":{"rendered":"http:\/\/www.danielansari.com\/wordpress\/?p=71"},"modified":"2010-04-01T07:47:46","modified_gmt":"2010-04-01T12:47:46","slug":"nhibernate-caching-solution-for-web-farms","status":"publish","type":"post","link":"http:\/\/www.danielansari.com\/wordpress\/2010\/02\/nhibernate-caching-solution-for-web-farms\/","title":{"rendered":"NHibernate caching solution for web farms"},"content":{"rendered":"<p>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.\u00a0 Whilst this is a decent solution, it does cause your whole cache region to be invalidated when data changes in the table.<\/p>\n<p>It may be more ideal for you to invalidate the cache on a <em>per-object<\/em> basis, <em>i.e.<\/em>, 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.<\/p>\n<p>A technique that I have used somewhat successfully is a shared disk cache invalidation mechanism called <em>FileSysCache<\/em>, similar to the &#8220;File Update Model&#8221; discussed in this <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms972417.aspx\">MSDN library article<\/a>.\u00a0 Unlike the technique in that article, however, ours does not suffer from the issues arising from SQL Server trying to access the file system.\u00a0 Our method creates a zero-length file on the shared disk, together with a CacheDependency to that file, for each cacheable object.\u00a0 It deletes that file when the cache is invalidated for that object.\u00a0 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.<\/p>\n<p>This happens behind the scenes for you as an application developer.\u00a0 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:<\/p>\n<pre>session.Evict(obj)<\/pre>\n<p>To configure FileSysCache, put the following into your web.config:<\/p>\n<pre>\u00a0 &lt;configSections&gt;\r\n...\r\n\u00a0\u00a0\u00a0 &lt;section name=\"filesyscache\" type=\"NHibernate.Caches.FileSysCache.FileSysCacheSectionHandler, NHibernate.Caches.FileSysCache\" \/&gt;<\/pre>\n<p>and also:<\/p>\n<pre>  &lt;filesyscache path=\"C:\\Projects\\NHibernate.Caches.FileSysCache.Tests\\bin\\Debug\\Cache\"&gt;\r\n    &lt;cache region=\"foo\" expiration=\"500\" priority=\"4\" \/&gt;\r\n  &lt;\/filesyscache&gt;<\/pre>\n<p>I meant to make this post a few years ago, so I hope the information here is still relevant, and I hope it&#8217;s better late than never.<\/p>\n<p>The code, including unit tests, may be found <a href=\"\/wordpress\/code\/NHibernate.Caches.FileSysCache.zip\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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.\u00a0 Whilst this is a decent solution, it does cause your whole cache region to be invalidated when data changes in the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[18,6],"tags":[20,27,19,21],"_links":{"self":[{"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/posts\/71"}],"collection":[{"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/comments?post=71"}],"version-history":[{"count":5,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/posts\/71\/revisions"}],"predecessor-version":[{"id":76,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/posts\/71\/revisions\/76"}],"wp:attachment":[{"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/media?parent=71"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/categories?post=71"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.danielansari.com\/wordpress\/wp-json\/wp\/v2\/tags?post=71"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}