我正在使用Memcached(使用spymemcached作为客户端)来缓存从远程服务器收到的响应。我的程序的逻辑很简单:
- 如果请求的资源缓存在Memcached中,则立即返回缓存;
- 如果没有,则连接到远程服务器,缓存它,然后返回结果。
该程序类似于,
Object cachedResource = spyMemcachedClient.get(RESOURCE_KEY);
if (cachedResource != null) {
return cachedResource;
} else {
Object remoteResource = getTheResourceFromTheRemoteServer();
spyMemcachedClient.set(RESOURCE_KEY, EXP_TIME, remoteResource);
return remoteResource;
}
但是我注意到,由于同时会有很多并发请求,因此有可能两个线程都找到 cachedResource
是 null
,所以它们都调用 getTheResourceFromTheRemoteServer
,我不想这样做。
那么,我该如何避免这种情况呢?是否有像 ConcurrentMap.putIfAbsent
这样的原子操作在spymemcached中。 (顺便说一句,程序将部署在多个实例上,这意味着不可能使用像Lock这样的Java并发工具来实现这一点。)
最佳答案
memcached 中有一个 add
命令可以执行您想要的操作 ( list of commands )。为了避免调用两次或多次 getTheResourceFromTheRemoteServer
,您应该使用 memcached 模拟写锁(add
和 delete
命令的组合)。因此,只有在同一特定键 (RESOURCE_KEY_LOCK) 上成功调用 add
的线程才应调用 getTheResourceFromTheRemoteServer
并将其放入缓存中。其他线程应该等待并再次调用 get(RESOURCE_KEY)
关于java - 如何使用spymemcached实现原子操作 "setIfAbsent",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23191364/