EHC ❯ Support for coherent and incoherent cache views on same jvm
-
New Feature
-
Status: Closed
-
0 Showstopper
-
Resolution: Fixed
-
-
-
hsingh
-
Reporter: ssubbiah
-
March 04, 2010
-
0
-
Watchers: 0
-
January 17, 2013
-
May 03, 2010
Description
This is a requirement that stems from one of our customer usecase.
In high volume usecases, looks like different users of the cache want different guarantees and have different performance requirements and they are coexist within the same VM. Recently we were talking to one of our customer who want to get insane read tps, but most of that comes from web ui which can display stale data but there is also some read/writes that need to work on a coherent view of the cache. The first suggestion that we gave was to separate their load by their coherent/incoherent requirement and send them to different nodes but this is impractical in many cases. So we have to come up with a way where we can get to access the same cache in both coherent and incoherent mode from the same node.
Some of the ideas are :
1)
Cache coherentCache = cacheManager.get(“foo”); coherentCache.setCoherent(true);
Cache incoherentCache = cacheManager.get(“foo”); incoherentCache.setCoherent(false);
These two represent two different views of the same cache, then these references can be passed on to different consumers in the system. In the current system it will not work since it is the same object.
2) We could add a new method in cacheManager to create “views” of the cache and then users can make calls on it.
3) Or we could make use of decorated caches to have multiple views.
Other ideas welcome.
Comments
Saravanan Subbiah 2010-03-08
Saravanan Subbiah 2010-03-09
One thing to keep in mind is that every “view” into the cache needs to be accounted for, for methods like waitUntilCoherent() to work correct. For example, if a node creates two views to the same cache and then sets one as incoherent, then loses the reference to the view, we still have to able return correct values for isClusterCoherent() or waitUntilCoherent() methods.
To me seems like promoting these “views” to same as cache life-cycles will make life easier. i.e. Views are just caches registered under different name. They could have different settings like coherent/incoherent or stats enabled/disabled or have different registered listeners etc.
So if one want to create a view and register it, one would do something like this.
Cache incoherentView = cacheManager.createView(“cacheName”, “viewName”); incoherentView.setCoherent(false); // remember coherence is a local attribute
Then if one wants to get a view, all they have to do is
Cache incoherentView = cacheManager.getCache(“viewName”);
Views can be disposed off just like a cache. It has same life cycle.
In Terracotta implementation, we use the same ClusteredBackend across all views and the cache.
Saravanan Subbiah 2010-03-19
In the last meeting this is what we agreed to.
EHCache cacheView = cacheManager.createView(“cacheName”, “viewName”);
This will create a cache view for the cache and register the view with the cache manager with viewName. Note that the return type is the Ehcache (but we could choose to return Cache which implements Ehcache)
Also we need to implement the following method.
Set
gluck 2010-03-30
Summary of a View So a “view” is an Ehcache with a cloned configuration but a common store. It can only be created through a CacheManager method using an existing cache name. The view is initialized just like a Cache is. A view is Terracotta only.
It is really a Store view, not a Cache View which sort of makes it awkward to thing about and visualise.
Consequences and Surprises Anything that can be registered in a CacheConfiguration gets spun up but as separate instances.
So if you have a CacheExtension, it gets spun up. Given that these are often used for timers you would end up with two, not one, operating on the same piece of underlying data (the shared store)
New listeners get created. But only get fired for their cache or view, which ever has the event. In a database, an updatable view which has a data change made to it will cause triggers to be fired. Ours does not work this way.
Replication in addition to Terracotta gets spun up but won’t work because the other nodes would not have a cache of the view name, so these would not work.
In summary, I think the idea is too counter intuitive to be simple. It has surprises for the unwary. And it is very unEhcachey.
Proposal I think decorated cache are much easier to think about. With a decorated cache, you can either interact with the cache or its decorator. Both ways the data ends up in the store and there is only one set of listeners, extensions and all the rest that hangs of a cache. Decorators are also a know language pattern.
Right now in CacheManager we have:
public void replaceCacheWithDecoratedCache(Ehcache ehcache, Ehcache decoratedCache)
But we need to add a decorated cache with its own unique name so it can be separately referenced. So let’s add a new method:
public void addDecoratedCache(Ehcache ehcache, Ehcache, decoratedCache)
Things then become very simple. We add this incoherent functionality into the TerracottaAwareCache, another decorated cache we are creating for disconnected mode. See http://ehcache.org/documentation/terracotta_aware_cache.html. We just add a new property coherent=”true | false” to TerracottaAwareCache. |
Saravanan Subbiah 2010-03-31
Greg,
All the points listed in your comments seem to be implementation detail that can be easily fixed. None of them seem like inherent design flaw that requires us to move to DecoratedCaches.
From what I understand we can fix
1) Views to share same cacheExtensions with underlying cache 2) Views to have same listeners as underlying cache (seems like having different listeners is greater flexibility but we can always do that depending on user input later) 3) Not sure what you are saying about Replication. Views are replicated and changes are visible across nodes.
cheers, Saravanan
Abhishek Singh 2010-05-03
implemented in unlockedreadsview module.
Himadri Singh 2010-05-11
h4. Test Case: Unlocked Read View Performance test Using cachetest _(terracotta clustered)_, two nodes doing read/write operations on coherent cache, with one node viewing cache using UnlockedReadView
h5. Setup {quote} perf08-09: do r/w operations on coherent cache perf07: unlocked read view
ehcache.inMemoryCount: 0 ehcache.coherent: true ehcache.valueMode: serialization size: 300000 payload.size: 1024 K {quote}
h5. Case 1: w/ unlocked read view
node | throughput | |||
perf07 | 574,060 | |||
perf08 | 21,734 | |||
perf09 | 22,404 |
_Results Zip: /shares/perf/perfFrameworksApps/dataForDB/cachetest-results-perfTests-perf-2010-05-10-22.20.05.zip_
h5. Case 2: w/o unlocked read view (2-nodes)
node | throughput | |||
perf08 | 23,653 | |||
perf09 | 23,717 |
_Results Zip: /shares/perf/perfFrameworksApps/dataForDB/cachetest-results-perfTests-perf-2010-05-10-22.44.05.zip_
Comment from Greg :
1) This is a bit weired becase the get should be pointing to the same reference, so setting it looks like it is doing it to the same one.
2) This might work.
What about CacheManager.getCache(“name”, mode);
3) Yep this could work but the usual idiom is to create a decorated cache and then add it back to the CacheManager with the same name.