Grails In-Memory Cache using Google’s Guava Library

Post by Matt Nohr

In a Grails application, there are a couple of cases where you may want to consider storing data in a in-memory cache.  For example:

  • If it is expensive to read/create the data (reading across the network)
  • If the data will be used more than once
  • If multiple users need to access the data so you need to store it outside of a single user session

Here I will give you one example of how to use an in-memory cache. This can greatly improve performance but there are a couple of things you must keep in mind.

Scoped Services

One approach for storing the data is in an instance variable in a service. By default, Grails services are singletons, so only one instance of the service ever exists. Because of this, you could do something like this:

class MyService {
    private def cache

    public MyService() {
        //initialize the cache
    }

    public getValue(String key){
        //load value if it is not in cache
        //return value from cache
    }
}

Every request from a controller that accesses the service will be accessing the same instance, and therefore will be accessing the same “cache” variable.

Cache Considerations

This can be pretty powerful, and can help performance considerably, but there are some considerations you must think about.

  1. Concurrency – Since all requests are going to be accessing the same instance, you must ensure that the “cache” variable is accessed in a thread-safe way or correctly handles concurrency
  2. Memory Size – Since there will only ever be one instance, there should be a mechanism for removing old entries from the cache and/or limiting the size of the cache.

Google’s Guava Cache Library

A very good way to handle this is to use Google’s Guava cache library. Some of the key benefits are:

  • It has built in concurrency handling
  • You can expire contents of the cache automatically
  • You can limit the size of the cache
  • You can just call “get” on the cache and it will either return the object from the cache or load it if needed

To include the Guava libraries in your Grails project, you need to update your BuildConfig.groovy and add this line:

grails.project.dependency.resolution = {
    dependencies {
        compile "com.google.guava:guava:12.0"
    }
}

Then to setup your cache in your service you can do this:

public MyService() {
    //initialize the cache
    cache = CacheBuilder.newBuilder().
	expireAfterWrite(60, TimeUnit.MINUTES).
	maximumSize(500).
	build(new CacheLoader() {
		public MyExpensiveObject load(String key) {
		    return doExpensiveLoadOperation()
		}
        })
}

This cache (a LoadingCache object) will have a maximum of 500 entries and each entry will expire after 60 minutes. If the value is not already in the cache, the “load()” method will be called and the result (a MyExpensiveObject in this case) will be returned. There are other configurations to expire cache entries well explained in the documentation.

To use the cache then you would just do this:

def getValue(String key){
    return cache.get(key)
}

You do not need to check if the object is in the cache because if it is not it will automatically be loaded.

Conclusion

Using an instance variable on a singleton service can serve as an in-memory cache, and by using the Guava libraries you can overcome the most complicated issues surrounding caching.

References

This entry was posted in Software Development and tagged , , , . Bookmark the permalink.

Related Posts:

One Response to Grails In-Memory Cache using Google’s Guava Library

  1. Crazy4Groovy says:

    I liked this — thanks for the tip!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>