xmemcached cas原子操作,当key不存在时,会抛Null GetsResponse问题解决方案
当调用xmemcached 客户端?
net.rubyeye.xmemcached.exception.MemcachedException: Null GetsResponseat 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 详细描述文章地址:?https://code.google.com/p/xmemcached/issues/detail?id=137?解决方案,如下:核心代码:
?@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();}