Bootstrap

Redis队列使用

一、前言

      前一段时间,项目中要开发一个活动,为了提高接口的吞吐量,把一些完成后的操作使用异步的方法来操作。刚开始的时候想的是使用一个异步的方法,处理方法完成后的其他操作。但是在压测的时候发现,并发量很多的时候,线程池就会被沾满了,然后所有的操作都会堆积在这里,吞吐量就下来了。为了解决这个问题。就想用队列来处理,但是为了这么一个小的优化,接入mq又有点不合适。正好项目中用到了redis,就正好用redis来做异步处理,redis的性能也是非常好的。

      下面就介绍一下小编项目中的使用:

二、redisTemplete

      项目中,小编使用的是spring-data-redis,springboot使用的是1.5。

连接信息

package com.xxx.common.redis;

import com.alibaba.fastjson.JSON;
import com.xxx.common.logger.DushuLogger;
import com.xxx.common.utils.basic.RSAKeysUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;


@Configuration
public class RedisConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public JedisPoolConfig jedisPoolConfig() {

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 最大空闲数
        jedisPoolConfig.setMaxIdle(50);
        // 连接池的最大数据库连接数
        jedisPoolConfig.setMaxTotal(100);
        // 最大建立连接等待时间
        jedisPoolConfig.setMaxWaitMillis(3000);
        // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 5分钟
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(1000 * 60 * 5);
        // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
        jedisPoolConfig.setTestOnBorrow(true);
        return jedisPoolConfig;
    }


    /*
     * 仅支持springboot 2.0以上
    @Bean
    public JedisConnectionFactory connectionFactory(JedisPoolConfig jedisPoolConfig){
        JedisClientConfiguration.JedisClientConfigurationBuilder buider =  JedisClientConfiguration.builder();
        JedisClientConfiguration jedisClientConfiguration = buider.usePooling().poolConfig(jedisPoolConfig).build();
        RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
        standaloneConfiguration.setHostName(String.valueOf(ConfClient.getConfigInfo("redPacketSystem.redis.host", "")));
        standaloneConfiguration.setPassword(RedisPassword.of(RSAKeysUtil.decrypt(String.valueOf(ConfClient.getConfigInfo("redPacketSystem.redis.password", "")))));
        standaloneConfiguration.setPort(Integer.valueOf(ConfClient.getConfigInfo("redPacketSystem.redis.port", "6379").toString()).intValue());
        standaloneConfiguration.setDatabase(Integer.valueOf(ConfClient.getConfigInfo("redPacketSystem.redis.db", "12").toString()).intValue());
        JedisConnectionFactory jedisConnectionFactory =
                new JedisConnectionFactory(standaloneConfiguration,jedisClientConfiguration);
        return jedisConnectionFactory;
    }*/

    @Bean
    public JedisConnectionFactory connectionFactory(JedisPoolConfig jedisPoolConfig){
        DushuLogger.info("redis config:{},====", JSON.toJSONString(redisProperties));
        JedisConnectionFactory jedisConnectionFactory =
                new JedisConnectionFactory(jedisPoolConfig);
        jedisConnectionFactory.setHostName(redisProperties.getHost());
        jedisConnectionFactory.setPassword(RSAKeysUtil.decrypt(redisProperties.getPassword()));
        jedisConnectionFactory.setPort(redisProperties.getPort());
        jedisConnectionFactory.setDatabase(redisProperties.getDb());
        return jedisConnectionFactory;
    }


    @Bean("template")
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }

    /**
     *
     * 功能描述:
     * 后面要改成支持集群的ClusterConnnection
     * @param:
     * @return:
     * @auther: zhang
     * @date: 2018/9/30 17:00
     */
    @Deprecated
    public StringRedisConnection getStringRedisConnection(){
        DefaultStringRedisConnection defaultRedis = new DefaultStringRedisConnection(connectionFactory(jedisPoolConfig()).getConnection());
        return defaultRedis;
    }

}

RedisTemplate与StringRedisTemplate

      区别:

      1.两者数据各自存,各自取,数据不互通。

      RedisTemplate不能取StringRedisTemplate存入的数据。
      StringRedisTemplate不能取RedisTemplate存入的数据

      2.序列化策略不同。

      RedisTemplate采用JDK的序列化策略
      StringRedisTemplate采用String的序列化策略

      分析:

      RedisTemplate:

      存储时,先将数据序列化为字节数组,再存入Redis数据库。查看Redis会发现,是字节数组的形式。读取时,会将数据当做字节数组转化为我们需要的数据。

在这里插入图片描述

      StringRedisTemplate:

      存储和读取,都为可读的数据。
在这里插入图片描述

      问题:

      根据分析,我们就会发现一个问题。

      RedisTemplate存入数据后,key与value在Redis中均变为了字节数组。那么,如果使用StringRedisTemplate以相同的key去Redis中查询,会查询不到该key,则会报NULL。

      StringRedisTemplate存入数据后,key与value在Redis中均为可读数据。那么,如果使用RedisTemplate以相同key去Redus中查询,key变为了字节数组的形式,查询不到该字节数组形式的key,则会报NULL。

      所以,RedisTemplate与StringRedisTemplate的数据不互通。

      总结:

      如果你需要缓存的是字符串,那么你就使用StringRedisTemplate即可。但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择

在这里插入图片描述

存储入队列

 @Resource
 private RedisTemplate<String, Object> template;  //或者 private StringRedisTemplate stringRedisTemplate;

//把对象从队列的左边添加进去
 template.boundListOps(springgift:point:userId).leftPush(JSON.toJSONString(pointBO));

消费队列

package com.soybean.springgift;

import com.alibaba.fastjson.JSON;
import com.xxx.common.logger.DushuLogger;
import com.xxx.common.utils.basic.DateUtil;
import com.xxx.common.utils.basic.JsonUtil;
import com.xxx.common.utils.basic.entities.BusiSystemResponse;
import com.xxx.enums.common.CommonResponseCodeEnum;
import com.xxx.notify.bo.AppNotificationAddBO;
import com.xxx.notify.service.IAppNotificationService;
import com.xxxx.springgift.bo.PointBO;
import com.xxx.springgift.constant.ShareConstant;
import com.xxx.userbonus.bo.DeliverUserBonusBO;
import com.xxx.userbonus.bo.DeliverUserBonusIntegralParamsBO;
import com.xxx.userbonus.service.IBonusDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Component
public class PointMessageProcesser {

    @Resource(name = "template")
    private RedisTemplate<String, String> redisTemplate;
    private String springgiftPoint="springgift:point:queue";


    @Scheduled(cron = "*/5 * * * * ?")
    public void onMessage() {
        BoundListOperations<String, String> ops = redisTemplate.boundListOps(springgiftPoint);
        long count=0;
        while (!Thread.currentThread().isInterrupted()) {
            DushuLogger.debug("redis message consumer,queue:{}", springgiftPoint);
            //从队列右侧取出一条记录,如果超过等待的时间3秒仍没有元素则退出
            String data = ops.rightPop(3, TimeUnit.SECONDS);
            if (StringUtils.isEmpty(data)) {
                break;
            }
            DushuLogger.info("redis message:{}", data);
            PointBO pointBO = new PointBO();
            try {
                pointBO = JsonUtil.fromJSON(data, PointBO.class);
            } catch (Exception e) {
                DushuLogger.error("转换PointBO失败,data:{}", data);
            }
            if (null == pointBO) {
                break;
            }
            
            try {
                 //业务操作
            } catch (Exception e) {
                DushuLogger.error(e);
            }
            
            //每执行200次,休息50ms
            if((++count)%200 == 0) {
                count = 0;
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}

三、JedisTool相关的工具

      连接池

package com.soybean.redis.component;

import com.soybean.common.logger.DushuLogger;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPool;

@Component
public class RedisComponent {
    private final static String ipString = "xxxx";
    private final static String protString = "6379";
    private final static String timeoutString = "2000";
    private final static String paswordString = "xxxx";
    private final static String indexString = "6666";

    /**
     * 连接池
     *
     * @return
     */
    public JedisPool getUserJedisTool() {
        GenericObjectPoolConfig gopConfig = new GenericObjectPoolConfig();
        gopConfig.setMaxIdle(500);
        gopConfig.setMinIdle(500);
        gopConfig.setMaxTotal(500);

        String host = String.valueOf(ipString);
        int port = Integer.valueOf(protString);
        int timeout = Integer.valueOf(timeoutString);
        String password = paswordString;
        int db = Integer.valueOf(indexString);

        JedisPool jedisPool = new JedisPool(gopConfig, host, port, timeout, password, db);

        DushuLogger.info("-------redis 数据源信息-----\n{},{},{},{},{}", host, port, timeout, password, db);
        return jedisPool;
    }

}

      tool工具类:

package com.soybean.redis.component;

import com.soybean.common.logger.DushuLogger;
import com.soybean.common.utils.exception.RedisException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;

import java.util.List;
import java.util.Map;
import java.util.Set;


@Component
public class DushuJedisTool {


    @Autowired
    private RedisComponent redisComponent;

    public volatile JedisPool jedisPool;

    public Jedis getRedis() {
        Jedis jedis = null;
        try {
            if (jedisPool==null){
                jedisPool = redisComponent.getUserJedisTool();
            }
            jedis =  jedisPool.getResource();
        } catch (Exception e) {
            DushuLogger.info("redis连接失败,尝试重新连接");
            jedisPool = redisComponent.getUserJedisTool();
            jedis =  jedisPool.getResource();
        }
        return jedis;
    }

    public void ping() {
        Jedis j = getRedis();
        try {
            String ret = j.ping();
            if (ret.equals("PONG"))
                DushuLogger.info("Redis服务器连接正常");
            else
                DushuLogger.info("Redis服务器连接异常");
        } catch (Throwable t) {
            DushuLogger.error("redis ping error:", t);
        } finally {
            j.close();
        }
    }

    //
    // ------------------------------Key相关命令------------------------------
    //
    public String type(String key) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.type(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis type error:", t);
            throw new RedisException("redis type error");
        } finally {
            j.close();
        }
    }

    public Long del(String key) throws RedisException {
        Jedis j = getRedis();
        Long result = null;
        try {
            result = j.del(key);

            return result;
        } catch (Throwable t) {
            DushuLogger.error("redis del error:", t);
            throw new RedisException("redis del error");
        } finally {
            j.close();
        }
    }

    public void del(byte[] key) throws RedisException {
        Jedis j = getRedis();

        try {
            j.del(key);

        } catch (Throwable t) {
            DushuLogger.error("redis del error:", t);
            throw new RedisException("redis del error");
        } finally {
            j.close();
        }
    }

    /**
     * 删除指定的Key.
     * <p>
     * 时间复杂度 o(N),N为要移除Key的数量.<br>
     * 如果Key不存在,则直接忽略.
     *
     * @param keys Key列表
     * @return 被删除Keys的数量
     */
    public long del(String... keys) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.del(keys);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis del error:", t);
            throw new RedisException("redis del error");
        } finally {
            j.close();
        }
    }

    /**
     * 查找所有匹配给定的模式的Key.
     *
     * @param pattern 模式
     * @return Key集合
     */
    public Set<String> keys(String pattern) throws RedisException {
        Jedis j = getRedis();
        Set<String> ret = null;
        try {
            ret = j.keys(pattern);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis keys error:", t);
            throw new RedisException("redis keys error");
        } finally {
            j.close();
        }
    }

    /**
     * 查找所有匹配给定的模式的Key.
     *
     * @param pattern 模式
     * @return Key集合
     */
    public Set<byte[]> keys(byte[] pattern) throws RedisException {
        Jedis j = getRedis();
        Set<byte[]> ret = null;
        try {
            ret = j.keys(pattern);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis keys error:", t);
            throw new RedisException("redis keys error");
        } finally {
            j.close();
        }
    }

    /**
     * 设计Key的过期时间。
     * <p>
     * 如果Key已过期,将会被自动删除,设置了过期时间的Key被称之为volatile(不稳定) KEY.<br>
     *
     * @param key     KEY
     * @param seconds 过期时间(秒)
     * @return 如果设置了过期时间返回1,没有设置或不能设置过期时间返回0
     */
    public long expire(String key, int seconds) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.expire(key, seconds);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis expire error:", t);
            throw new RedisException("redis expire error");
        } finally {
            j.close();
        }
    }

    /**
     * 移除生存时间
     */
    public long persist(String key) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.persist(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis persist error:", t);
            throw new RedisException("redis persist error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取生存时间
     */
    public long ttl(String key) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.ttl(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis ttl error:", t);
            throw new RedisException("redis ttl error");
        } finally {
            j.close();
        }
    }

    //
    // ------------------------------String相关命令------------------------------
    //

    /**
     * 设置key所对应的value值.
     * <p>
     * 时间复杂度为o(1)<br>
     * 如果Key已存在了,它会被覆盖,而不管它是什么类型。<br>
     * 这里干掉了返回值,因为SET不会失败,总返回OK
     *
     * @param key   KEY值
     * @param value KEY对应的Value
     */
    public void set(String key, String value) throws RedisException {
        Jedis j = getRedis();
        try {
            j.set(key, value);

        } catch (Throwable t) {
            DushuLogger.error("redis set error:", t);
            throw new RedisException("redis set error");
        } finally {
            j.close();
        }
    }

    /**
     * 将key重命名为newKey.如果key与newkey相同,将返回错误,如果newkey已经存在,则值将被覆盖
     */
    public void rename(String key, String newKey) throws RedisException {
        Jedis j = getRedis();
        try {
            j.rename(key, newKey);

        } catch (Throwable t) {
            DushuLogger.error("redis rename error:", t);
            throw new RedisException("redis rename error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取key所对应的value值.
     * <p>
     * 时间复杂度为o(1)<br>
     * 如果key不存在,返回null.<br>
     * 如果key的value值不是String类型,就返回错误,因为Get只处理String类型的Values.
     *
     * @param key Key值
     * @return 如果Key存在,则返回对应的Value值.
     */
    public String get(String key) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.get(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis get error:", t);
            throw new RedisException("redis get error");
        } finally {
            j.close();
        }
    }

    /**
     * 判断指定Key是否存在.
     * <p>
     * 时间复杂度o(1)<br>
     *
     * @param key Key值
     * @return 如果存在,则返回true.
     */
    public boolean exists(String key) throws RedisException {
        Jedis j = getRedis();
        boolean ret = false;
        try {
            ret = j.exists(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis exists error:", t);
            throw new RedisException("redis exists error");
        } finally {
            j.close();
        }
    }

    /**
     * @param value the decrement value
     * @return the value of key after the decrement
     */
    public long decrBy(String key, long value) throws RedisException {
        Long ret = null;
        Jedis j = getRedis();
        try {
            ret = j.decrBy(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis decrBy error:", t);
            throw new RedisException("redis decrBy error");
        } finally {
            j.close();
        }
    }

    public String setex(String key, int seconds, String value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.setex(key, seconds, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis setex error:", t);
            throw new RedisException("redis setex error");
        } finally {
            j.close();
        }
    }

    public Long setnx(String key, String value) throws RedisException {
        Jedis j = getRedis();
        try {
            return j.setnx(key, value);
        } catch (Throwable t) {
            DushuLogger.error("redis setex error:", t);
            throw new RedisException("redis setex error");
        } finally {
            j.close();
        }
    }

    public String set(byte[] key, byte[] value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.set(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis set error:", t);
            throw new RedisException("redis set error");
        } finally {
            j.close();
        }
    }

    /**
     * <br>
     * Title      : RedisTool<br>
     * Description: <br>
     * Param      : @param key
     * Param      : @param value
     * Param      : @return
     * Param      : @throws RedisException 参数<br>
     * Return     : String 返回类型<br>
     * Throws     : 抛出的异常,有多个用逗号分隔<br>
     */
    public String set(String key, byte[] value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.set(key.getBytes(), value);
            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis set error:", t);
            throw new RedisException("redis set error");
        } finally {
            j.close();
        }
    }

    public String setex(byte[] key, int seconds, byte[] value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.setex(key, seconds, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis setex error:", t);
            throw new RedisException("redis setex error");
        } finally {
            j.close();
        }
    }

    public byte[] get(byte[] key) throws RedisException {
        Jedis j = getRedis();
        byte[] ret = null;
        try {
            ret = j.get(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis get error:", t);
            throw new RedisException("redis get error");
        } finally {
            j.close();
        }
    }

    public List<String> mget(String... keys) throws RedisException {
        Jedis j = getRedis();
        List<String> ret = null;
        try {
            ret = j.mget(keys);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis mget error:", t);
            throw new RedisException("redis mget error");
        } finally {
            j.close();
        }
    }

    public List<byte[]> mget(byte[]... keys) throws RedisException {
        Jedis j = getRedis();
        List<byte[]> ret = null;
        try {
            ret = j.mget(keys);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis mget error:", t);
            throw new RedisException("redis mget error");
        } finally {
            j.close();
        }
    }

    public String mset(String... kvs) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.mset(kvs);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis mset error:", t);
            throw new RedisException("redis mset error");
        } finally {
            j.close();
        }
    }

    //
    // ------------------------------Hash相关命令------------------------------
    //

    /**
     * Hash操作,设置Key指定的Hash集中指定字段的值.
     * <p>
     * 时间复杂度为o(N),其中N是被设置的字段数量.<br>
     * 该命令将重写所有在Hash集中存在字段,如果key指定的Hash集不存在,会创建一个新的Hash集并与key关联
     *
     * @param key   Key键
     * @param value Hash集
     * @return 状态码
     */
    public String hmset(String key, Map<String, String> value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.hmset(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hmset error:", t);
            throw new RedisException("redis hmset error");
        } finally {
            j.close();
        }
    }

    /**
     * Hash操作,设置Key指定的Hash集中指定字段的值.
     * <p>
     * 时间复杂度为o(N),其中N是被设置的字段数量.<br>
     * 该命令将重写所有在Hash集中存在字段,如果key指定的Hash集不存在,会创建一个新的Hash集并与key关联
     *
     * @param key   Key键
     * @param value Hash集
     * @return 状态码
     */
    public String hmset(byte[] key, Map<byte[], byte[]> value) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.hmset(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hmset error:", t);
            throw new RedisException("redis hmset error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取Key对应的Hash集中该字段所关联值的列表.
     * <p>
     * 时间复杂度o(N),其中N是被请求字段的数量<br>
     *
     * @param key    Key值
     * @param fields 指定字段
     * @return 如果存在此字段,则返回所关联的值列表,否则返回空列表.
     */
    public List<String> hmget(String key, String... fields) throws RedisException {
        Jedis j = getRedis();
        List<String> ret = null;
        try {
            ret = j.hmget(key, fields);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hmget error:", t);
            throw new RedisException("redis hmget error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取Key对应的Hash集中该字段所关联的值.
     * <p>
     * 时间复杂度o(1)<br>
     *
     * @param key   Key值
     * @param field 指定字段
     * @return 如果存在此字段,则返回所关联的值,否则返回null
     */
    public String hget(String key, String field) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.hget(key, field);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hmget error:", t);
            throw new RedisException("redis hget error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取Key对应的Hash集中该字段所关联的值.
     * <p>
     * 时间复杂度o(1)<br>
     *
     * @param key   Key值
     * @param field 指定字段
     * @return 如果存在此字段,则返回所关联的值,否则返回null
     */
    public byte[] hget(byte[] key, byte[] field) throws RedisException {
        Jedis j = getRedis();
        byte[] ret = null;
        try {
            ret = j.hget(key, field);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hget error:", t);
            throw new RedisException("redis hget error");
        } finally {
            j.close();
        }
    }

    /**
     * Hash操作,设置Key指定的Hash集中指定字段的值.
     */
    public Long hset(String key, String field, String value) throws RedisException {
        Jedis j = getRedis();
        Long ret = null;
        try {
            ret = j.hset(key, field, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hset error:", t);
            throw new RedisException("redis hset error");
        } finally {
            j.close();
        }
    }

    /**
     * Hash操作,设置Key指定的Hash集中指定字段的值.
     */
    public Long hset(byte[] key, byte[] field, byte[] value) throws RedisException {
        Jedis j = getRedis();
        Long ret = null;
        try {
            ret = j.hset(key, field, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hset error:", t);
            throw new RedisException("redis hset error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取key指定的Hash集中所有的字段和值。
     * <p>
     * 时间复杂度o(N),其中N是Hash集的大小。<br>
     * 使用命令行时请注意:<br>
     * 返回值中,每个字段名的下一个是它的值,所以返回值的长度是Hash集大小的两倍.
     *
     * @param key Key值
     * @return 如果key所对应的Hash集存在,则返回此集合,否则返回空列表.
     */
    public Map<String, String> hgetAll(String key) throws RedisException {
        Jedis j = getRedis();
        Map<String, String> ret = null;
        try {
            ret = j.hgetAll(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hgetAll error:", t);
            throw new RedisException("redis hgetAll error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取key指定的Hash集中所有的字段和值。
     * <p>
     * 时间复杂度o(N),其中N是Hash集的大小。<br>
     * 使用命令行时请注意:<br>
     * 返回值中,每个字段名的下一个是它的值,所以返回值的长度是Hash集大小的两倍.
     *
     * @param key Key值
     * @return 如果key所对应的Hash集存在,则返回此集合,否则返回空列表.
     */
    public Map<byte[], byte[]> hgetAll(byte[] key) throws RedisException {
        Jedis j = getRedis();
        Map<byte[], byte[]> ret = null;
        try {
            ret = j.hgetAll(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hgetAll error:", t);
            throw new RedisException("redis hgetAll error");
        } finally {
            j.close();
        }
    }

    /**
     * 删除Key所对应的Hash集中指定field字段.
     * <p>
     * 时间复杂度 o(N),其中N为要移除字段的数量.<br>
     * 如果指定字段不存在,则忽略处理,如果指定的Hash集不存在,应该指令返回0.<br>
     * 此指令可以返回被成功删除字段的数量,但目前没有需求,就不返回了.
     *
     * @param key   Key值
     * @param field 指定要删除的字段集合
     */
    public Long hdel(String key, String... field) throws RedisException {
        Jedis j = getRedis();
        Long ret = 1L;
        try {
            ret = j.hdel(key, field);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hdel error:", t);
            throw new RedisException("redis hdel error");
        } finally {
            j.close();
        }
    }

    /**
     * 增加Key所对应的Hash集中指定字段的数值.
     * <p>
     * 时间复杂度为o(1)<br>
     * 如果Key不存在,会创建一个新的Hash集并与之关联。<br>
     * 如果指定字段不存在,则字段的值在该操作执行前被设计为0<br>
     * <b>注意:此命令支持的值范围限定在64位 有符号整数<b>
     *
     * @param key   Key值
     * @param field 指定字段
     * @param value 要加的值
     * @return 增值操作执行后该字段的值
     */
    public long hincrBy(String key, String field, long value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.hincrBy(key, field, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis hincrBy error:", t);
            throw new RedisException("redis hincrBy error");
        } finally {
            j.close();
        }
    }

    //
    // ------------------------------List 有序的相关命令------------------------------
    //

    /**
     * 删除列表里最右边的元素。
     * <p>
     *
     * @param key KEY值
     * @return 最右边的元素
     */
    public String rpop(String key) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.rpop(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis rpop error:", t);
            throw new RedisException("redis rpop error");
        } finally {
            j.close();
        }
    }

    /**
     * 获得列表的长度。
     * <p>
     *
     * @param key KEY值
     * @return 成员数量
     */
    public long llen(String key) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.llen(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis llen error:", t);
            throw new RedisException("redis llen error");
        } finally {
            j.close();
        }
    }

    /**
     * 获得列表所有元素。
     * <p>
     *
     * @param key   KEY值
     * @param start 列表起始位置
     * @param end   列表结束位置
     * @return 列表所有元素
     */
    public List<String> lrange(String key, long start, long end) throws RedisException {
        Jedis j = getRedis();
        List<String> ret = null;
        try {
            ret = j.lrange(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lrange error:", t);
            throw new RedisException("redis lrange error");
        } finally {
            j.close();
        }
    }

    public List<byte[]> lrange(byte[] key, int start, int end) throws RedisException {
        Jedis j = getRedis();
        List<byte[]> ret = null;
        try {
            ret = j.lrange(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lrange error:", t);
            throw new RedisException("redis lrange error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回列表key中,小标为index的元素
     * <p>
     *
     * @param key   KEY值
     * @param index VALUE值
     * @return 成员数量
     */
    public String lindex(String key, long index) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.lindex(key, index);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lindex error:", t);
            throw new RedisException("redis lindex error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回列表长度
     * <p>
     *
     * @param key   KEY值
     * @param value VALUE值
     * @param pivot 位于这个值之前或者之后
     * @return 成员数量
     */
    public long linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value)
            throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.linsert(key, where, pivot, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis linsert error:", t);
            throw new RedisException("redis linsert error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回被移除的数量
     * <p>
     *
     * @param key   KEY值
     * @param value VALUE值
     * @return 被移除的数量
     */
    public long lrem(String key, String value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.lrem(key, 1, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lrem error:", t);
            throw new RedisException("redis lrem error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回被移除的数量
     * <p>
     *
     * @param key   KEY值
     * @param count 负数表示从尾部开始
     * @param value VALUE值
     * @return 被移除的数量
     */
    public long lrem(String key, int count, String value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.lrem(key, count, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lrem error:", t);
            throw new RedisException("redis lrem error");
        } finally {
            j.close();
        }
    }

    /**
     * 从列表左边添加一个元素。
     * <p>
     *
     * @param key   KEY值
     * @param value VALUE值
     * @return 成员数量
     */
    public long lpush(String key, String... value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.lpush(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lpush error:", t);
            throw new RedisException("redis lpush error");
        } finally {
            j.close();
        }
    }

    public long lpush(byte[] key, byte[] value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.lpush(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis lpush error:", t);
            throw new RedisException("redis lpush error");
        } finally {
            j.close();
        }
    }

    public long rpush(String key, String... value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.rpush(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis rpush error:", t);
            throw new RedisException("redis rpush error");
        } finally {
            j.close();
        }
    }

    public List<String> blpop(int timeout, String... key) throws RedisException {
        Jedis j = getRedis();
        List<String> ret = null;
        try {
            ret = j.blpop(timeout, key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis blpop error:", t);
            throw new RedisException("redis blpop error");
        } finally {
            j.close();
        }
    }

    public String lpop(String key) throws RedisException {
        Jedis j = getRedis();
        String ret = null;
        try {
            ret = j.lpop(key);
            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis blpop error:", t);
            throw new RedisException("redis blpop error");
        } finally {
            j.close();
        }
    }

    public List<String> brpop(int timeout, String... key) throws RedisException {
        Jedis j = getRedis();
        List<String> ret = null;
        try {
            ret = j.brpop(timeout, key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis blpop error:", t);
            throw new RedisException("redis blpop error");
        } finally {
            j.close();
        }
    }

    /**
     * 修剪到指定范围的列表
     */
    public void ltrim(byte[] key, int start, int end) throws RedisException {
        Jedis j = getRedis();
        try {
            j.ltrim(key, start, end);

        } catch (Throwable t) {
            DushuLogger.error("redis ltrim error:", t);
            throw new RedisException("redis ltrim error");
        } finally {
            j.close();
        }
    }

    //
    // --------------------------------Set相关命令
    // 无序--------------------------------
    //

    /**
     * SADD操作,添加Set类型数据.
     * <p>
     * o(N) 时间复杂度中的N表示操作的成员数量.<br>
     * 如果在插入的过程中,参数中有的成员已存在,该成员将被忽略,其它成员正常插入。<br>
     * 如果执行命令之前,此KEY并不存在,将以此Key创建新的Set
     *
     * @param key   KEY值
     * @param value 成员
     * @return 本次操作实际插入的成员数量
     */
    public long sadd(String key, String value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.sadd(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis sadd error:", t);
            throw new RedisException("redis sadd error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取Key所对应的Set集合里面的所有值
     *
     * @param key KEY值
     * @return Set集中的所有元素
     */
    public Set<String> smembers(String key) throws RedisException {
        Jedis j = getRedis();
        Set<String> ret = null;
        try {
            ret = j.smembers(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis smembers error:", t);
            throw new RedisException("redis smembers error");
        } finally {
            j.close();
        }
    }

    /**
     * 从集合移除元素(如果不存在则忽略)
     *
     * @return 返回成功移除的元素个数
     */
    public long srem(String key, String value) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.srem(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis srem error:", t);
            throw new RedisException("redis srem error");
        } finally {
            j.close();
        }
    }

    /**
     * @return 返回集合的元素个数
     */
    public long scard(String key) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.scard(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis scard error:", t);
            throw new RedisException("redis scard error");
        } finally {
            j.close();
        }
    }

    /**
     * @return 返回元素是否在集合中
     */
    public boolean sismember(String key, String value) throws RedisException {
        Jedis j = getRedis();
        boolean ret = false;
        try {
            ret = j.sismember(key, value);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis sismember error:", t);
            throw new RedisException("redis sismember error");
        } finally {
            j.close();
        }
    }

    /**
     * 将元素从一个集合移动到另一个集合
     *
     * @return 成功移动,返回1 没有任何操作,返回0
     */
    public long smove(String srckey, String dstkey, String member) throws RedisException {
        Jedis j = getRedis();
        long ret = 0;
        try {
            ret = j.smove(srckey, dstkey, member);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis smove error:", t);
            throw new RedisException("redis smove error");
        } finally {
            j.close();
        }
    }

    //
    // ------------------------------Sorted set相关命令
    // 有序---------------------------
    //

    /**
     * 添加指定成员到Key对应的Set集合中.
     * <p>
     * 时间复杂度o(log(N)) N为Set集合中的元素个数<br>
     * 每一个成员都有一个分数值,如果指定成员存在,那么其分数就会被更新成最新的。<br>
     * 如果不存在,则会创建一个新的。
     *
     * @param key    KEY值
     * @param score  分数值
     * @param member 指定成员
     * @return 返回添加到Set集合中的元素个数,不包括那种已存在只更新的分数的元素。
     */
    public long zadd(String key, double score, String member) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.zadd(key, score, member);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zadd error:", t);
            throw new RedisException("redis zadd error");
        } finally {
            j.close();
        }
    }

    public long zadd(String key, Map<String, Double> map) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.zadd(key, map);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zadd error:", t);
            throw new RedisException("redis zadd error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取指定Key的Set集合中成员member的排名。
     * <p>
     * 其中Set集合成员按score值递增(由小到大)排列。<br>
     * <b>注意:排名以0为底,也就是说score值最小的成员排名为0.</b>
     *
     * @param key    KEY值
     * @param member 指定成员
     * @return 如果member是key对应Set集合中的成员,则返回member的排名值。
     */
    public Long zrank(String key, String member) throws RedisException {
        Jedis j = getRedis();
        Long ret = null;
        try {
            ret = j.zrank(key, member);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrank error:", t);
            throw new RedisException("redis zrank error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取指定Key的Set集合中成员member的排名。
     * <p>
     * 其中Set集合成员按score值递增(由小到大)排列。<br>
     * <b>注意:排名以0为底,也就是说score值最小的成员排名为0.</b>
     *
     * @param key    KEY值
     * @param member 指定成员
     * @return 如果member是key对应Set集合中的成员,则返回member的排名值。
     */
    public Long zrevrank(String key, String member) throws RedisException {
        Jedis j = getRedis();
        Long ret = null;
        try {
            ret = j.zrevrank(key, member);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrevrank error:", t);
            throw new RedisException("redis zrevrank error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取指定Key对应的Set集合中指定区间内的成员。
     * <p>
     * 其中成员按Score值递增来排序,具有相同值的成员按字典序来排列.<br>
     *
     * @param key   KEY值
     * @param start 开始下标 rank
     * @param end   结束下标 rank
     * @return 如果指定区间有成员,则返回此区间的成员集合.
     */
    public Set<String> zrange(String key, long start, long end) throws RedisException {
        Jedis j = getRedis();
        Set<String> ret = null;
        try {
            ret = j.zrange(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrange error:", t);
            throw new RedisException("redis zrange error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取指定Key对应的Set集合中指定区间内的成员。
     * <p>
     * 其中成员按Score值递减来排序,具有相同值的成员按字典序来排列.<br>
     *
     * @param key   KEY值
     * @param start 开始下标 rank
     * @param end   结束下标 rank
     * @return 如果指定区间有成员,则返回此区间的成员集合.
     */
    public Set<String> zrevrange(String key, long start, long end) throws RedisException {
        Jedis j = getRedis();
        Set<String> ret = null;
        try {
            ret = j.zrevrange(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrevrange error:", t);
            throw new RedisException("redis zrevrange error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取指定Key对应的Set集合中指定分数的成员。
     *
     * @param key KEY值
     * @param min 最小值 score
     * @param max 最大值 score
     * @return 如果指定区间有成员,则返回此区间的成员集合.
     */
    public Set<String> zrangeByScore(String key, double min, double max) throws RedisException {
        Jedis j = getRedis();
        Set<String> ret = null;
        try {
            ret = j.zrangeByScore(key, min, max);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrangeByScore error:", t);
            throw new RedisException("redis zrangeByScore error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回指定分数区间的元素集合(包括min和max) 按照分数从大到小排序
     *
     * @param key KEY值
     * @param min 最小值 score
     * @param max 最大值 score
     * @return 如果指定区间有成员,则返回此区间的成员集合.
     */
    public Set<String> zrevrangeByScore(String key, double min, double max) throws RedisException {
        Jedis j = getRedis();
        try {
            Set<String> ret = j.zrevrangeByScore(key, min, max);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrevrangeByScore error:", t);
            throw new RedisException("redis zrevrangeByScore error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回指定排名区间的元素集合(按照score从大到小排序)
     *
     * @param start 开始下标 rank
     * @param end   结束下标 rank
     */
    public Set<Tuple> zrevrangeWithScore(String key, int start, int end) throws RedisException {
        Jedis j = getRedis();
        try {
            Set<Tuple> ret = j.zrevrangeWithScores(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrevrangeWithScore error:", t);
            throw new RedisException("redis zrevrangeWithScore error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回指定排名区间的元素集合(按照score从小到大排序)
     *
     * @param start 开始下标 rank
     * @param end   结束下标 rank
     */
    public Set<Tuple> zrangeWithScore(String key, int start, int end) throws RedisException {
        Jedis j = getRedis();
        try {
            Set<Tuple> ret = j.zrangeWithScores(key, start, end);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrangeWithScore error:", t);
            throw new RedisException("redis zrangeWithScore error");
        } finally {
            j.close();

        }
    }

    /**
     * 获取指定Key的Set集合中成员member的值。
     *
     * @param key    KEY值
     * @param member 指定成员
     * @return 如果member是key对应Set集合中的成员,则返回member的分数。
     */
    public long zscore(String key, String member) throws RedisException {
        Jedis j = getRedis();
        try {
            Double ret = j.zscore(key, member);

            if (ret == null)
                return 0L;
            return ret.longValue();
        } catch (Throwable t) {
            DushuLogger.error("redis zscore error:", t);
            throw new RedisException("redis zscore error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回key对应的Set集合中指定分数区间成员的个数。
     * <p>
     * 注意: min <= 此分数值 <= max
     *
     * @param key KEY值
     * @param min 分数值下限
     * @param max 分数值上限
     * @return 成员数量
     */
    public long zcount(String key, double min, double max) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.zcount(key, min, max);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zcount error:", t);
            throw new RedisException("redis zcount error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回key对应的Set集合中成员的个数。
     * <p>
     *
     * @param key KEY值
     * @return 成员数量
     */
    public long zcount(String key) throws RedisException {
        Jedis j = getRedis();
        long ret = 0L;
        try {
            ret = j.zcount(key, "-inf", "+inf");

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zcount error:", t);
            throw new RedisException("redis zcount error");
        } finally {
            j.close();
        }
    }

    /**
     * 删除指定Key对应的Set集合中指定的成员。
     * <p>
     *
     * @param key     KEY值
     * @param members 指定的成员
     * @return 返回被删除的元素的个数
     */
    public long zrem(String key, String... members) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.zrem(key, members);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zrem error:", t);
            throw new RedisException("redis zrem error");
        } finally {
            j.close();
        }
    }

    /**
     * 移除排名在start和stop(包含start,stop)在内的所有元素
     *
     * @return 返回移除元素的个数
     */
    public long zremrangeByRank(String key, int start, int stop) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.zremrangeByRank(key, start, stop);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zremrangeByRank error:", t);
            throw new RedisException("redis zremrangeByRank error");
        } finally {
            j.close();
        }
    }

    /**
     * 移除分数在min和max(包含min,max)在内的所有元素
     *
     * @return 返回移除元素的个数
     */
    public long zremrangeByScore(String key, double min, double max) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.zremrangeByScore(key, min, max);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zremrangeByScore error:", t);
            throw new RedisException("redis zremrangeByScore error");
        } finally {
            j.close();
        }
    }

    /**
     * 返回key对应的Set集合中成员的个数。
     * <p>
     *
     * @param key KEY值
     * @return 成员数量
     */
    public long zcard(String key) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.zcard(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zcard error:", t);
            throw new RedisException("redis zcard error");
        } finally {
            j.close();
        }
    }

    /**
     * 增加指定元素的分数
     *
     * @return 指定元素新的分数值
     */
    public double zincrby(String key, double increment, String member) throws RedisException {
        Jedis j = getRedis();
        try {
            double ret = j.zincrby(key, increment, member);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis zincrby error:", t);
            throw new RedisException("redis zincrby error");
        } finally {
            j.close();
        }
    }

    // ------------------------------------------订阅/发布------------------------------------

    /**
     * 将信息 message 发送到指定的频道 channel 。
     *
     * @return 接收到信息 message 的订阅者数量。
     * @version >= 2.0.0 时间复杂度: O(N+M),其中 N 是频道channel 的订阅者数量,而 M
     * 则是使用模式订阅(subscribed patterns)的客户端的数量。
     */
    public long publish(String channel, String message) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.publish(channel, message);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis publish error:", t);
            throw new RedisException("redis publish error");
        } finally {
            j.close();
        }
    }

    /**
     * 清空当前数据库里的所有数据,这个命令永远不会失败,使用时请注意加小心。
     */
    public void flushDB() throws RedisException {
        Jedis j = getRedis();
        try {
            j.flushDB();

        } catch (Throwable t) {
            DushuLogger.error("redis flushDB error:", t);
            throw new RedisException("redis flushDB error");
        } finally {
            j.close();
        }
    }

    /**
     * 获取当前数据库里的Keys的数量.
     *
     * @return Keys的数量
     */
    public long dbSize() throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.dbSize();

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis dbSize error:", t);
            throw new RedisException("redis dbSize error");
        } finally {
            j.close();
        }
    }

    /**
     * <br>
     * Title      : RedisTool<br>
     * Description: redis 原子增减<br>
     * Param      : @param key
     * Param      : @return
     * Param      : @throws RedisException 参数<br>
     * Return     : long 返回类型<br>
     * Throws     : 抛出的异常,有多个用逗号分隔<br>
     */
    public long incr(String key) throws RedisException {
        Jedis j = getRedis();
        try {
            long ret = j.incr(key);

            return ret;
        } catch (Throwable t) {
            DushuLogger.error("redis dbSize error:", t);
            throw new RedisException("redis dbSize error");
        } finally {
            j.close();
        }
    }
}

四、小结

      通过这次接触,感觉就是只有接触了才会知道怎么做,才会知道如何优化。redis使用了才会有更深刻的印象。

;