jfrank
jfrank

Reputation: 733

Is it feasible to use Guava Cache as a "helper" for my own persistent cache?

I'm looking to relieve the pressure on a "lookup service" that hits a database each time, by putting a caching layer between the service provider and the service client. I want this caching layer to be persistent and to fit more objects than RAM would allow, so a vanilla Guava Cache won't do. I've looked into things like EhCache and CouchBase but have decided to roll my own for various reasons.

It's pretty easy to write the naive code for this persistent caching layer. However, I know enough about caching to realize that there are a lot of concurrency issues to handle, and I am pretty sure I won't get all of them right the first time. For example there is the "thundering herd" problem, where a cache miss could cause a lot of simultaneous requests to the backing service for the exact same object. It struck me that this is exactly the type of thing that a LoadingCache already handles. Does it seem like a reasonable idea to try to get Guava to do the hard stuff dealing with concurrency, and just plug in my own subclass(es) to do the actual object retrieval and storage? I'm not sure where the exact boundaries would be in terms of what I would subclass or override, but I can figure that out if this isn't just a totally misguided idea. I haven't seen examples of extending / customizing Guava caching, so if there are any examples and or documents to look at, I'd be interested in those.

Upvotes: 2

Views: 694

Answers (1)

jfrank
jfrank

Reputation: 733

What I ended up doing was very simple. I make a normal LoadingCache, and perform some extra operations in the load and reload methods. This gave me the hooks (i.e. the load and reload methods of CacheLoader) to look in my local database for an object, and call the remote service if I don't find it and persist it, without worrying that many threads would be trying to get the same object, due to all the concurrency guards that Guava provides.

I'm sure it's far from how the cache is intended to be used, since I'm actually setting the maximumSize on my cache to 0, so that my load function is always called. (For a variety of reasons I want to serve the objects from persistent storage each time, not from RAM). I haven't tested it thoroughly but it seems to be behaving as I want. The overall effect is a pull-through "object mirror", acting as a self-updating copy of the upstream service.

Upvotes: 2

Related Questions