November, 2011
The Collections Cache
Monday, November 7th, 2011
This is a very simple pattern that can be used to solve a variety of problems. The structure uses a “Collections Cache”: a cache that appends values to a collection using a Trigger. You can then access the entire collection using a get() or alternatively use an EntryProcessor to extract a certain value from the collection.
The pattern is used on ODC to track aggregate views. Say you want a materialised view of trades grouped by book. We keep a reverse index of trade references for each book. The view is updated asynchronously as data is added to the cache using an async CacheStore. The pattern is applicable to a variety of other use cases, one being an approach to managing version history.
One downside of this pattern is that if the concept is not well known it can be confusing, after all the object you put() is not the same type as is returned from a get(). Simple naming as collections* can help avoid this confusion though.
Singleton Service
Saturday, November 5th, 2011
Being a data grid, Coherence is very good at doing things in a distributed way across all nodes in the cluster. However it doesn’t offer any functionality (currently) for running a service just the once, in a reliable manner. Most applications solve this problem by simply running another process, for example you might start a second process that reads data off some queue and keeps your cluster up to date. It’d be nice however if you could leverage Coherence’s fault tolerance to ensure that, if the cluster was running, your QueueListener was always running too. In fact this is fairly simple to do and can be used for a host of common applications including loading data, keeping it up to date, adding indexes and regulating a cluster wide time stamp (article to follow).
What we want is a service that will always run on one of our Coherence nodes no matter what happens to the cluster.
This solution is conceptually simple. You have lots of processes in your cluster. When each node starts it simply checks whether the service has already been started elsewhere by attempting to lock a fictitious, well-known key:
lockCache.lock(“SingletonLockKey”);
Only one of the processes in the cluster will attain the lock. If it does attain it then it starts the Singleton Service, adds indexes, loads data or whatever. Simple. If the node running the service dies then the lock is released and another process will acquire it and start the singleton service there.
//Run in a new thread on a wrapped DefaultCacheServer i.e. should run on every node int blockUntilLockAquired = -1; lockCache.lock(“SingetonLockKey”); while(true){ boolean locked = lockCache.lock("singletonLockKey", blockUntilLockAquired); if(locked){ //start singletons here wait(); } }
Reliable version of putAll()
Friday, November 4th, 2011
I like triggers in Coherence. They allow us to do lots of cool stuff to our objects as we add them to the cache. Implement versioning, stamp them with cluster time, save them to a messaging system, check for duplicate writes, check for concurrent writes … the list goes on. But with all this processing comes the risk of failure and Coherence provides little in the way of exception reporting. In fact it provides no information on the individual failures, something that quickly becomes a problem as the level of trigger functionality increases. On ODC this caused us a real problem so we re-implemented putAll() so that it correctly reported those writes that failed. Credit goes to Jonathan Knight and Andrew Wilson for working this implementation through.
The pattern is pretty simple at a high level. It involves two Invocables. The first simply executes on the extend proxy, as we need to be inside the cluster to get access to the key assignment strategy. The next step is to split the data being written into the subsets applicable to each node using getKeyOwner(). These subsets are then sent, via a second Invocable, to the members that own them and EntryProcessors are used to do the write to the backing map directly (although this is no longer needed in 3.7). This is shown pictorially below.
You can view the code for doing this in the coherence-bootstrap project on Github: PutAllThatReportsIndividualExceptions.java
[Edit Jan ’12] My colleague Jon ‘The Gridman’ Knight has done a detailed and methodical post drilling into how to implement this pattern in Coherence]
An Overview of some of the best Coherence Patterns
Friday, November 4th, 2011
You can view the PDF version here