Java游戏服务器开发之二十二--使用Jedis访问redis数据库.md

Posted by lizhao on 07-09,2019

Java游戏服务器开发之二十二--使用Jedis访问redis数据库

介绍

Redis是一个远程数据结构服务器。它肯定比将数据存储在本地内存中要慢(因为它涉及套接字往返存取数据)。但是,它也带来了一些有趣的属性:

  • Redis可以被应用程序的所有进程访问,可能运行在多个节点上(本地内存无法实现)。
  • Redis内存存储非常高效,并在单独的过程中完成。如果应用程序在内存被垃圾收集的平台上运行(node.js,java等),它允许处理更大的内存缓存/存储。在实践中,非常大的堆用垃圾收集语言表现不佳。 如果需要,Redis可以将数据保存在磁盘上。
  • Redis不仅仅是一个简单的缓存:它提供了各种数据结构,各种项目驱逐策略,阻塞队列,pub / sub,原子性,Lua脚本等等。
  • Redis可以使用主/从机制来复制其活动,以实现高可用性。

基本上,如果需要你的应用程序在共享相同数据的多个节点上进行扩展,则需要类似Redis(或任何其他远程键/值存储)。

简单使用

redis快速上手使用 https://blog.csdn.net/cmqwan/article/details/81481522

Jedis

  • Jedis是对redis的一层封装,把一些常用方法封装好了。
  • JedisPool是jedis的连接池。
    • 看下JedisPool的构造方法的参数
      • @param poolConfig 连接池设置
      • @param host 主机
      • @param port 端口
      • @param timeout 超时
      • @param password 密码
      • @param databaseIndex 数据库 -- Jedis有哪些方法

需要引入的包

<!-- redis start -->
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.8.3</version>
    </dependency>
    <!--上面已经添加了-->
    <!--<dependency>-->
    <!--<groupId>org.springframework.data</groupId>-->
    <!--<artifactId>spring-data-redis</artifactId>-->
    <!--<version>1.7.1.RELEASE</version>-->
    <!--</dependency>-->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.8.1</version>
    </dependency>
    <!-- redis end -->

关键代码

我们使用就是在JedisPool上进行操作,主要是这么几个方法

构造线程池

  /**
   * 创建一个redis连接池
   *
   * @param poolConfig    连接池设置
   * @param host          主机
   * @param port          端口
   * @param timeout       超时
   * @param password      密码
   * @param databaseIndex 数据库
   */
  public void createJedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, int timeout,
          final String password, final int databaseIndex) {
    pool = new JedisPool(poolConfig, host, port, timeout, password, databaseIndex);
  }

从线程池中获取Jedis

 /**
   * 获取Jedis对象
   *
   * @return Jedis
   */
  public synchronized Jedis getJedis() {
    Jedis jedis = null;
    if (pool != null) {
      if (jedis == null) {
        try {
          jedis = pool.getResource();
        } catch (Exception e) {
          logger.debug("Jedis getJedis find error", e);
        }
      }
    }
    return jedis;
  }

使用jedis进行读写

  /**
   * 从高到低排名,返回前 num 个
   *
   * @param key 键
   * @param num 数量
   * @return  Set
   */
  public Set<String> ztop(String key, int num) {
    if (num <= 0) {
      return Collections.emptySet();
    }
    Jedis jedis = getJedis();
    Set<String> ret = jedis.zrevrange(key, 0, num - 1);
    jedis.close();
    return ret;
  }

测试方法

/*
 * Copyright (C), 2015-2018
 * FileName: RedisTest
 * Author:   zhao
 * Date:     2018/8/6 16:00
 * Description: Redis的测试类
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lizhaoblog.base.redis;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import redis.clients.jedis.JedisPoolConfig;

/**
 * 〈一句话功能简述〉<br>
 * 〈Redis的测试类〉
 * 〈Redis工具,从<<Java游戏服务器开发>>一书中获取〉
 *
 * @author zhao
 * @date 2018/8/6 16:00
 * @see Redis
 * @since 1.0.1
 */
public class RedisTest {
  private static final Logger logger = LoggerFactory.getLogger(RedisTest.class);

  @Test
  public void test() {
    String host = "127.0.0.1";
    int port = 6379;
    int timeout = 2000;
    String password = "admin123";
    int databaseIndex = 16;
    logger.info("Redis at {}:{}", host, port);

    JedisPoolConfig poolConfig = new JedisPoolConfig();
    //设置最大连接数(100个足够用了,没必要设置太大)
    poolConfig.setMaxTotal(100);
    //最大空闲连接数
    poolConfig.setMaxIdle(10);
    //获取Jedis连接的最大等待时间(50秒)
    poolConfig.setMaxWaitMillis(50 * 1000);
    //在获取Jedis连接时,自动检验连接是否可用
    poolConfig.setTestOnBorrow(false);
    //在将连接放回池中前,自动检验连接是否有效
    poolConfig.setTestOnReturn(true);
    //自动测试池中的空闲连接是否都是可用连接
    poolConfig.setTestWhileIdle(true);

    Redis redis = Redis.getInstance();
    redis.createJedisPool(poolConfig, host, port, timeout, password, databaseIndex);

    /** redis save **/
    logger.info("=============redis save==============");
    // string save
    logger.info("string save:调用set时,若key不存在则添加key,否则为修改key对应的值");
    redis.set("testKey1", "test string val1");
    // set save
    logger.info("set save:set中的元素不允许出现重复且无序");
    redis.sadd("testKey2", "test set val1");
    redis.sadd("testKey2", "test set val2");
    redis.sadd("testKey2", "test set val3");
    // hash save
    logger.info("hash save:调用hset时,若key不存在则创建key,若hash中存在这个hashkey,则修改其值,不存在则添加一条hash数据");
    redis.hset("testKey3", "hashKey1", "hashVal1");
    redis.hset("testKey3", "hashKey2", "hashVal2");
    redis.hset("testKey3", "hashKey3", "hashVal3");
    redis.hset("testKey3", "hashKey4", "hashVal4");
    // list save
    logger.info("list save:数据在链表中是有序的,并可以重复添加数据");
    redis.lpush("testKey4", "test list val1");
    redis.lpush("testKey4", "test list val2");
    redis.lpush("testKey4", "test list val3");
    // sorted set save
    logger.info("sorted set save:有序set中的元素是有序的");
    redis.zadd("testKey5", 1, "test zset val1");
    redis.zadd("testKey5", 2, "test zset val2");
    redis.zadd("testKey5", 3, "test zset val3");
    redis.zadd("testKey5", 4, "test zset val4");
    /** redis get **/
    logger.info("=============redis get==============");
    // string get
    String stringRet = redis.get("testKey1");
    logger.info("string get:" + stringRet);
    // set get
    Set<String> setRet = redis.sget("testKey2");
    logger.info("set get:");
    for (String string : setRet) {
      logger.info(string + ",");
    }
    // hash get
    String hashKeyRet = redis.hget("testKey3", "hashKey2");
    logger.info("hash key get:" + hashKeyRet);
    Map<String, String> hashRet = redis.hgetAll("testKey3");
    logger.info("hash get:");
    for (String string : hashRet.keySet()) {
      logger.info("key[" + string + "]" + "value[" + hashRet.get(string) + "],");
    }
    // list get
    List<String> listRet = redis.lgetList("testKey4");
    logger.info("list get:");
    for (String string : listRet) {
      logger.info(string + ",");
    }
    // zset get
    long val2Rank = redis.zrank("testKey5", "test zset val2");
    logger.info("zset get val2 rank:" + val2Rank);
    Set<String> zsetRet = redis.zrange("testKey5", 0, 3);
    logger.info("zset get range:");
    for (String string : zsetRet) {
      logger.info(string + ",");
    }
    /** redis delete **/
    logger.info("=============redis delete==============");
    // string delete
    logger.info("string delete:调用Redis的del方法,可直接删除key,对于所有的数据类型来说,都可以通过这种方式直接删除整个key");
    redis.del("testKey1");
    // set delete
    logger.info("set delete:删除set中的val3");
    redis.sremove("testKey2", "test set val3");
    // hash delete
    logger.info("hash delete:删除hash中key为hashKey4的元素");
    redis.hdel("testKey3", "hashKey4");
    // list delete
    logger.info("list delete:删除list中值为test list val3的元素,其中count参数,0代表删除全部,正数代表正向删除count个此元素,负数代表负向删除count个此元素");
    redis.lrem("testKey4", 0, "test list val3");
    // zset delete
    logger.info("zset delete:同set删除元素的方式相同");
    redis.zrem("testKey5", "test zset val4");
    logger.info("除了以上常用api之外,还有更多api,在Redis类中都有列出,请参考Redis类,或直接参照Jedis的官方文档");
  }

}

工具类完整代码

/*
 * Copyright (C), 2015-2018
 * FileName: Redis
 * Author:   zhao
 * Date:     2018/8/4 10:30
 * Description: Redis工具
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lizhaoblog.base.redis;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Tuple;

/**
 * 〈一句话功能简述〉<br>
 * 〈Redis工具,从<<Java游戏服务器开发>>一书中获取〉
 * <具体简单入门可以查看:https://blog.csdn.net/cmqwan/article/details/81481522>
 *
 * @author zhao
 * @date 2018/8/4 10:30
 * @since 1.0.1
 */
public class Redis {
  private static Redis instance;
  private static final Logger logger = LoggerFactory.getLogger(Redis.class);

  private JedisPool pool = null;

  public static Redis getInstance() {
    if (instance == null) {
      instance = new Redis();
    }
    return instance;
  }

  /**
   * 创建一个redis连接池
   *
   * @param poolConfig    连接池设置
   * @param host          主机
   * @param port          端口
   * @param timeout       超时
   * @param password      密码
   * @param databaseIndex 数据库
   */
  public void createJedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, int timeout,
          final String password, final int databaseIndex) {
    pool = new JedisPool(poolConfig, host, port, timeout, password, databaseIndex);
  }

  /**
   * 获取Jedis对象
   *
   * @return Jedis
   */
  public synchronized Jedis getJedis() {
    Jedis jedis = null;
    if (pool != null) {
      if (jedis == null) {
        try {
          jedis = pool.getResource();
        } catch (Exception e) {
          logger.debug("Jedis getJedis find error", e);
        }
      }
    }
    return jedis;
  }

  public Map<String, String> hgetAll(String key) {
    if (key == null) {
      return null;
    }
    Jedis jedis = getJedis();
    //

    Map<String, String> ret = jedis.hgetAll(key);
    jedis.close();
    return ret;
  }

  public static Map<String, String> objectToHash(Object obj)
          throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Map<String, String> map = new HashMap<String, String>();
    BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
    PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
    for (PropertyDescriptor property : propertyDescriptors) {
      if (!"class".equals(property.getName())) {
        map.put(property.getName(), "" + property.getReadMethod().invoke(obj));
      }
    }
    return map;
  }

  public static void hashToObject(Map<?, ?> map, Object obj) throws IllegalAccessException, InvocationTargetException {
    for (Map.Entry<?, ?> entry : map.entrySet()) {
      if ("null".equals(entry.getValue())) {
        entry.setValue(null);
      }
    }
    BeanUtils.populate(obj, (Map) map);
  }

  @SuppressWarnings("unchecked")
  public static <T> T hashToObject(Map<?, ?> map, Class c)
          throws IllegalAccessException, InvocationTargetException, InstantiationException {
    Object obj = c.newInstance();
    hashToObject(map, obj);
    return (T) obj;
  }

  public List<String> hmget(String key, String... fields) {
    Jedis jedis = getJedis();

    List<String> ret = jedis.hmget(key, fields);

    jedis.close();
    return ret;
  }

  public String hmset(String key, Object object)
          throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
    Jedis jedis = getJedis();

    String ret = jedis.hmset(key, objectToHash(object));
    jedis.close();
    return ret;
  }

  public String hmset(String key, Map<String, String> fields)
          throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
    Jedis jedis = getJedis();

    String ret = jedis.hmset(key, fields);
    jedis.close();
    return ret;
  }

  public boolean hexist(String key, String field) {
    if (key == null) {
      return false;
    }
    Jedis jedis = getJedis();

    boolean ret = jedis.hexists(key, field);
    jedis.close();
    return ret;
  }

  public Long hdel(String key, String... fields) {
    Jedis jedis = getJedis();

    Long cnt = jedis.hdel(key, fields);
    jedis.close();
    return cnt;
  }

  public String hget(String key, String field) {
    if (key == null) {
      return null;
    }
    Jedis jedis = getJedis();

    String ret = jedis.hget(key, field);
    jedis.close();
    return ret;
  }

  public void hset(String key, String field, String value) {
    if (field == null || field.length() == 0) {
      return;
    }
    if (value == null || value.length() == 0) {
      return;
    }
    Jedis jedis = getJedis();

    jedis.hset(key, field, value);
    jedis.close();
  }

  /**
   * Map 的存放和获取
   */
  public void add(String group, Map<String, String> values) {
    if (values == null || values.size() == 0) {
      return;
    }
    Jedis jedis = getJedis();

    jedis.hmset(group, values);
    jedis.close();
  }

  public void add(String group, String key, String value) {
    if (value == null || key == null) {
      return;
    }
    Jedis jedis = getJedis();

    jedis.hset(group, key, value);
    jedis.close();
  }

  public void set(String key, String value) {
    if (value == null || key == null) {
      return;
    }
    Jedis jedis = getJedis();
    jedis.set(key, value);
    jedis.close();
  }

  public Long hDelBuilder(String group, String... keys) {
    Jedis jedis = getJedis();

    byte[][] fields = new byte[keys.length][];
    for (int i = 0; i < keys.length; i++) {
      fields[i] = keys[i].getBytes();
    }
    Long cnt = jedis.hdel(group.getBytes(), fields);
    jedis.close();
    return cnt;
  }

  public Map<String, String> getMap(String group) {
    Jedis jedis = getJedis();
    Map<String, String> ret = jedis.hgetAll(group);
    jedis.close();
    return ret;
  }

  public String get(String key) {
    Jedis jedis = getJedis();
    String ret = jedis.get(key);
    jedis.close();
    return ret;
  }

  /**
   * 添加元素到集合中
   *
   * @param key
   * @param element
   */
  public boolean sadd(String key, String... element) {
    if (element == null || element.length == 0) {
      return false;
    }
    Jedis jedis = getJedis();
    boolean success = jedis.sadd(key, element) == 1;
    jedis.close();
    return success;
  }

  public boolean smove(String oldKey, String newKey, String element) {
    if (element == null) {
      return false;
    }
    Jedis jedis = getJedis();
    boolean success = (jedis.smove(oldKey, newKey, element) == 1);
    jedis.close();
    return success;
  }

  /**
   * 删除指定set内的元素
   */
  public boolean sremove(String key, String... element) {
    if (element == null) {
      return false;
    }
    Jedis jedis = getJedis();
    boolean success = (jedis.srem(key, element) == 1);
    jedis.close();
    return success;
  }

  public Set<String> sget(String key) {
    Jedis jedis = getJedis();
    Set<String> m = jedis.smembers(key);
    jedis.close();
    return m;
  }

  /**
   * 返回set的的元素个数
   *
   * @param key
   * @return
   * @Title: zcard
   
   */
  public long scard(String key) {
    Jedis jedis = getJedis();
    long size = jedis.scard(key);
    jedis.close();
    return size;
  }

  public void laddList(String key, String... elements) {
    if (elements == null || elements.length == 0) {
      return;
    }
    Jedis jedis = getJedis();
    jedis.lpush(key, elements);
    jedis.close();
  }

  /**
   * @param key
   * @param id
   * @Title: lpush
   
   */
  public void lpush(String key, String id) {
    Jedis jedis = getJedis();
    jedis.lpush(key, id);
    jedis.close();
  }

  public void rpush(String key, String id) {
    Jedis jedis = getJedis();
    jedis.rpush(key, id);
    jedis.close();
  }

  /**
   * add by wangzhuan
   *
   * @param key
   * @param start
   * @param end
   * @return
   * @Title: lrange
   
   */
  public List<String> lrange(String key, int start, int end) {
    Jedis jedis = getJedis();
    List<String> list = jedis.lrange(key, start, end);
    jedis.close();
    return list;
  }

  public List<String> lgetList(String key) {
    Jedis jedis = getJedis();
    long len = jedis.llen(key);
    List<String> ret = jedis.lrange(key, 0, len - 1);
    jedis.close();
    return ret;
  }

  /**
   * 列表list中是否包含value
   *
   * @param key
   * @param value
   * @return
   */
  public boolean lexist(String key, String value) {
    List<String> list = lgetList(key);
    return list.contains(value);
  }

  public List<String> lgetList(String key, long len) {
    Jedis jedis = getJedis();
    long max = jedis.llen(key);
    long l = max > len ? len : max;
    List<String> ret = jedis.lrange(key, 0, l - 1);
    jedis.close();
    return ret;
  }

  public Long del(String key) {
    Jedis jedis = getJedis();
    Long cnt = jedis.del(key);
    jedis.close();
    return cnt;
  }

  /**
   * 模糊删除
   *
   * @param key
   * @return
   */
  public Long delKeyLikes(String key) {
    Jedis jedis = getJedis();
    Set<String> keys = jedis.keys(key);
    Long cnt = jedis.del(keys.toArray(new String[keys.size()]));
    jedis.close();
    return cnt;
  }

  /**
   * 测试元素是否存在
   *
   * @param key
   * @param element
   * @return
   */
  public boolean sexist(String key, String element) {
    Jedis jedis = getJedis();
    boolean ret = jedis.sismember(key, element);
    jedis.close();
    return ret;
  }

  /**
   * 判断某一个key值得存储结构是否存在
   *
   * @param key
   * @return
   * @Title: exist
   
   */
  public boolean exist(String key) {
    Jedis jedis = getJedis();
    boolean yes = jedis.exists(key);
    jedis.close();
    return yes;
  }

  /**********************************************************************
   * 排行用到的SortedSet
   **********************************************************************/
  public long zadd(String key, int score, String member) {
    Jedis jedis = getJedis();
    long ret = 0;
    try {
      ret = jedis.zadd(key, score, member);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    } finally {
      jedis.close();
    }
    return ret;
  }

  /**
   * 添加 分数,并返回修改后的值
   *
   * @param key
   * @param update
   * @param member
   * @return
   */
  public double zincrby(String key, int update, String member) {
    Jedis jedis = getJedis();
    double ret = jedis.zincrby(key, update, member);
    jedis.close();
    return ret;
  }

  /**
   * 返回有序集 key 中,成员 member 的 score 值,存在返回score,不存在返回-1
   *
   * @param key
   * @param member
   * @return
   */
  public double zscore(String key, String member) {
    Jedis jedis = getJedis();
    Double ret = jedis.zscore(key, member);
    jedis.close();
    if (ret == null) {
      return -1;
    }
    return ret;
  }

  /**
   * 按 从大到小的排名,获取 member的 排名
   *
   * @param key
   * @param member
   * @return
   */
  public long zrevrank(String key, String member) {
    Jedis jedis = getJedis();
    long ret = jedis.zrevrank(key, member);
    jedis.close();
    return ret;
  }

  /**
   * 按照score的值从小到大排序,返回member的排名 排序是从0开始
   *
   * @param key
   * @param member
   * @return 设置为名次从1开始。返回为-1,表示member无记录
   * @Title: zrank
   
   */
  public long zrank(String key, String member) {
    Jedis jedis = getJedis();
    long ret = -1;
    Long vv = jedis.zrank(key, member);
    if (vv != null) {
      ret = vv.longValue();
    }
    jedis.close();
    if (ret != -1) {
      ret += 1;
    }
    return ret;
  }

  /**
   * 返回的是score的值
   *
   * @param key
   * @param member
   * @return 返回有序集 key 中,成员 member 的 score 值 如果 member 元素不是有序集 key 的成员,或 key
   * 不存在,返回 null 。
   * @Title: zscore
   
   */
  public int zscoreDouble(String key, String member) {
    Jedis jedis = getJedis();
    int ret = -1;
    Double vv = jedis.zscore(key, member);
    if (vv != null) {
      ret = (int) vv.doubleValue();
    }
    jedis.close();
    if (ret != -1) {
      ret += 1;
    }
    return ret;
  }

  /**
   * min 和max 都是score的值
   *
   * @param key
   * @param min
   * @param max
   * @return
   * @Title: zrangebyscore
   
   */
  // add 20141216
  public Set<String> zrangebyscore(String key, long min, long max) {
    Jedis jedis = getJedis();
    Set<String> ss = jedis.zrangeByScore(key, min, max);
    jedis.close();
    return ss;
  }

  public Set<String> zrange(String key, long min, long max) {
    Jedis jedis = getJedis();
    Set<String> ss = jedis.zrange(key, min, max);
    jedis.close();
    return ss;
  }

  /**
   * min 和max 都是score的值 获得一个包含了score的元组集合. 元组(Tuple)
   * 笛卡尔积中每一个元素(d1,d2,…,dn)叫作一个n元组(n-tuple)或简称元组
   *
   * @param key
   * @param min
   * @param max
   * @return
   * @Title: zrangebyscorewithscores
   
   */
  public Set<Tuple> zrangebyscorewithscores(String key, long min, long max) {
    Jedis jedis = getJedis();
    Set<Tuple> result = null;
    try {
      result = jedis.zrangeByScoreWithScores(key, min, max);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    } finally {
      jedis.close();
    }
    return result;
  }

  /**
   * zrevrangeWithScores : 从大到小排序 zrangeWithScores : 从小到大排序
   *
   * @param key
   * @param start : (排名)0表示第一个元素,-x:表示倒数第x个元素
   * @param end   : (排名)-1表示最后一个元素(最大值)
   * @return 返回 排名在start 、end之间带score元素
   
   
   */
  public Map<String, Double> zrevrangeWithScores(String key, long start, long end) {
    Jedis jedis = getJedis();
    Set<Tuple> result = null;
    try {
      result = jedis.zrevrangeWithScores(key, start, end);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    } finally {
      jedis.close();
    }
    return tupleToMap(result);
  }

  /**
   * @param tupleSet  一个set
   * @return Map<String<element, score>
   */
  public Map<String, Double> tupleToMap(Set<Tuple> tupleSet) {
    if (tupleSet == null) {
      return null;
    }
    Map<String, Double> map = new LinkedHashMap<String, Double>();
    for (Tuple tup : tupleSet) {
      map.put(tup.getElement(), tup.getScore());
    }
    return map;
  }

  /**
   * 删除key中的member
   *
   * @param key 键
   * @param member  值
   * @return  结果
   */
  public long zrem(String key, String member) {
    Jedis jedis = getJedis();
    long result = -1;
    try {
      result = jedis.zrem(key, member);
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    } finally {
      jedis.close();
    }
    return result;
  }

  /**
   * 从高到低排名,返回前 num 个score和member
   *
   * @param key 根据某个key
   * @param num 前面第n个
   * @return  返回一个set
   */
  public Set<Tuple> ztopWithScore(String key, int num) {
    if (num <= 0) {
      return Collections.emptySet();
    }
    Jedis jedis = getJedis();
    Set<Tuple> ret = jedis.zrevrangeWithScores(key, 0, num - 1);
    jedis.close();
    return ret;
  }

  /**
   * 返回score区间的member
   *
   * @param key 键
   * @param max 最大值
   * @param min 最小值
   * @return  一个区间set
   */
  public Set<String> zrankByScore(String key, int max, int min) {
    Jedis jedis = getJedis();
    Set<String> ret = jedis.zrevrangeByScore(key, max, min);
    jedis.close();
    return ret;
  }

  /**
   * 从高到低排名,返回前 num 个
   *
   * @param key 键
   * @param num 数量
   * @return  Set
   */
  public Set<String> ztop(String key, int num) {
    if (num <= 0) {
      return Collections.emptySet();
    }
    Jedis jedis = getJedis();
    Set<String> ret = jedis.zrevrange(key, 0, num - 1);
    jedis.close();
    return ret;
  }

  /**
   * 从高到低排名,返回start到end的前 num 个
   *
   * @param key 排序方式
   * @return set
   */
  public Set<String> ztop(String key, int start, int end) {
    if (end <= start) {
      return Collections.emptySet();
    }
    Jedis jedis = getJedis();
    Set<String> ret = jedis.zrevrange(key, start, end - 1);
    jedis.close();
    return ret;
  }

  public long zcard(String key) {
    Jedis jedis = getJedis();
    long size = jedis.zcard(key);
    jedis.close();
    return size;
  }

  public static void destroy() {
    getInstance().pool.destroy();
  }

  public void publish(String channel, String message) {
    if (channel == null || message == null) {
      return;
    }
    Jedis jedis = getJedis();
    jedis.publish(channel, message);
    jedis.close();
  }

  public String lpop(String key) {
    Jedis jedis = getJedis();
    String value = jedis.lpop(key);
    jedis.close();
    return value;
  }

  public void lrem(String key, int count, String value) {
    Jedis jedis = getJedis();
    jedis.lrem(key, count, value);
    jedis.close();
  }

}