当调用xmemcached 客户端
public <T> boolean cas(final String key, final CASOperation<T> operation) throws TimeoutException, InterruptedException, MemcachedException方法时报错:
net.rubyeye.xmemcached.exception.MemcachedException: Null GetsResponse at net.rubyeye.xmemcached.XMemcachedClient.cas0(XMemcachedClient.java:1639) at net.rubyeye.xmemcached.XMemcachedClient.cas(XMemcachedClient.java:1674) at net.rubyeye.xmemcached.XMemcachedClient.cas(XMemcachedClient.java:1767) at aaa.util.OptimisticUpdateModification.execute(OptimisticUpdateModification.java:33) at aa.util.CacheWriter.run(CacheWriter.java:36) at java.lang.Thread.run(Thread.java:619)
BUG 详细描述文章地址:
解决方案,如下:
核心代码:
@Override
public <T> T cas(String key, final AbsCASOpt<T> casOpt) {
try {
GetsResponse<T> response = client.gets(key);
T t = casOpt.initValue();
if (casOpt.isInitNewValue()){
t = casOpt.getNewValue(casOpt.initValue());
}
int max = casOpt.isRedoConflicts() ? AbsCASOpt.MAX_TRIES : 1;
if (response == null){
for (int i = 0; i < max; i++) {
if (client.add(key, casOpt.initExp(), t)){
return t;
}else{
try {
return cas(key, casOpt);
} catch (Exception e) {
}
}
}
}else{
XCASOperation<T> operation = new XCASOperation<T>() {
private T lastValue;
@Override
public int getMaxTries() {
return casOpt.isRedoConflicts() ? AbsCASOpt.MAX_TRIES : 0;
}
@Override
public T getNewValue(long currentCAS, T currentValue) {
lastValue = casOpt.getNewValue(currentValue);
return lastValue;
}
@Override
public T getLastValue(){
return this.lastValue;
}
};
boolean casFlag = client.cas(key, operation);
if (casFlag){
return operation.getLastValue();
}
}
throw new UnCaughtException("Couldn't get a CAS in " + max + " attempts.");
} catch (Exception e) {
throw new UnCaughtException(e);
}
}
辅助类:
package yangz;
/**
* 缓存原子性操作接口.
*
* @author yangz
* @date 2013-9-3 上午9:55
*/
public abstract class AbsCASOpt<T> {
public static final int MAX_TRIES = 8192;
/**
* 初始值.
*
* @return
*/
public abstract T initValue();
/**
* 初始值过期时间, 0为永不过期.
*
* @return
*/
public int initExp(){
return 0;
}
/**
* 初始化后是否设置新值, 即调用getNewValue(initValue());
*
* @return
*/
public boolean isInitNewValue(){
return true;
}
/**
* 并发冲突时,是否重试。如果不重试,并且冲突时则抛异常。
* @return
*/
public boolean isRedoConflicts(){
return true;
}
/**
* 获取新值.
*
* @param current
* @return
*/
public abstract T getNewValue(T current);
}
辅助类:
package yangz;
import net.rubyeye.xmemcached.CASOperation;
/**
* xmemcache 原子性操作.
* @author yangz
* @date 2013-9-3 下午4:50
*/
public interface XCASOperation<T> extends CASOperation<T>{
/**
* 操作成功后的值.
* @return
*/
public T getLastValue();
}