cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrus Adamchik <and...@objectstyle.org>
Subject Re: Configuring the Cache in a multi-node environment. (cayenne 3.0)
Date Sun, 13 Dec 2015 10:43:14 GMT
Hi Eric,

I just posted an answer on StackOverflow: http://stackoverflow.com/questions/34244260/cayenne-cache-does-query-cache-replace-object-cache/34250211#34250211

Copying it here as I think it may be useful to other list members. Feel free to follow up
either here on on SO.

Andrus

---- 

Object cache and query cache are independent from each other, though they can affect each
other's state.

**Object Cache**

Object cache is accessed when expanding object graph (as you correctly noticed). But **synchronization**
of object cache does not just update the cache, but is also propagated to ObjectContexts,
causing a refresh of the in-memory object graph. While this sounds awesome and super-automatic,
from experience it is most useful in desktop apps, when you have a limited graph of objects
relevant for a single user. In clustered multi-user web applications syncing object cache
is more of a nuisance then help. It creates lots of network traffic, forces your instances
to consume CPU to process events they don't really care about, and finally, updates your objects
from underneath when you least expect it. So I usually turn off object cache syncing, and
rely purely on clustered query cache to handle synchronization.

**Query Cache**

Here is [an example project][1] demonstrating query cache with clustering. It uses Cayenne
4.0, EHCache as a cache provider, and ActiveMQ/JMS for cross-instance events.

The way query cache works, it caches lists of objects that matched a given query, including
prefetched related objects if the query contained prefetches. To take full advantage of query
cache, you may have to change your coding style a bit. Instead of storing long-lived references
to query result lists in your instance variables (essentially doing your own caching), you
create and run a query (with proper cache settings) any time you need such list, and let Cayenne
decide whether the list should be returned from cache or fetched fresh from DB. 

The next step is to configure your cache in a way depending on what provider you are using
to specify its default expiration policies (per cache group). E.g. a [sample EHCache config][2].

Finally you can add clustering and event-driven cache refreshing, which can be done either
explicitly via API calls, or implicitly on commit of certain entities (only available since
Cayenne 3.1).

Query cache refreshing is very cheap. The only thing sent across the network is the name of
the "cache group", and on the receiving end a bunch of lists are lazily invalidated at once.
It also results in cleaner code. 

**Version of Cayenne**

I strongly recommend upgrading to at least Cayenne 3.1 (or even to 4.0.M2). Among other nice
things there, the caching mechanism is more mature than 3.0. It will make your experience
configuring Cayenne and integrating external cache providers so much easier.


  [1]: https://github.com/andrus/wowodc13
  [2]: https://github.com/andrus/wowodc13/blob/master/services/src/main/resources/ehcache.xml
  


> On Dec 11, 2015, at 9:51 PM, Eric Cobb <ecobb@levelsbeyond.com> wrote:
> 
> Hello All!
> 
> I am looking for resources on how to best configure cayenne when running in
> a cluster, or multiple JVMs using the same domain. I've been reading the
> documentation and I see this:
> 
> "there are ways to notify other stacks about the object changes. This can
> be set up in the Modeler. However full synchronization of every change
> often results in excessive network traffic and CPU consumption, and is
> usually avoided in favor of the query cache approach described elsewhere
> <https://cayenne.apache.org/docs/3.0/query-result-caching.html> in this
> chapter."
> 
> That links to the Query-Result-Caching page. It is my understanding that
> object caching is used when an associated object is retrieved via a getter
> or when an object is retrieved by its id. Is this quote telling me that if
> I configure query caching, object caching won't be used? Or that I need to
> avoid doing that would hit the object cache in my application code? Should
> I disable the object cache completely (if that's even possible)? If I don't
> set up cayenne to notify other stacks of changes to the object cache, don't
> I run the risk of stale data?
> 
> I appreciate any and all tips on the best way to run cayenne across
> multiple  nodes, or if you have some resources to point me toward, that
> would be very helpful as well.
> 
> Thanks in advance for your time!


Mime
View raw message