I'm using Memcached (using spymemcached as client) to cache response received from a remote server. The logic of my program is simple:
The program is something like,
Object cachedResource = spyMemcachedClient.get(RESOURCE_KEY);
if (cachedResource != null) {
return cachedResource;
} else {
Object remoteResource = getTheResourceFromTheRemoteServer();
spyMemcachedClient.set(RESOURCE_KEY, EXP_TIME, remoteResource);
return remoteResource;
}
But I notice that since there will be many concurrent requests at the same time, it is possible that two threads both find cachedResource
is null
, so they both invoke getTheResourceFromTheRemoteServer
, which I don't want to.
So, how can I avoid this. Is there any atomic operation like ConcurrentMap.putIfAbsent
in spymemcached. (By the way, the program will be deployed on multiple instances, which means that it is not possible to use Java concurrent utils like Lock to achieve that.)
There is add
command in memcached that does what you want (list of commands). To avoid calling twice or more getTheResourceFromTheRemoteServer
you should emulate write locks using memcached (combination of add
and delete
commands). So only a thread that successfully invokes add
on same particular key (RESOURCE_KEY_LOCK) should call getTheResourceFromTheRemoteServer
and put it into cache. Other threads should wait and call again get(RESOURCE_KEY)