xmemcached cas原子操作,当key不存在时,会抛Null GetsResponse问题解决方案

当调用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 详细描述文章地址:   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();
}


猜你喜欢

转载自yangzdpssoft.iteye.com/blog/1936035