Alachisoft.com
Boost NHibernate Performance & Scalability

Boost NHibernate Performance & Scalability

NCache provides extremely fast and highly scalable level-2 distributed cache for NHibernate. NCache is a distributed in-memory object cache for .NET and lets you improve NHibernate performance and scalability. As a software appliance, plug NCache into your existing .NET apps using NHibernate without any code change.

Distributed In-Memory Cache for NHibernate

Distributed cache, the core engine of NCache, is extremely fast and scalable. Cache both static and transactional application data and reduce expensive database trips. NCache synchronizes cache updates across multiple servers.

  • Scale up with Mirrored, Replicated, Partitioned, and Client Cache topologies
  • Software appliance for NHibernate (no code change required)
  • Database synchronization of cache thru SqlDependency

Drawbacks of Regular NHibernate Cache

NHibernate provides an in-process cache out of box. Following are some of its drawbacks:

  1. Cannot handle ASP.NET worker process recycling: Worker process recycling destroys and recreates the entire cache which has a negative performance impact on your app.
  2. Cannot handle ASP.NET web gardens: ASP.NET app runs in multiple worker processes in a web garden configuration. This creates multiple in-process copies of the cache that are not synchronized with each other and lead to data integrity errors.
  3. Cannot handle ASP.NET web farms: ASP.NET apps frequently run in web farms for scalability reasons. A stand-alone cache is unaware of multiple servers and cache instances and is not synchronized. This leads to data integrity problems.
  4. Cannot handle application scalability: If your application (ASP.NET, .NET web service, distributed app, grid computing app, or an N-tier app) needs to scale up and run on multiple servers, your cache must be distributed. Otherwise, it would lead to data integrity problems.
  5. Cannot handle large cache size: In-process cache means it cannot grow more than what your app process can handle. A distributed cache on the other hand can grow in size through distribution.

Benefits of NCache as Second Level Distributed Cache for NHibernate

NCache is a distributed cache that lets you improve your application performance and also scales up very nicely when your application needs to scale up. Below are some of the benefits of using clustered sessions:

  1. Handles ASP.NET worker processes well: NCache can be used out-of-process. This means multiple ASP.NET worker processes can share a common out-of-process cache. This also addresses worker process recycling problem because the cache is not affected by it.
  2. Handles ASP.NET web farms: NCache creates a clustered cache that can live on multiple servers. This allows your ASP.NET apps and .NET web services to run in web farm configuration without worrying about cache synchronization issues.
  3. Highly scalable: You have a rich set of clustering topologies (replicated, partitioned, and client nodes) that allow you to scale up to 100's of web servers in your farm without compromising on performance.
  4. No single point of failure (high availability): Clustering the cache allows you to eliminate all single points of failures from your environment. This makes your application highly available.
  5. 100% Native .NET: NCache is a 100% native .NET product. This means that you can expect us to stay on top of all additions and changes to .NET as compared to a non-.NET solution.

How Does It Work?

Using NCache as a second level distributed cache for NHibernate is very simple. It requires no code change in your application and you only modify your NHibernate configuration file to start using NCache. NCache implements two interfaces NHibernate.Cache.ICacheProvider and NHibernate.Cache.ICache that lets NHibernate call NCache for all its caching needs.

NCache as a second level distributed cache for NHibernate

Incorporating NCache into your .NET application using NHibernate is a simple three-step process as described below.

  1. Install NCache on each server where your application is running
  2. Define a clustered cache: Use NCache Manager (a graphical tool) to define a clustered cache that is appropriate for you. You should select replicated cache, partitioned cache, or partition-replica cache. And, you can also specify whether the cache should reside on the same server as your application or whether you should have a separate caching tier (again a cluster of multiple cache servers) where all the cache is kept. For larger configurations, a separate caching tier is more appropriate.
  3. Modify app.config or web.config file to add NCache provider information and the name of the cache you've just created. NCache provides a sample project called nhibernate along with NCache installation that demonstrates how to use NCache with NHibernate. Here is a sample app.config or web.config:
    
    <nhibernate>
       <!-- ...  -->
       <add key="hibernate.cache.provider_class"
            value=
    		"Alachisoft.NCache.Integrations.NHibernate.Cache.NCacheProvider,
             Alachisoft.NCache.Integrations.NHibernate.Cache"/>
    </nhibernate>
    <ncache>
       <add key="cacheName" value="myCache"/>
       <add key="useAsync" value="false"/>
       <add key="enableCacheException" value="false"/>
    
       <!--"sqlDependency" means .NET event based synchronization with-->
       <!--SQL 2005. "dbDependency" means polling based synchronization-->
       <!--with OLEDB database. "dbDependency" does not require-->
       <!--"sqlDependency" "sql" values below-->
       <dbSync type="sqlDependency"/>
    
       <class name="nhibernator.BLL.Customer">
          <cacheKey format="Customer:CustomerID:[pk]"/>
     
       <!-- priority value is 1-6 only-->
       <add key="priority" value="1"/>
    
       <!--relativeExpiration value is in seconds-->
       <add key="relativeExpiration" value="1000"/>
    
       <sqlDependency
         sql="select ContactName from Customers where CustomerID = ?"/>
    </class>
    
    <class name="nhibernator.BLL.Employee">
       <cacheKeyformat="Employee:EmployeeID:[pk]"/>
    
       <!-- priority value is 1-6 only -->
       <add key="priority" value="3"/>
    
       <!-- staticExpiration value is in datetime string with hh:mm:ss -->
       <add key="staticExpiration" value="10-12-2007 00:00:00"/>
    
       <sqlDependency
         sql="select EmployeeID from Employees where EmployeeID = ?"/>
       </class>
    </ncache>
    
    

Once you do this, you're .NET application is ready to start using a distributed cache. The above example of app.config or web.config contains the following options for you to configure. Each of them is explained below as well.

  • hibernate.cache.provider_class: This option lets you specify that NCache is your second level cache provider. You need to mention the two classes that implement NHibernate.Cache.ICacheProvider and NHibernate.Cache.ICache interfaces respectively. This is how NHibernate knows how to call this second level cache.
  • cacheName: This option is included inside the <ncache> tag and lets you specify name of the cache that you have configured through NCache Manager. All caches in NCache are named and this name allows NCache provider to connect to the right cache.
  • useAsync: This is a flag that tells the provider whether to use the standard synchronized "Add" and "Insert" or the asynchronous "AddAsync" and "InsertAsync" operations. The asynchronous operations immediately return control back to the client and queues up the operation in a background queue. Then, a background thread executes the command.
  • enableCacheException: This flag allows you to turn on exception handling which by default is turned off. This will throw an exception which you'll have to catch in your .NET application.
  • dbSync: The value for this is either "sqlDependency" or "dbDependency". SqlDependency is a mechanism for synchronizing your cache with SQL Server 2005 database through .NET events. DbDependency allows you to synchronize your cache with any OLEDB compliant database through a configurable polling interval. If you specify "sqlDependency" value, then you must also specify the "<sqlDependency sql=..." tag below.
  • class: This lets you specify options specific to a .NET class. All the options below are class-specific.
    • cacheKey: You can specify the cache-key format here. The example above shows "Employee:EmployeeID:[pk]" which would translate into "Employee:EmployeeID:1000" if the EmployeeID value of the object were 1000.
    • priority: The priority you want to use for items cached. The possible values are from 1 to 6.
    • relativeExpiration: This value is specified as number of seconds. It indicates the idle-time expiration for your items, meaning how long your item can stay without being accessed.
    • staticExpiration: This value is in date-time and indicates an absolute time when an item should be expired.
    • sqlDependency: You specify a "select" SQL statement to identify a row in SQL Server 2005 database that corresponds to this cached item. Then, whenever that row is updated or removed, this cached item is also removed. This is a way to synchronize your cache with SQL Server 2005 database. Synchronization is done through .NET events.