Spring cache abstraction - distributed environment

caching, ehcache, java, spring, tomcat

Solution

If it's EHCache that you've told Spring to use, then EHCache supports replication across multiple cache instances across different physical servers. I've had some success with the RMI Replicated Caching using multicast discovery. Evicting from one cache will automatically replicate across the other caches - and likewise when adding to a cache.

In terms of the Spring config, you'll need to set up the various config elements and beans:

<cache:annotation-driven />

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="cacheManager" />
</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation"  value="classpath:/ehcache.xml"/>
</bean> 

The rest of the configuration is done in the `ehcache.xml` file. An example replicated cache from `ehcache.xml` may look something like this:

<cache name="example" 
        maxElementsInMemory="1000"
        eternal="false" 
        overflowToDisk="false" 
        timeToIdleSeconds="0"
        timeToLiveSeconds="600">
        <cacheEventListenerFactory 
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
</cache>

And then you'll need to add the replication settings to the `ehcache.xml` which may look like this:

<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.2,
                    multicastGroupPort=4455, timeToLive=1" />

<cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="hostName=localhost, port=40001, socketTimeoutMillis=2000" />

There are other ways to configure replication in EHCache as described in the documentation but the RMI method described above is relatively simple and has worked well for me.

Problem

I would like to use the spring cache abstraction in my distributed web application. My web application runs on 3 different tomcats with a load balancer. Now, My problem is how exactly can I @Evict cache in all tomcats when another tomcat preforms an update? Does spring supports this kind of thing? Thanks!

Original source