I need to fetch some string resources from Amazon S3 in a concurrent multithreaded environment. I would like to implement caching using Amazon ElastiCache. In essence I would like to implement a method like that:
String getSomething(key) {
String something = elastiCache.get(key);
if (something == null) {
something = s3.get(key);
elastiCache.put(key, something);
}
return something;
}
The problem is that in concurrent environment the code like this is a subject to race conditions. If the key expires in elastiCache, multiple threads will try to fetch it from s3 and put it back to elastiCache. The easiest way to avoid it is to put synchronized on the method. This is not optimal, because all calls to getSomething will be interleaving and that will result in a slowdown for the case when the value is in elastiCache. I found CAS methods on MemcachedClient: gets/asyncGets and as/asyncCAS. Using this methods I can make it so that only the thread that didn't find the key in elastiCache will put it back. But is there a way I could avoid accessing s3 from multiple threads, short of using synchronized?