Pages

Monday, March 7, 2011

Caching isn't perfect !

Caching  in applications is a two sided sword. If it is not used properly it can have unintended side effects.
In my current project, we were using Ehcache as a cache manager in Hibernate.Since the database interactions are very minimum, we were not concentrating on how good or effective the caching was.At the time of UAT, team noticed that the application caching strategy was not effective. So we started looking in to it.As one would think, we have certain values which will never change and there are few which can change frequently. Since application was defining the same strategy for all the entities it was not effective,which is understandable.

Now  JEE application space is too crowded ,there are many plugable components which can be used or coded in many different ways.As the number of components increase this permutation and combination increases exponentially.In other words  now a days there is no universal solution, and thus solution depends on  the components used , version, application server it is running etc etc.

Background:
We uses Hibernate as an O/R mapping layer along with the Spring framework .The hibernate components are deployed as a .har file in Jboss application server.To access the hibernate sessions from the application layer app uses org.springframework.orm.hibernate3.HibernateTemplate,which is a convenient class provided by spring and Ehcache as a Hibernate cache provider.

Even though the above said configurations are set according to the  Ehcache/Hibernate configurations:( http://ehcache.org/documentation/hibernate.html), the application was not caching any of the entities defined in the ehcache.xml.



ehcache.xml
        <cache name="com.sample.data.Person"
           maxElementsInMemory="10"
           eternal="false"
           overflowToDisk="true"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU" />
Person.hbm.xml
……..
<cache usage="read-write" />
……..
……..


When , hibernate show sql option was turned on , it was clear that app goes to DB every single time it executes the query.

Then ,after doing a little bit research, I enabled the secondary caching and query caching on hibernate. Since app was using har file , these changes should be done on jboss-service.xml.

jboss-service.xml
    <attribute name="QueryCacheEnabled">true</attribute>
    <attribute name="SecondLevelCacheEnabled">true</attribute>
I was very much confident that the caching will work fine now, but it turned out to be a false confidence.
Now what? all the combination of property values are testing and finally started following the call path using server side debugging.

Finally , I arrived at the Eureka moment !
it  seems like the HibernateDaoSupport class is not getting some of the properties set through the config files. The testing results shows that we need to manually set the setCacheQueries to true in theHibernate Template(getHibernateTemplate().setCacheQueries(true))

Now  from the logs it is very clear that when app is hitting the cache and when it is going to the DB.

2011-01-17 12:32:23,752 DEBUG [net.sf.ehcache.Cache] org.hibernate.cache.UpdateTimestampsCache cache - Miss
2011-01-17 12:32:23,752 DEBUG [net.sf.ehcache.hibernate.EhCache] Element for key PERSON is null
2011-01-17 12:32:23,752 DEBUG [org.hibernate.cache.StandardQueryCache] returning cached query results

Few Important things to watch:

1) It is very important to understand the defaultCache element in the ehcache.xml.
 If a separate cache  entity is not defined in the ehcache.xml , ehcache will use defaultCache settings.

              <defaultCache maxElementsInMemory="1000"
                  eternal="false"
                  timeToIdleSeconds="30"
                  timeToLiveSeconds="30"
                  overflowToDisk="true"
                  diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="120" />

2) Another thing is be judicious about the element  "eternal". If the value is set to "true" then the cache will never expire.

Finally , I should acknowledge the following references helped me a lot to arrive at a working solution.Thanks to all sharing the knowledge
 
http://docs.jboss.org/jbossas/javadoc/4.0.5/hibernate-int/org/jboss/hibernate/jmx/Hibernate.html 


 

1 comment:

Related Posts Plugin for WordPress, Blogger...