天天看点

jedis的使用

package com.bigdata.project.util.cache.redis.cluster;

import com.bigdata.project.util.json.JsonUtils;
import com.fasterxml.jackson.databind.JavaType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.Hashing;
import redis.clients.util.SafeEncoder;

import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;

public class RedisUtils implements InitializingBean {
    private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);

    //Cluster start
    private JedisCluster jedisCluster;
    private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");
    //Cluster end

    //Sharded start
    private ShardedJedisPool pool;
    private JedisPoolConfig jedisPoolConfig;
    private String uri;
    private String password;
    //Sharded end

    private Boolean isCluster = false;

    public JedisCluster getJedisCluster() {
        return jedisCluster;
    }

    public void setJedisCluster(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }

    public ShardedJedisPool getPool() {
        return pool;
    }

    public void setPool(ShardedJedisPool pool) {
        this.pool = pool;
    }

    public JedisPoolConfig getJedisPoolConfig() {
        return jedisPoolConfig;
    }

    public void setJedisPoolConfig(JedisPoolConfig jedisPoolConfig) {
        this.jedisPoolConfig = jedisPoolConfig;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Boolean getCluster() {
        return isCluster;
    }

    public void setCluster(Boolean cluster) {
        isCluster = cluster;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.debug("uri+++++++" + uri);
        String[] addressArr = uri.split(",");
        if (isCluster) {
            Set<HostAndPort> portHashSet = new HashSet<HostAndPort>();
            for (String str : addressArr) {
                boolean isIpPort = p.matcher(str).matches();
                if (!isIpPort) {
                    throw new IllegalArgumentException("Redis Cluster ip 或 port 不合法[" + str + "]");
                }

                String[] split = str.split(":");
                String ip = split[0];
                String port = split[1];

                HostAndPort hostAndPort = new HostAndPort(ip, Integer.parseInt(port));
                portHashSet.add(hostAndPort);
                log.debug("redis Cluster 服务端 ip:" + ip + "  port:" + port);
            }
            jedisCluster = new JedisCluster(portHashSet, jedisPoolConfig);
        } else {
            List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
            for (String str : addressArr) {
                boolean isIpPort = p.matcher(str).matches();
                if (!isIpPort) {
                    throw new IllegalArgumentException("Redis ip 或 port 不合法[" + str + "]");
                }

                String[] split = str.split(":");
                String ip = split[0];
                String port = split[1];
                JedisShardInfo jedisShardInfo = new JedisShardInfo(ip, Integer.parseInt(port));
                if (StringUtils.isNotBlank(password)) {
                    jedisShardInfo.setPassword(password);
                }
                list.add(jedisShardInfo);
                log.debug("redis Sharded 服务端 ip:" + ip + "  port:" + port);
            }
            pool = new ShardedJedisPool(jedisPoolConfig, list);
            Collection<Jedis> allShards = pool.getResource().getAllShards();
            for (Jedis jedis : allShards) {
                jedis.ping();
                log.debug("redis-pingtest    ip:" + jedis.getClient().getHost() + "  port:" + jedis.getClient().getPort());
            }
        }
    }

    /**
     * 获取 ShardedJedis
     *
     * @return
     */
    public ShardedJedis getResource() {
        return pool.getResource();
    }

    /**
     * 回收 ShardedJedis
     *
     * @param shardedJedis
     */
    public void returnResource(ShardedJedis shardedJedis) {
        if (shardedJedis == null) {
            return;
        }
        try {
            pool.returnResource(shardedJedis);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    /**
     * 销毁 ShardedJedis
     *
     * @param shardedJedis
     */
    public void returnBrokenResource(ShardedJedis shardedJedis) {
        if (shardedJedis == null) {
            return;
        }
        try {
            pool.returnBrokenResource(shardedJedis);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    /**
     * list尾部添加元素
     *
     * @return list长度
     * @see -link- http://redis.cn/commands/rpush.html
     */
    public long rpush(String key, String string) {
        if (isCluster) {
            return jedisCluster.rpush(key, string);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long ret = shardedJedis.rpush(key, string);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public long rpush(String key, Object obj) {
        return rpush(key, JsonUtils.toJson(obj));
    }

    /**
     * list头部添加元素
     *
     * @return list长度
     * @see -link- http://redis.cn/commands/lpush.html
     */
    public long lpush(String key, String string) {
        if (isCluster) {
            return jedisCluster.lpush(key, string);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long ret = shardedJedis.lpush(key, string);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public long lpush(String key, Object obj) {
        return lpush(key, JsonUtils.toJson(obj));
    }

    /**
     * set
     *
     * @return
     * @see -link- http://redis.cn/commands/sadd.html
     */
    public long sadd(String key, String... members) {
        if (isCluster) {
            return jedisCluster.sadd(key, members);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long res = shardedJedis.sadd(key, members);
                return res;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public long sadd(String key, Object... object) {
        String[] arr = new String[object.length];
        for (int i = 0; i < object.length; i++) {
            arr[i] = JsonUtils.toJson(object[i]);
        }
        return sadd(key, arr);
    }

    /**
     * 弹出头部元素
     *
     * @return string 头部元素
     * @see -link- http://redis.cn/commands/lpop.html
     */
    public String lpop(String key) {
        if (isCluster) {
            return jedisCluster.lpop(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String ret = shardedJedis.lpop(key);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public List<String> blpop(String key) {
        if (isCluster) {
            return jedisCluster.blpop(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                List<String> ret = shardedJedis.blpop(key);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public List<String> brpop(String key) {
        if (isCluster) {
            return jedisCluster.brpop(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                List<String> ret = shardedJedis.brpop(key);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public <T> T lpop(String key, Class<T> clazz) {
        return JsonUtils.fromJson(lpop(key), clazz);
    }

    /**
     * 弹出头部元素
     *
     * @return
     * @see -link- http://redis.cn/commands/rpop.html
     */
    public String rpop(String key) {
        if (isCluster) {
            return jedisCluster.rpop(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String ret = shardedJedis.rpop(key);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public <T> T rpop(String key, Class<T> clazz) {
        return JsonUtils.fromJson(rpop(key), clazz);
    }

    /**
     * 获取LIST长度
     *
     * @return list长度
     * @see -link- http://redis.cn/commands/llen.html
     */
    public long llen(String key) {
        if (isCluster) {
            return jedisCluster.llen(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long ret = shardedJedis.llen(key);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 删除LIST中的值
     *
     * @return list长度
     * @see -link- http://redis.cn/commands/lrem.html
     */
    public long lrem(String key, long count, String value) {
        if (isCluster) {
            return jedisCluster.lrem(key, count, value);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long ret = shardedJedis.lrem(key, count, value);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public long lrem(String key, long count, Object obj) {
        return lrem(key, count, JsonUtils.toJson(obj));
    }

    /**
     * 修剪
     *
     * @return list长度
     * @see -link- http://redis.cn/commands/ltrim.html
     */
    public String ltrim(String key, long start, long end) {
        if (isCluster) {
            return jedisCluster.ltrim(key, start, end);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String ret = shardedJedis.ltrim(key, start, end);
                return ret;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 获取key这个List,从第几个元素到第几个元素 LRANGE key start
     *
     * @param key   List别名
     * @param start 开始下标
     * @param end   结束下标
     * @return
     * @see -link- http://redis.cn/commands/lrange.html
     */
    public List<String> lrange(String key, long start, long end) {
        if (isCluster) {
            return jedisCluster.lrange(key, start, end);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                List<String> list = shardedJedis.lrange(key, start, end);
                return list;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public <T> List<T> lrange(String key, long start, long end, Class<T> clazz) {
        List<String> lrange = lrange(key, start, end);
        List<T> returnList = new ArrayList<T>();
        for (String string : lrange) {
            returnList.add(JsonUtils.fromJson(string, clazz));
        }
        return returnList;
    }

    /**
     * 将哈希表key中的域field的值设为value。
     *
     * @param key    哈希表别名
     * @param field 键
     * @param value  值
     * @see -link- http://redis.cn/commands/hset.html
     */
    public void hset(String key, String field, String value) {
        if (isCluster) {
            jedisCluster.hset(key, field, value);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                shardedJedis.hset(key, field, value);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public void hset(String key, String field, Object value) {
        hset(key, field, JsonUtils.toJson(value));
    }

    /**
     * @param key
     * @param value
     * @see -link- http://redis.cn/commands/set.html
     */
    public void set(String key, String value) {
        if (isCluster) {
            jedisCluster.set(key, value);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                shardedJedis.set(key, value);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public void set(String key, Object value) {
        set(key, JsonUtils.toJson(value));
    }

    /**
     * 获取key的值
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/get.html
     */
    public String get(String key) {
        if (isCluster) {
            return jedisCluster.get(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String value = shardedJedis.get(key);
                return value;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public <T> T get(String key, Class<T> clazz) {
        return JsonUtils.fromJson(get(key), clazz);
    }

    public <T> T get(String key, JavaType javaType) {
        return JsonUtils.fromJson(get(key), javaType);
    }

    /**
     * 获取key的值
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/get.html
     */
    public long del(String key) {
        if (isCluster) {
            return jedisCluster.del(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                long value = shardedJedis.del(key);
                return value;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 将多个field - value(域-值)对设置到哈希表key中。
     *
     * @param key
     * @param map
     * @see -link- http://redis.cn/commands/hmset.html
     */
    public void hmset(String key, Map<String, String> map) {
        if (isCluster) {
            jedisCluster.hmset(key, map);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                shardedJedis.hmset(key, map);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public void hmset2(String key, Map<String, Object> map) {
        Map<String, String> bMap = new LinkedHashMap<String, String>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            bMap.put(entry.getKey(), JsonUtils.toJson(entry.getValue()));
        }
        hmset(key, bMap);
    }

    /**
     * 给key赋值,并生命周期设置为seconds
     *
     * @param key
     * @param seconds 生命周期 秒为单位
     * @param value
     * @see -link- http://redis.cn/commands/setex.html
     */
    public void setex(String key, int seconds, String value) {
        if (isCluster) {
            jedisCluster.setex(key, seconds, value);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                shardedJedis.setex(key, seconds, value);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public void setex(String key, int seconds, Object value) {
        setex(key, seconds, JsonUtils.toJson(value));
    }

    /**
     * 为给定key设置生命周期
     *
     * @param key
     * @param seconds 生命周期 秒为单位
     * @see -link- http://redis.cn/commands/expire.html
     */
    public void expire(String key, int seconds) {
        if (isCluster) {
            jedisCluster.expire(key, seconds);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                shardedJedis.expire(key, seconds);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 获取key的有效时间
     *
     * @param key
     * @return seconds 生命时间 有效时间
     * @see -link- http://redis.cn/commands/ttl.html
     */
    public Long ttl(String key) {
        if (isCluster) {
            return jedisCluster.ttl(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.ttl(key);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 检查key是否存在
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/exists.html
     */
    public boolean exists(String key) {
        if (isCluster) {
            return jedisCluster.exists(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                boolean bool = shardedJedis.exists(key);
                return bool;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 返回key值的类型 none(key不存在),string(字符串),list(列表),set(集合),zset(有序集),hash(哈希表)
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/type.html
     */
    public String type(String key) {
        if (isCluster) {
            return jedisCluster.type(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String type = shardedJedis.type(key);
                return type;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 从哈希表key中获取field的value
     *
     * @param key
     * @param field
     * @see -link- http://redis.cn/commands/hget.html
     */
    public String hget(String key, String field) {
        if (isCluster) {
            return jedisCluster.hget(key, field);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                String value = shardedJedis.hget(key, field);
                return value;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 返回哈希表key中,所有的域和值 默认无序
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/hgetall.html
     */
    public Map<String, String> hgetAll(String key) {
        return hgetAll(key, false);
    }

    /**
     * 返回哈希表key中,所有的域和值
     *
     * @param key
     * @param order 是否保持原始顺序
     * @return
     * @see -link- http://redis.cn/commands/hgetall.html
     */
    public Map<String, String> hgetAll(String key, boolean order) {
        if (isCluster) {
            return jedisCluster.hgetAll(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                if (order) {
                    Jedis shard = shardedJedis.getShard(key);
                    if (shard.getClient().isInMulti()) {
                        throw new JedisDataException("Cannot use Jedis when in Multi. Please use JedisTransaction instead.");
                    }
                    shard.getClient().hgetAll(key);
                    return STRING_LINKEDHASHMAP.build(shard.getClient().getBinaryMultiBulkReply());
                } else {
                    return shardedJedis.hgetAll(key);
                }
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 返回哈希表key中,所有的域和值 默认有序
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/hgetall.html
     */
    public Map<String, String> hgetAllToLinkedHashMap(String key) {
        return hgetAll(key, true);
    }

    public static final Builder<Set<String>> STRING_LINKEDHASHSET = new Builder<Set<String>>() {
        @Override
        @SuppressWarnings("unchecked")
        public Set<String> build(Object data) {
            if (null == data) {
                return null;
            }
            List<byte[]> l = (List<byte[]>) data;
            final Set<String> result = new LinkedHashSet<String>(l.size());
            for (final byte[] barray : l) {
                if (barray == null) {
                    result.add(null);
                } else {
                    result.add(SafeEncoder.encode(barray));
                }
            }
            return result;
        }

        @Override
        public String toString() {
            return "Set<String>";
        }
    };

    public static final Builder<Map<String, String>> STRING_LINKEDHASHMAP = new Builder<Map<String, String>>() {
        @Override
        @SuppressWarnings("unchecked")
        public Map<String, String> build(Object data) {
            final List<byte[]> flatHash = (List<byte[]>) data;
            final Map<String, String> hash = new LinkedHashMap<String, String>();
            final Iterator<byte[]> iterator = flatHash.iterator();
            while (iterator.hasNext()) {
                hash.put(SafeEncoder.encode(iterator.next()), SafeEncoder.encode(iterator.next()));
            }

            return hash;
        }

        @Override
        public String toString() {
            return "Map<String, String>";
        }

    };

    /**
     * 返回哈希表key中,所有值
     *
     * @param key
     * @return
     * @see -link- http://redis.cn/commands/smembers.html
     */
    public Set<?> smembers(String key) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            Set<?> set = shardedJedis.smembers(key);
            return set;
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 移除集合中的member元素
     *
     * @param key   List别名
     * @param field 键
     * @see -link- http://redis.cn/commands/srem.html
     */
    public void srem(String key, String... field) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            shardedJedis.srem(key, field);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public void srem(String key, Object... field) {
        String[] arr = new String[field.length];
        for (int i = 0; i < field.length; i++) {
            arr[i] = JsonUtils.toJson(field[i]);
        }
        srem(key, arr);
    }

    /**
     * 判断member元素是否是集合key的成员。是(true),否则(false)
     *
     * @param key
     * @param field
     * @return
     * @see -link- http://redis.cn/commands/sismember.html
     */
    public boolean sismember(String key, String field) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            boolean bool = shardedJedis.sismember(key, field);
            return bool;
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public boolean sismember(String key, Object field) {
        return sismember(key, JsonUtils.toJson(field));
    }

    /**
     * 如果key已经存在并且是一个字符串,将value追加到key原来的值之后
     *
     * @param key
     * @param value
     * @see -link- http://redis.cn/commands/append.html
     */
    public void append(String key, String value) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            shardedJedis.append(key, value);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * -- key
     *
     * @param key
     * @see -link- http://redis.cn/commands/decr.html
     */
    public Long decr(String key) {
        if (isCluster) {
            return jedisCluster.decr(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.decr(key);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * key 减指定数值
     *
     * @param key
     * @see -link- http://redis.cn/commands/decrBy.html
     */
    public Long decrBy(String key, Integer integer) {
        if (isCluster) {
            return jedisCluster.decrBy(key, integer);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.decrBy(key, integer);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 删除key
     *
     * @param key
     * @see -link- http://redis.cn/commands/del.html
     */
    public Long decrBy(String key) {
        if (isCluster) {
            return jedisCluster.del(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.del(key);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 这里的N是返回的string的长度。复杂度是由返回的字符串长度决定的,但是因为从一个已经存在的字符串创建一个子串是很容易的,所以对于较小的字符串,
     * 可以认为是O(1)的复杂度。
     *
     * @param key
     * @see -link- http://redis.cn/commands/getrange.html
     */
    public String decrBy(String key, int startOffset, int endOffset) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.getrange(key, startOffset, endOffset);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。
     *
     * @param key
     * @param value
     * @see -link- http://redis.cn/commands/getSet.html
     */
    public String decrBy(String key, String value) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.getSet(key, value);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 从 key 指定的哈希集中移除指定的域。在哈希集中不存在的域将被忽略。如果 key
     * 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0。
     * <p/>
     * 返回值 整数:返回从哈希集中成功移除的域的数量,不包括指出但不存在的那些域
     *
     * @param key
     * @param fields
     * @see -link- http://redis.cn/commands/hdel.html
     */
    public Long hdel(String key, String... fields) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hdel(key, fields);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 返回字段是否是 key 指定的哈希集中存在的字段。
     * <p/>
     * 返回值 整数, 含义如下:
     * <p/>
     * 1 哈希集中含有该字段。 0 哈希集中不含有该存在字段,或者key不存在。
     *
     * @param key
     * @param fields
     * @see -link- http://redis.cn/commands/hexists.html
     */
    public Boolean hexists(String key, String fields) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hexists(key, fields);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Boolean hexists(String key, Object field) {
        return hexists(key, JsonUtils.toJson(field));
    }

    /**
     * 增加 key 指定的哈希集中指定字段的数值。如果 key 不存在,会创建一个新的哈希集并与 key
     * 关联。如果字段不存在,则字段的值在该操作执行前被设置为 0
     * <p/>
     * HINCRBY 支持的值的范围限定在 64位 有符号整数
     * <p/>
     * 返回值 整数:增值操作执行后的该字段的值。
     *
     * @param key
     * @param field
     * @param value
     * @see -link- http://redis.cn/commands/hincrBy.html
     */
    public Long hincrBy(String key, String field, int value) {
        if (isCluster) {
            return jedisCluster.hincrBy(key, field, value);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.hincrBy(key, field, value);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 返回 key 指定的哈希集中所有字段的名字。
     * <p/>
     * 返回值 多个返回值:哈希集中的字段列表,当 key 指定的哈希集不存在时返回空列表。
     *
     * @param key
     * @return 返回值为linkedhashset有序
     * @see -link- http://redis.cn/commands/hkeys.html
     */
    public Set<String> hkeys(String key) {
        if (isCluster) {
            return jedisCluster.hkeys(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                Jedis shard = shardedJedis.getShard(key);
                if (shard.getClient().isInMulti()) {
                    throw new JedisDataException("Cannot use Jedis when in Multi. Please use JedisTransaction instead.");
                }
                shard.getClient().hkeys(key);
                return STRING_LINKEDHASHSET.build(shard.getClient().getBinaryMultiBulkReply());
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * key field 原子性incr value
     * <p/>
     * 返回值incr后的值
     *
     * @param key
     * @param field
     * @param value
     * @return
     * @see -link- http://redis.cn/commands/hincrbyfloat.html
     */
    public Double hincrbyfloat(String key, String field, double value) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hincrByFloat(key, field, value);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 增量迭代一个集合元素 SCAN
     * 命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程 当 SCAN
     * 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。<br>
     * 量式迭代命令, 在进行完整遍历的情况下可以为用户带来以下保证 : 从完整遍历开始直到完整遍历结束期间,
     * 一直存在于数据集内的所有元素都会被完整遍历返回; 这意味着, 如果有一个元素, 它从遍历开始直到遍历结束期间都存在于被遍历的数据集当中, 那么
     * SCAN 命令总会在某次迭代中将这个元素返回给用户。
     * 同样,如果一个元素在开始遍历之前被移出集合,并且在遍历开始直到遍历结束期间都没有再加入,那么在遍历返回的元素集中就不会出现该元素。
     * 然而因为增量式命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点: 同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责,
     * 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。 如果一个元素是在迭代过程中被添加到数据集的,
     * 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会。
     *
     * @param key
     * @param cursor 游标
     * @return
     * @see -link- http://redis.cn/commands/hscan.html
     */
    public ScanResult<Map.Entry<String, String>> hscan(String key, String cursor) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hscan(key, cursor);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 返回 key 指定的哈希集包含的字段的数量。
     * <p/>
     * 返回值 整数:哈希集中字段的数量,当 key 指定的哈希集不存在时返回 0
     *
     * @param key
     * @see -link- http://redis.cn/commands/hlen.html
     */
    public Long hlen(String key) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hlen(key);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 返回 key 指定的哈希集中指定字段的值。
     * <p/>
     * 对于哈希集中不存在的每个字段,返回 nil 值。因为不存在的keys被认为是一个空的哈希集,对一个不存在的 key 执行 HMGET
     * 将返回一个只含有 nil 值的列表
     * <p/>
     * 返回值 多个返回值:含有给定字段及其值的列表,并保持与请求相同的顺序。
     *
     * @param key
     * @param fields
     * @see -link- http://redis.cn/commands/hmget.html
     */
    public List<String> hmget(String key, String... fields) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hmget(key, fields);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 只在 key 指定的哈希集中不存在指定的字段时,设置字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key
     * 关联。如果字段已存在,该操作无效果。
     * <p/>
     * 返回值 整数:含义如下
     * <p/>
     * 1:如果字段是个新的字段,并成功赋值 0:如果哈希集中已存在该字段,没有操作被执行
     *
     * @param key
     * @see -link- http://redis.cn/commands/hsetnx.html
     */
    public Long hsetnx(String key, String field, String value) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.hsetnx(key, field, value);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long hsetnx(String key, String field, Object value) {
        return hsetnx(key, field, JsonUtils.toJson(value));
    }

    /**
     * 返回 key 指定的哈希集中所有字段的值。
     * <p/>
     * 返回值 多个返回值:哈希集中的值的列表,当 key 指定的哈希集不存在时返回空列表。
     *
     * @param key
     * @return 返回值为arraylist 有序
     * @see -link- http://redis.cn/commands/hvals.html
     */
    public List<String> hvals(String key) {
        if (isCluster) {
            return jedisCluster.hvals(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.hvals(key);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * ++key
     *
     * @param key
     * @see -link- http://redis.cn/commands/incr.html
     */
    public Long incr(String key) {
        if (isCluster) {
            return jedisCluster.incr(key);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.incr(key);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 参选,如果参选成功将为key续期,如果已有被选举人则判断是否为自己 为自己则续期
     *
     * @param key        参选项目
     * @param candidates 候选人
     * @param timeOut    参选成功后的过期时间
     * @return true 参选成功并续期成功 或 被选举人为自己并续期成功, false 参选失败或被选举人不为自己
     */
    public boolean electioneer(String key, String candidates, int timeOut) {
        if (isCluster) {
            int setnx = jedisCluster.setnx(key, candidates).intValue();
            if (setnx == 1) {
                jedisCluster.expire(key, timeOut);
            }
            String electee = jedisCluster.get(key);
            if (electee != null && electee.equals(candidates)) {
                jedisCluster.expire(key, timeOut);
                return true;
            }else {
                return false;
            }
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                int setnx = shardedJedis.setnx(key, candidates).intValue();
                boolean bool = false;
                if (setnx == 1) {
                    shardedJedis.expire(key, timeOut);
                    bool = true;
                } else {
                    String electee = shardedJedis.get(key);
                    if (electee != null && electee.equals(candidates)) {
                        shardedJedis.expire(key, timeOut);
                        bool = true;
                    }
                }
                return bool;
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    /**
     * 将key对应的数字加decrement。如果key不存在,操作之前,key就会被置为0。
     * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
     * <p/>
     * 查看命令INCR了解关于增减操作的额外信息。
     * <p/>
     * 返回值 数字:增加之后的value值。
     *
     * @param key
     * @param integer
     * @see -link- http://redis.cn/commands/incrBy.html
     */
    public Long incrBy(String key, int integer) {
        if (isCluster) {
            return jedisCluster.incrBy(key, integer);
        } else {
            ShardedJedis shardedJedis = null;
            try {
                shardedJedis = getResource();
                return shardedJedis.incrBy(key, integer);
            } catch (Exception e) {
                returnBrokenResource(shardedJedis);
                log.error(e.getMessage(), e);
                throw new JedisException(e);
            } finally {
                returnResource(shardedJedis);
            }
        }
    }

    public Long zadd(String key, Map<String, Double> scoreMembers) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zadd(key, scoreMembers);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zadd(String key, double score, String member) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zadd(key, score, member);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zcard(String key) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zcard(key);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zcount(String key, double min, double max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zcount(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zcount(String key, String min, String max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zcount(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Double zincrby(String key, double score, String member) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zincrby(key, score, member);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrange(String key, long start, long end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrange(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScoreWithScores(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, String min, String max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScoreWithScores(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrangeWithScores(String key, long start, long end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeWithScores(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrangeByScore(String key, String min, String max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScore(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrangeByScore(String key, double min, double max) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScore(key, min, max);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScoreWithScores(key, min, max, offset, count);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrangeByScoreWithScores(key, min, max, offset, count);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zrank(String key, String member) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrank(key, member);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zrem(String key, String... members) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrem(key, members);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zremrangeByRank(String key, long start, long end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zremrangeByRank(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zremrangeByScore(String key, double start, double end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zremrangeByScore(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zremrangeByScore(String key, String start, String end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zremrangeByScore(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrevrange(String key, long start, long end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrange(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrevrangeByScore(String key, double max, double min) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScore(key, max, min);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<String> zrevrangeByScore(String key, String max, String min) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScore(key, max, min);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScoreWithScores(key, max, min);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScoreWithScores(key, max, min);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Set<Tuple> zrevrangeWithScores(String key, long start, long end) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrangeWithScores(key, start, end);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public Long zrevrank(String key, String member) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zrevrank(key, member);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    public ScanResult<Tuple> zscan(String key, String cursor) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            return shardedJedis.zscan(key, cursor);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 订阅指定shardkey下的某些频道
     *
     * @param shardkey    用于shard定向
     * @param jedisPubSub 用于回调
     * @param channels    频道名称
     * @see -link- http://redis.cn/commands/subscribe.html
     */
    public void subscribe(String shardkey, JedisPubSub jedisPubSub, String... channels) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            shardedJedis.getShard(shardkey).subscribe(jedisPubSub, channels);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 向指定shardkey下的某频道发送消息
     *
     * @param shardkey 用于shard定向
     * @param channel  频道名称
     * @param message  消息内容
     * @see -link- http://redis.cn/commands/publish.html
     */
    public void publish(String shardkey, String channel, String message) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = getResource();
            shardedJedis.getShard(shardkey).publish(channel, message);
        } catch (Exception e) {
            returnBrokenResource(shardedJedis);
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        } finally {
            returnResource(shardedJedis);
        }
    }

    /**
     * 构建一个支持sharding的批处理工具类
     *
     * @return
     */
    public ShardedJedisPipelineUtils buildPipelineUtils() {
        if (isCluster) {
            return new ShardedJedisPipelineUtils(this.pool, this.getResource());
        } else {
            return new ShardedJedisPipelineUtils(this.pool, this.getResource());
        }
    }

    /**
     * 根据shardKey获取jedis
     *
     * @param shardKey
     */
    public Jedis getJedisByShardKey(String shardKey) {
        try {
            return getResource().getShard(shardKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new JedisException(e);
        }
    }

    /**
     * 判断是否能提交
     */
    public boolean canBeSubmit(String key, String value, int seconds) {
        if (isCluster) {
            try {
                JedisClusterPipelineUtils jcp = JedisClusterPipelineUtils.pipelined(jedisCluster);
                jcp.setnx(key, value);
                jcp.expire(key, seconds);
                List<Object> resultList = jcp.syncAndReturnAll();
                log.debug("resultList size ++++" + resultList.size());
                log.debug("resultList value ++++" + JsonUtils.toJson(resultList));
                if (CollectionUtils.isNotEmpty(resultList)) {
                    if ("1".equals(resultList.get(0).toString())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
//            if (jedisCluster.setnx(key, value).intValue() == 1){
//                jedisCluster.expire(key, seconds);
//                jedisCluster.getClusterNodes();
//                return true;
//            } else {
//                return false;
//            }
        } else {
            try {
                ShardedJedisPipelineUtils pipelineUtils = this.buildPipelineUtils();
                pipelineUtils.setnx(key, value);
                pipelineUtils.expire(key, seconds);
                List<Object> resultList = pipelineUtils.syncAndReturnAll();

                if ("1".equals(resultList.get(0).toString())) {
                    return true;
                } else {
                    return false;
                }

            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }

    /**
     * 获取key在 shard分片中的index
     *
     * @param uri
     * @param key
     * @return
     */
    public static int getShardIndex(String uri, String key) {
        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
        for (String ips : uri.split(",")) {
            JedisShardInfo info = new JedisShardInfo(ips.split(":")[0], Integer.parseInt(ips.split(":")[1]));
            shards.add(info);
        }
        TreeMap<Long, JedisShardInfo> nodes = new TreeMap<Long, JedisShardInfo>();
        for (int i = 0; i != shards.size(); ++i) {
            final JedisShardInfo shardInfo = shards.get(i);
            if(shardInfo.getName() == null) {
                for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
                    nodes.put(Hashing.MURMUR_HASH.hash("SHARD-" + i + "-NODE-" + n), shardInfo);
                }
            }else {
                for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
                    nodes.put(Hashing.MURMUR_HASH.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo);
                }
            }
        }
        SortedMap<Long, JedisShardInfo> tail = nodes.tailMap(Hashing.MURMUR_HASH.hash(SafeEncoder.encode(key)));
        JedisShardInfo currJedisShardInfo = null;
        if (tail.size() == 0) {
            currJedisShardInfo = nodes.get(nodes.firstKey());
        } else {
            currJedisShardInfo = tail.get(tail.firstKey());
        }
        System.out.println(key + " saved " + currJedisShardInfo);
        for (int i = 0; i < shards.size(); i++) {
            if (shards.get(i).equals(currJedisShardInfo)) {
                return i;
            }
        }
        return -1;
    }

}
           
package com.bigdata.project.util.cache.redis.cluster;


import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisMovedDataException;
import redis.clients.jedis.exceptions.JedisRedirectionException;
import redis.clients.util.JedisClusterCRC16;
import redis.clients.util.SafeEncoder;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;

public class JedisClusterPipelineUtils extends PipelineBase implements Closeable {

    // 部分字段没有对应的获取方法,只能采用反射来做
    // 你也可以去继承JedisCluster和JedisSlotBasedConnectionHandler来提供访问接口
    private static final Field FIELD_CONNECTION_HANDLER;
    private static final Field FIELD_CACHE;
    static {
        FIELD_CONNECTION_HANDLER = getField(BinaryJedisCluster.class, "connectionHandler");
        FIELD_CACHE = getField(JedisClusterConnectionHandler.class, "cache");
    }

    private JedisSlotBasedConnectionHandler connectionHandler;
    private JedisClusterInfoCache clusterInfoCache;
    private Queue<Client> clients = new LinkedList<Client>();   // 根据顺序存储每个命令对应的Client
    private Map<JedisPool, Jedis> jedisMap = new HashMap<JedisPool, Jedis>();   // 用于缓存连接
    private boolean hasDataInBuf = false;   // 是否有数据在缓存区

    /**
     * 根据jedisCluster实例生成对应的JedisClusterPipeline
     * @param
     * @return
     */
    public static JedisClusterPipelineUtils pipelined(JedisCluster jedisCluster) {
        JedisClusterPipelineUtils pipeline = new JedisClusterPipelineUtils();
        pipeline.setJedisCluster(jedisCluster);
        return pipeline;
    }

    public JedisClusterPipelineUtils() {
    }

    public void setJedisCluster(JedisCluster jedis) {
        connectionHandler = getValue(jedis, FIELD_CONNECTION_HANDLER);
        clusterInfoCache = getValue(connectionHandler, FIELD_CACHE);
    }
    @Override
    public void close() throws IOException {
        clean();

        clients.clear();

        for (Jedis jedis : jedisMap.values()) {
            if (hasDataInBuf) {
                flushCachedData(jedis);
            }

            jedis.close();
        }

        jedisMap.clear();

        hasDataInBuf = false;
    }

    @Override
    protected Client getClient(String key) {
        byte[] bKey = SafeEncoder.encode(key);

        return getClient(bKey);
    }

    @Override
    protected Client getClient(byte[] key) {
        Jedis jedis = getJedis(JedisClusterCRC16.getSlot(key));

        Client client = jedis.getClient();
        clients.add(client);

        return client;
    }

    /**
     * 刷新集群信息,当集群信息发生变更时调用
     *
     * @param
     * @return
     */
    public void refreshCluster() {
        connectionHandler.renewSlotCache();
    }

    /**
     * 同步读取所有数据. 与syncAndReturnAll()相比,sync()只是没有对数据做反序列化
     */
    public void sync() throws IOException{
        innerSync(null);
    }

    private static Field getField(Class<?> cls, String fieldName) {
        try {
            Field field = cls.getDeclaredField(fieldName);
            field.setAccessible(true);

            return field;
        } catch (Exception e) {
            throw new RuntimeException("cannot find or access field '" + fieldName + "' from " + cls.getName(), e);
        }
    }

    private static <T> T getValue(Object obj, Field field) {
        try {
            return (T) field.get(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Jedis getJedis(int slot) {
        JedisPool pool = clusterInfoCache.getSlotPool(slot);

        // 根据pool从缓存中获取Jedis
        Jedis jedis = jedisMap.get(pool);
        if (null == jedis) {
            jedis = pool.getResource();
            jedisMap.put(pool, jedis);
        }

        hasDataInBuf = true;
        return jedis;
    }

    private void flushCachedData(Jedis jedis) {
        try {
            jedis.getClient().getAll();
        } catch (RuntimeException ex) {
        }
    }

    /**
     * 同步读取所有数据 并按命令顺序返回一个列表
     *
     * @return 按照命令的顺序返回所有的数据
     */
    public List<Object> syncAndReturnAll() throws IOException{
        List<Object> responseList = new ArrayList<Object>();

        innerSync(responseList);

        return responseList;
    }

    private void innerSync(List<Object> formatted) throws IOException {
        HashSet<Client> clientSet = new HashSet<Client>();

        try {
            for (Client client : clients) {
                // 在sync()调用时其实是不需要解析结果数据的,但是如果不调用get方法,发生了JedisMovedDataException这样的错误应用是不知道的,因此需要调用get()来触发错误。
                // 其实如果Response的data属性可以直接获取,可以省掉解析数据的时间,然而它并没有提供对应方法,要获取data属性就得用反射,不想再反射了,所以就这样了
                Object data = generateResponse(client.getOne()).get();
                if (null != formatted) {
                    formatted.add(data);
                }

                // size相同说明所有的client都已经添加,就不用再调用add方法了
                if (clientSet.size() != jedisMap.size()) {
                    clientSet.add(client);
                }
            }
        } catch (JedisRedirectionException jre) {
            if (jre instanceof JedisMovedDataException) {
                // if MOVED redirection occurred, rebuilds cluster's slot cache,
                // recommended by Redis cluster specification
                refreshCluster();
            }

            throw jre;
        } finally {
            if (clientSet.size() != jedisMap.size()) {
                // 所有还没有执行过的client要保证执行(flush),防止放回连接池后后面的命令被污染
                for (Jedis jedis : jedisMap.values()) {
                    if (clientSet.contains(jedis.getClient())) {
                        continue;
                    }

                    flushCachedData(jedis);
                }
            }

            hasDataInBuf = false;
            close();
        }
    }

}
           
package com.bigdata.project.util.cache.redis.cluster;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisException;

import java.util.*;

public class ShardedJedisPipelineUtils extends Queable {
	private static final Logger logger = LoggerFactory
			.getLogger(ShardedJedisPipelineUtils.class);

	private ShardedJedisPool pool;

	public ShardedJedisPipelineUtils(ShardedJedisPool pool, ShardedJedis jedis) {
		super();
		this.pool = pool;
		this.jedis = jedis;
	}

	/**
	 * 执行批命令并返回执行结果list,不管是否执行成功都会释放连接池资源
	 */
	public List<Object> syncAndReturnAll() {
		try {
			List<Object> formatted = new ArrayList<Object>();
			for (Client client : clients) {
				formatted.add(generateResponse(client.getOne()).get());
			}
			return formatted;
		} catch (Exception e) {
			if (jedis != null) {
				try {
					pool.returnBrokenResource(jedis);
				} catch (Exception e2) {
					logger.error(e2.getMessage(), e2);
				}
			}
			logger.error(e.getMessage(), e);
			throw new JedisException(e);
		} finally {
			if (jedis != null) {
				try {
					pool.returnResource(jedis);
				} catch (Exception e2) {
					logger.error(e2.getMessage(), e2);
				}
			}
		}
	}

	private ShardedJedis jedis;
	private List<FutureResult> results = new ArrayList<FutureResult>();
	private Queue<Client> clients = new LinkedList<Client>();

	private static class FutureResult {
		private Client client;

		public FutureResult(Client client) {
			this.client = client;
		}

		public Object get() {
			return client.getOne();
		}
	}

	public void setShardedJedis(ShardedJedis jedis) {
		this.jedis = jedis;
	}

	public Response<String> set(String key, String value) {
		Client c = getClient(key);
		c.set(key, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> del(String key) {
		Client c = getClient(key);
		c.del(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> get(String key) {
		Client c = getClient(key);
		c.get(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Boolean> exists(String key) {
		Client c = getClient(key);
		c.exists(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<Boolean> type(String key) {
		Client c = getClient(key);
		c.type(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<Long> expire(String key, int seconds) {
		Client c = getClient(key);
		c.expire(key, seconds);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> expireAt(String key, long unixTime) {
		Client c = getClient(key);
		c.expireAt(key, unixTime);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> ttl(String key) {
		Client c = getClient(key);
		c.ttl(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> getSet(String key, String value) {
		Client c = getClient(key);
		c.getSet(key, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> setnx(String key, String value) {
		Client c = getClient(key);
		c.setnx(key, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> setex(String key, int seconds, String value) {
		Client c = getClient(key);
		c.setex(key, seconds, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> decrBy(String key, long integer) {
		Client c = getClient(key);
		c.decrBy(key, integer);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> decr(String key) {
		Client c = getClient(key);
		c.decr(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> incrBy(String key, int integer) {
		Client c = getClient(key);
		c.incrBy(key, integer);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> incr(String key) {
		Client c = getClient(key);
		c.incr(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> append(String key, String value) {
		Client c = getClient(key);
		c.append(key, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> substr(String key, int start, int end) {
		Client c = getClient(key);
		c.substr(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> hset(String key, String field, String value) {
		Client c = getClient(key);
		c.hset(key, field, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> hget(String key, String field) {
		Client c = getClient(key);
		c.hget(key, field);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> hsetnx(String key, String field, String value) {
		Client c = getClient(key);
		c.hsetnx(key, field, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> hmset(String key, Map<String, String> hash) {
		Client c = getClient(key);
		c.hmset(key, hash);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<List<String>> hmget(String key, String... fields) {
		Client c = getClient(key);
		c.hmget(key, fields);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_LIST);
	}

	public Response<Long> hincrBy(String key, String field, int value) {
		Client c = getClient(key);
		c.hincrBy(key, field, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Boolean> hexists(String key, String field) {
		Client c = getClient(key);
		c.hexists(key, field);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<Long> hdel(String key, String field) {
		Client c = getClient(key);
		c.hdel(key, field);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> hlen(String key) {
		Client c = getClient(key);
		c.hlen(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Set<String>> hkeys(String key) {
		Client c = getClient(key);
		c.hkeys(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_SET);
	}

	public Response<Set<String>> hvals(String key) {
		Client c = getClient(key);
		c.hvals(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_SET);
	}

	public Response<Map<String, String>> hgetAll(String key) {
		Client c = getClient(key);
		c.hgetAll(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_MAP);
	}

	public Response<Long> rpush(String key, String string) {
		Client c = getClient(key);
		c.rpush(key, string);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> lpush(String key, String string) {
		Client c = getClient(key);
		c.lpush(key, string);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> llen(String key) {
		Client c = getClient(key);
		c.llen(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<List<String>> lrange(String key, int start, int end) {
		Client c = getClient(key);
		c.lrange(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_LIST);
	}

	public Response<String> ltrim(String key, int start, int end) {
		Client c = getClient(key);
		c.ltrim(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<String> lindex(String key, int index) {
		Client c = getClient(key);
		c.lindex(key, index);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<String> lset(String key, int index, String value) {
		Client c = getClient(key);
		c.lset(key, index, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> lrem(String key, int count, String value) {
		Client c = getClient(key);
		c.lrem(key, count, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> lpop(String key) {
		Client c = getClient(key);
		c.lpop(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<String> rpop(String key) {
		Client c = getClient(key);
		c.rpop(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> sadd(String key, String member) {
		Client c = getClient(key);
		c.sadd(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Set<String>> smembers(String key) {
		Client c = getClient(key);
		c.smembers(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_SET);
	}

	public Response<Long> srem(String key, String member) {
		Client c = getClient(key);
		c.srem(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<String> spop(String key) {
		Client c = getClient(key);
		c.spop(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> scard(String key) {
		Client c = getClient(key);
		c.scard(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Boolean> sismember(String key, String member) {
		Client c = getClient(key);
		c.sismember(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<String> srandmember(String key) {
		Client c = getClient(key);
		c.srandmember(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING);
	}

	public Response<Long> zadd(String key, double score, String member) {
		Client c = getClient(key);
		c.zadd(key, score, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Set<String>> zrange(String key, int start, int end) {
		Client c = getClient(key);
		c.zrange(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_ZSET);
	}

	public Response<Long> zrem(String key, String member) {
		Client c = getClient(key);
		c.zrem(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Double> zincrby(String key, double score, String member) {
		Client c = getClient(key);
		c.zincrby(key, score, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.DOUBLE);
	}

	public Response<Long> zrank(String key, String member) {
		Client c = getClient(key);
		c.zrank(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> zrevrank(String key, String member) {
		Client c = getClient(key);
		c.zrevrank(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Set<String>> zrevrange(String key, int start, int end) {
		Client c = getClient(key);
		c.zrevrange(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_ZSET);
	}

	public Response<Set<Tuple>> zrangeWithScores(String key, int start, int end) {
		Client c = getClient(key);
		c.zrangeWithScores(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.TUPLE_ZSET);
	}

	public Response<Set<Tuple>> zrevrangeWithScores(String key, int start,
			int end) {
		Client c = getClient(key);
		c.zrevrangeWithScores(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.TUPLE_ZSET);
	}

	public Response<Long> zcard(String key) {
		Client c = getClient(key);
		c.zcard(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Double> zscore(String key, String member) {
		Client c = getClient(key);
		c.zscore(key, member);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.DOUBLE);
	}

	public Response<Double> sort(String key) {
		Client c = getClient(key);
		c.sort(key);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.DOUBLE);
	}

	public Response<List<String>> sort(String key,
			SortingParams sortingParameters) {
		Client c = getClient(key);
		c.sort(key, sortingParameters);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_LIST);
	}

	public Response<Long> zcount(String key, double min, double max) {
		Client c = getClient(key);
		c.zcount(key, min, max);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Set<String>> zrangeByScore(String key, double min,
			double max) {
		Client c = getClient(key);
		c.zrangeByScore(key, min, max);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_ZSET);
	}

	public Response<Set<String>> zrangeByScore(String key, double min,
			double max, int offset, int count) {
		Client c = getClient(key);
		c.zrangeByScore(key, min, max, offset, count);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.STRING_ZSET);
	}

	public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min,
			double max) {
		Client c = getClient(key);
		c.zrangeByScoreWithScores(key, min, max);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.TUPLE_ZSET);
	}

	public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min,
			double max, int offset, int count) {
		Client c = getClient(key);
		c.zrangeByScoreWithScores(key, min, max, offset, count);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.TUPLE_ZSET);
	}

	public Response<Long> zremrangeByRank(String key, int start, int end) {
		Client c = getClient(key);
		c.zremrangeByRank(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> zremrangeByScore(String key, double start, double end) {
		Client c = getClient(key);
		c.zremrangeByScore(key, start, end);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Long> linsert(String key, LIST_POSITION where,
			String pivot, String value) {
		Client c = getClient(key);
		c.linsert(key, where, pivot, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public Response<Boolean> getbit(String key, long offset) {
		Client c = getClient(key);
		c.getbit(key, offset);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<Boolean> setbit(String key, long offset, boolean value) {
		Client c = getClient(key);
		c.setbit(key, offset, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.BOOLEAN);
	}

	public Response<Long> setrange(String key, long offset, String value) {
		Client c = getClient(key);
		c.setrange(key, offset, value);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);

	}

	public Response<Long> getrange(String key, long startOffset, long endOffset) {
		Client c = getClient(key);
		c.getrange(key, startOffset, endOffset);
		results.add(new FutureResult(c));
		return getResponse(BuilderFactory.LONG);
	}

	public List<Object> getResults() {
		List<Object> r = new ArrayList<Object>();
		for (FutureResult fr : results) {
			r.add(fr.get());
		}
		return r;
	}

	/**
	 * Syncronize pipeline by reading all responses. This operation closes the
	 * pipeline. In order to get return values from pipelined commands, capture
	 * the different Response&lt;?&gt; of the commands you execute.
	 */
	public void sync() {
		for (Client client : clients) {
			generateResponse(client.getOne());
		}
	}

	/**
	 * This method will be removed in Jedis 3.0. Use the methods that return
	 * Response's and call sync().
	 */
	@Deprecated
	public void execute() {
	}

	private Client getClient(String key) {
		Client client = jedis.getShard(key).getClient();
		clients.add(client);
		return client;
	}
}
           

继续阅读