What is the best strategy to refactor a Singleton object to a cluster environment?
We use Singleton to cache some custom information from Database. Its mostly read-only but gets refreshed when some particular event occurs.
Now our application needs to be deployed in a Clustered environment. By definition, each JVM will have its own Singleton instance. So the cache may be out-of-sync between the JVM's when a refresh event occurs on a single node and its cache is refreshed.
What is the best way to keep the cache's in sync?
Thanks.
Edit: The cache is mainly used to provide an autocomplete list (performance reasons) to UI and we use Websphere. So any Websphere related tips welcome.
You could use the DistributedMap that is built into WAS.
-Rick
I'm with Mr. Vest Hansen on this one, move as far away from singletons as you possibly can. After being plaguged with the nightmare that is SAAJ and JAXP and getting compatible versions working on JBoss, I'm done with singletons and factories. A SOAP message shouldn't need a factory to instantiate it.
Okay, rant over, what about memcache or something similar? What sort of affinity do you need for your cache? Is it bad if it's EVER out of date, or is there some flexibility in how out of date the data can get?
There are several ways to handle this, depending on 1) how out of data the data is, and 2) does every instance need to have the same values all of the time.
If you just need data that is reasonably up to data, but every JVM doesn't need to have matching data, you can just have every jvm refresh its data on the same schedule (e.g., every 30 seconds).
If the refresh needs to happen at about the same time, you can have one jvm send out a message to the rest of them saying "its time to refresh now"
If every jvm always needs the same information, you need to do a sync, where the master says "refresh now", all of the caches block any new queries, refresh, and tell the master that they are done. When the master gets an answer back from every member of the cluster, it sends another message that says to proceed.
The simplest approaches are:
Add an expiry timer to your singleton cache so that every so often the cache gets purged and subsquent calls fetch the updated data from source (e.g. a database)
Implement a notification mechanism for the cache using something like a JMS topic/tibRV. Get each cache instance to subscribe and react to any change messages broadcast on this topic.
Or something like memcached
http://www.danga.com/memcached/
There are products for having a distributed in memory cache (such as memcache) that can help in this situation.
A better solution, if possible, may be to have the singletons not really be single, but have the application tolerate having separate instances (say that all recognize when they need to be refreshed) but not that they have to be in sync across JVMs, that can turn your cache into a bottleneck.