Redis部署方式(二)单机版安装与代码集成_redis集成-程序员宅基地

技术标签: redis  

一、linux安装redis步骤:

1、下载redis压缩包

wget http://download.redis.io/redis-stable.tar.gz 

2、然后解压压缩文件

tar -xzvf redis-stable.tar.gz

3、安装:

分别执行:

cd redis-stable
make
cd src
make install PREFIX=/usr/local/redis

注:执行make时候遇到报错server.c:xxxx:xx: error: ‘xxxxxxxx’ has no member named ‘xxxxx’,参见 安装redis-6.0.1报错server.c:xxxx:xx: error: ‘xxxxxxxx’ has no member named ‘xxxxx’_hello_cmy的博客-程序员宅基地

安装成功后生成bin目录,bin目录下是一些可执行文件:

3.1、redis-server:

启动Redis,使用/redis-server启动redis.conf配置文件

cd /usr/local/redis/bin 
./redis-server /xxx/xx/redis.conf 
3.2、redis-cli:

Redis命令行客户端(Client)

cd /usr/local/redis/bin 
./redis-cli 

即进入命令终端

选项
默认值
说明
对应配置项

redis.conf

-h <hostname> 127.0.0.1

以哪个主机名/IP登录Redis

如果某个IP没在conf文件中绑定,那就不能用它登录

bind
-p <port> 6379 服务器端口号 port
-a <password>

连接密码

当conf中指定了requirepass,登录时就需要-a

requirepass
-r n 重复执行某个命令n次
-c 启动集群cluster模式
--raw 以原始样式将结果输出到屏幕上
--csv 以CSV样式输出结果
--rdb 路径 导出rdb到本地

-v

--version

版本

如果设置了密码(requirepass),则

[root@172 bin]# ./redis-cli -p 6379
127.0.0.1:6379> auth 你的密码
OK
127.0.0.1:6379>
3.3、redis-sentinel:

哨兵模式启动工具。

3.4、redis-benchmark:

Redis基准测试工具

3.5、redis-check-aof:

AOF持久化文件检测和修复工具

3.6、redis-check-dump:

RDB持久化文件检测和修复工具

4、统一管理配置文件

移动配置文件到安装目录下:

cd ../
mkdir /usr/local/redis/etc
mv redis.conf /usr/local/redis/etc

当然这是为了方便管理,如果不移动,则后面涉及配置文件的地方仍在原目录下,如启动则执行:

cd /usr/local/redis/bin 
./redis-server /usr/local/redis/redis-stable/redis.conf 

再比如移动到bin目录下,则启动命令中redis.conf的目录改为当前目录即可:

mv /usr/local/redis/redis-stable/redis.conf /usr/local/redis/bin/
cd /usr/local/redis/bin
./redis-server ./redis.conf
 5、配置redis为后台启动:
vi /usr/local/redis/etc/redis.conf //将daemonize no 改成daemonize yes
6、启动redis:
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

查看进程,启动成功:

7、关闭redis:

有以下几种方法:

(1)kill -9 进程号 

(2)cli命令窗口执行shutdown。

8、常用命令 

二、windows安装redis:

 1、安装步骤: 参考http://www.runoob.com/redis/redis-tutorial.html

  2、启动方法:(1)cmd命令行启动:进入redis安装目录,运行redis-server.exe redis.windows.conf 即可启动redis服务。

  这时候另启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了。

  切换到redis目录下运行 redis-cli.exe -h 127.0.0.1 -p 6379 。

  设置键值对 set myKey abc

  取出键值对 get myKey

(2)服务自启动:在redis目录打开cmd命令执行redis-server.exe --service-install redis.windows-service.conf,即可把 redis加入服务管理中启动:

2、设置密码:默认安装后的redis是没有密码的,这明显有很大的安全隐患(注意:使用代码连接时,redis如果没有设置密码,代码就不需要写上password)。redis设置密码有两种方法:使用控制台或修改配置文件“redis.windows-service.conf”,使用第1种方式,需要知道如何在“控制台”里操作redis,而且重启后就无效了,不推荐这种方式。我们来说第2种方式,在安装的目录下找到并打开“redis.windows-service.conf”文件

################################## SECURITY ###################################

# Require clients to issue AUTH <PASSWORD> before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
# requirepass foobared

加上一行requirepass 你的密码,redis.windows.cong文件做同样的修改,重启redis生效。

三、redis可视化工具:

RedisDesktopManager

     

如我连接了本地的redis,从可视化工具也可以看到redis默认的共有16个数据库,(注意只能连接redis,不能连接哨兵)。

通过代码连接不指定的话默认的是使用第一个。且每个数据库是独立的不可共享。

四、单机版代码测试:

(redis及session共享)

1、pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>redisgroup</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

         <!-- session共享 -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session</artifactId>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.33</version>
        </dependency>
    </dependencies>

</project>

2、application.properties:

server.port=9999
server.context-path=/redisgroup

my.redis.server.host=xxx.xx.xxx
my.redis.server.port=6379
my.redis.server.password = wtyy
my.redis.server.jedis.pool.maxTotal=500
my.redis.server.jedis.pool.maxIdle=10
my.redis.server.jedis.pool.maxWaitMillis=5000
my.redis.server.jedis.pool.min-idle=5
my.redis.server.timeout=5000 

#session共享
spring.redis.host=xxx.xx.xxx
spring.redis.port=6379
spring.redis.password=wtyy

3、config:

(1)JedisConfig:

package com.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.support.collections.RedisProperties;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class JedisConfig {

    private Logger logger = LoggerFactory.getLogger(JedisConfig.class);

    @Value("${my.redis.server.host}")
    private String host;

    @Value("${my.redis.server.port}")
    private int port;

    @Value("${my.redis.server.password}")
    private String password;

    @Value("${my.redis.server.jedis.pool.maxTotal}")
    private int maxTotal;

    @Value("${my.redis.server.jedis.pool.maxIdle}")
    private int maxIdle;

    @Value("${my.redis.server.jedis.pool.maxWaitMillis}")
    private int maxWaitMillis;

    @Value("${my.redis.server.timeout}")
    private int timeout;

    @Bean(name = "jedisPool")
    public JedisPool jedisPool() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdle);
        config.setMaxWaitMillis(maxWaitMillis);
        return new JedisPool(config, host, port, timeout,password);
    }

}

2、RedisClient:redis  key、value操作util:

package com.demo.config;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;


@SuppressWarnings("unused")
@Component
public class RedisClient {
    private static boolean BORROW = true; // 在borrow一个事例时是否提前进行validate操作
    private static Logger logger = Logger.getLogger(RedisClient.class);
    @Autowired
    private JedisPool pool;


    /**
     * 获取连接
     */
    public  synchronized Jedis getJedis() {
        try {
            if (pool != null) {
                return pool.getResource();
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.info("连接池连接异常");
            return null;
        }

    }




    /**
     * @Description: 关闭连接
     * @param @param jedis
     * @return void 返回类型
     */

    public static void getColse(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }


    /**
     * 格式化Key
     */
    public static String format(String formatKey, String... keyValues) {
        if (keyValues == null || keyValues.length == 0) {
            return formatKey;
        }
        StringBuilder key = new StringBuilder();
        char[] chars = formatKey.toCharArray();
        int index = -1;
        boolean inmark = false;
        boolean firstinmark = false;
        for (int i = 0; i < chars.length; i++) {
            char ch = chars[i];
            if (ch == '{') {
                index++;
                inmark = true;
                firstinmark = true;
            } else if (ch == '}') {
                inmark = false;
            } else if (inmark) {
                if (firstinmark) {
                    firstinmark = false;
                    key.append(keyValues[index]);
                }
            } else {
                key.append(chars[i]);
            }
        }
        return key.toString();
    }

    /********************************** 针对key的操作 **************************************/

    /**
     * 删除一个key
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 被删除的keys的数量
     */
    public Long del(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.del(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 查询一个key是否存在
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return key是否存在。
     */
    public boolean exists(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.exists(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置一个key的过期的秒数
     *
     * @param keyFormat
     *            key标识
     * @param seconds
     *            过期的秒数
     * @param keyValues
     *            key变量
     * @return 1表示设置成功, 0 表示设置失败或者无法被设置
     */
    public Long expire(String keyFormat, int seconds, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.expire(key, seconds);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置一个UNIX时间戳的过期时间
     *
     * @param keyFormat
     *            key标识
     * @param expireDate
     *            过期时间
     * @param keyValues
     *            key变量
     * @return 1表示设置成功, 0 表示设置失败或者无法被设置
     */
    public Long expireAt(String keyFormat, Date expireDate, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.pexpireAt(key, expireDate.getTime());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 .
     */
    public Long persist(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.persist(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置一个key的过期的毫秒数
     *
     * <pre>
     * 这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param milliSeconds
     *            过期的毫秒数
     * @param keyValues
     *            key变量
     * @return 设置成功,返回 1,不存在或设置失败,返回 0
     */
    public Long pexpire(String keyFormat, long milliSeconds,
                        String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.pexpire(key, milliSeconds);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取key的有效毫秒数
     *
     * <pre>
     * 这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以毫秒为单位,返回 key
     *         的剩余生存时间。
     */
    public Long pttl(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.pttl(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    /**
     * 获取key的有效时间(单位:秒)
     *
     * <pre>
     * 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key
     *         的剩余生存时间。
     */
    public Long ttl(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.ttl(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /********************************** 针对字符串(string)的操作 **************************************/

    /**
     * 追加一个值到key上
     *
     * <pre>
     * 如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾。
     * 如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            要追加的值
     * @param keyValues
     *            key变量
     * @return 返回append后字符串值(value)的长度。
     */
    public Long append(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.append(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 整数原子减1
     *
     * <pre>
     * 对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
     * 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。
     * 这个操作最大支持在64位有符号的整型数字。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 数字:减小之后的value
     */
    public Long decr(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.decr(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 原子减指定的整数
     *
     * <pre>
     * 将key对应的数字减decrement。如果key不存在,操作之前,key就会被置为0。
     * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
     * 这个操作最多支持64位有符号的正型数字。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param integer
     *            要减小的数值
     * @param keyValues
     *            key变量
     * @return 返回一个数字:减少之后的value值。
     */
    public Long decrby(String keyFormat, long integer, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.decrBy(key, integer);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**

     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return key对应的value,或者null(key不存在时)
     */
    public String get(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.get(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置一个key的value,并获取设置前的值
     *
     * <pre>
     * 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。
     * exp:
     * GETSET可以和INCR一起使用实现支持重置的计数功能。
     * 举个例子:每当有事件发生的时候,一段程序都会调用INCR给key mycounter加1,但是有时我们需要获取计数器的值,并且自动将其重置为0。
     * 这可以通过GETSET mycounter "0"来实现:
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            要设置的值
     * @param keyValues
     *            key变量
     * @return 设置之前的值
     */
    public String getSet(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.getSet(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 执行原子加1操作
     *
     * <pre>
     * 对key对应的数字做加1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
     * 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。这个操作最大支持在64位有符号的整型数字。
     * 提醒:这是一个string操作,因为Redis没有专用的数字类型。key对应的string都被解释成10进制64位有符号的整型来执行这个操作。
     * Redis会用相应的整数表示方法存储整数,所以对于表示数字的字符串,没必要为了用字符串表示整型存储做额外开销。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 增加之后的value
     */
    public Long incr(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.incr(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 执行原子加1操作,并且设置过期时间(单位:s)
     *
     * <pre>
     * 本操作是在{@linkplain RedisClient#incr(String, String...)}之上增加了一个设置过期时间的操作
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param expireTime
     *            过期时间(单位:s)
     * @param keyValues
     *            key变量
     * @return 增加之后的value
     */
    public Long incr(String keyFormat, int expireTime, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            long result = jedis.incr(key);
            jedis.expire(key, expireTime);
            return result;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 执行原子增加一个整数
     *
     * <pre>
     * 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
     * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
     * 查看方法{@linkplain RedisClient#incr(String, String...)}了解关于增减操作的额外信息。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param increment
     *            要增加的数值
     * @param keyValues
     *            key变量
     * @return 增加后的value
     */
    public Long incrBy(String keyFormat, long increment, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.incrBy(key, increment);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 执行原子增加一个浮点数
     *
     * <pre>
     * 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
     * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param increment
     *            要增加的数值
     * @param keyValues
     *            key变量
     * @return 增加后的value
     */
    public Double incrByFloat(String keyFormat, double increment,
                              String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.incrByFloat(key, increment);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置一个key的value值
     *
     * <pre>
     * 警告:如果key已经存在了,它会被覆盖,而不管它是什么类型。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            要设置的值
     * @param keyValues
     *            key变量
     *
     * @return 总是"OK"
     */
    public String set(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.set(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置key-value并设置过期时间(单位:秒)
     *
     * <pre>
     * 设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期。
     * 该命令相当于执行了{@link #set(String, String, String...) SET} + {@link #expire(String, int, String...) EXPIRE}.并且该操作是原子的
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param seconds
     *            超时时间(单位:s)
     * @param value
     *            设置的值
     * @param keyValues
     *            key变量
     * @return 状态码
     */
    public String setex(String keyFormat, int seconds, String value,
                        String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.setex(key, seconds, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置key-value并设置过期时间(单位:毫秒)
     *
     * <pre>
     * 跟{@link #setex(String, int, String, String...)}效果差不多,唯一区别是超时时间是ms
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param milliseconds
     *            超时时间(单位:ms)
     * @param value
     *            设置的值
     * @param keyValues
     *            key变量
     * @return 状态码
     */
    public String psetex(String keyFormat, int milliseconds, String value,
                         String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.psetex(key, (long) milliseconds, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置的一个关键的价值,只有当该键不存在
     *
     * <pre>
     * 如果key不存在,就设置key对应字符串value。在这种情况下,该命令和SET一样。
     * 当key已经存在时,就不做任何操作。SETNX是"SET if Not eXists"。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            设置的value
     * @param keyValues
     *            key变量
     * @return 1 如果key被set,0 如果key没有被set
     */
    public Long setnx(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.setnx(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /********************************* Hash 操作 ******************************/

    /**
     * 删除一个哈希域
     *
     * <pre>
     * 从 key 指定的哈希集中移除指定的域。在哈希集中不存在的域将被忽略。
     * 如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            要删除的域
     * @param keyValues
     *            key变量
     * @return 返回从哈希集中成功移除的域的数量,不包括指出但不存在的那些域
     */
    public long hdel(String keyFormat, String field, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hdel(key, field);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 删除一个hash中的多个域
     *
     * <pre>
     * 相当于多次执行{@link #hdel(String, String, String...)}, 效率会有所提高
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param fileds
     *            要删除的域
     * @param keyValues
     *            key变量
     *
     * @return 返回从哈希集中成功移除的域的数量,不包括指出但不存在的那些域
     */
    public Long hdel(String keyFormat, Set<String> fileds, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hdel(key, fileds.toArray(new String[fileds.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 判断给定域是否存在于哈希集中
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            指定的域
     * @param keyValues
     *            key变量
     * @return 返回字段是否是 key 指定的哈希集中存在的字段。
     */
    public Boolean hexists(String keyFormat, String field, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hexists(key, field);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 读取哈希域的的值
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            指定的域
     * @param keyValues
     *            key变量
     * @return 该字段所关联的值。当字段不存在或者 key 不存在时返回null。
     */
    public String hget(String keyFormat, String field, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hget(key, field);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 读取哈希域的的值(返回的是byte[])
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            指定的域
     * @param keyValues
     *            key变量
     * @return 该字段所关联的值(byte[])。当字段不存在或者 key 不存在时返回null。
     */
    public byte[] hgetBytes(String keyFormat, String field, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hget(key.getBytes(), field.getBytes());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从哈希集中读取全部的域和值
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 哈希集中字段和值的列表。当 key 指定的哈希集不存在时返回空列表。
     */
    public Map<String, String> hgetAll(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hgetAll(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 将哈希集中指定域的值增加给定的数字
     *
     * <pre>
     * 增加 key 指定的哈希集中指定字段的数值。
     * 如果 key 不存在,会创建一个新的哈希集并与 key 关联。
     * 如果字段不存在,则字段的值在该操作执行前被设置为 0
     * HINCRBY 支持的值的范围限定在 64位 有符号整数
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            指定的域
     * @param value
     *            给定的数字
     * @param keyValues
     *            key变量
     * @return 增值操作执行后的该字段的值。
     */
    public long hincrBy(String keyFormat, String field, long value,
                        String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hincrBy(key, field, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 将哈希集中指定域的值增加给定的浮点数
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            指定的域
     * @param value
     *            给定的浮点数
     * @param keyValues
     *            key变量
     * @return 增值操作执行后的该字段的值。
     */
    public Double hincrByFloat(String keyFormat, String field, double value,
                               String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hincrByFloat(key, field, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取hash的所有字段
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 哈希集中的字段列表,当 key 指定的哈希集不存在时返回空列表。
     */
    public Set<String> hkeys(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hkeys(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取hash里所有字段的数量
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 哈希集中字段的数量,当 key 指定的哈希集不存在时返回 0
     */
    public Long hlen(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hlen(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 批量获取hash中的值
     *
     * <pre>
     * 返回 key 指定的哈希集中指定字段的值。
     * 对于哈希集中不存在的每个字段,返回null值。
     * 因为不存在的keys被认为是一个空的哈希集,对一个不存在的 key 执行 HMGET 将返回一个只含有 null值的列表
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param fileds
     *            指定的域
     * @param keyValues
     *            key变量
     * @return 含有给定字段及其值的列表,并保持与请求相同的顺序。
     */
    public List<String> hmget(String keyFormat, List<String> fileds,
                              String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hmget(key, fileds.toArray(new String[fileds.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 批量设置hash中的值
     *
     * <pre>
     * 设置 key 指定的哈希集中指定字段的值。该命令将重写所有在哈希集中存在的字段。
     * 如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param hash
     *            指定的域和值
     * @param keyValues
     *            key变量
     * @return Return OK or Exception if hash is empty
     */
    public String hmset(String keyFormat, Map<String, String> hash,
                        String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hmset(key, hash);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置hash里面一个字段的值
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            字段
     * @param value
     *            值
     * @param keyValues
     *            key变量
     * @return 含义如下:1如果field是一个新的字段 0如果field原来在map里面已经存在
     *
     */
    public Long hset(String keyFormat, String field, String value,
                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hset(key, field, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置hash里面一个字段的值(值为byte[]数组类型)
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            字段
     * @param value
     *            值
     * @param keyValues
     *            key变量
     * @return 含义如下:1如果field是一个新的字段 0如果field原来在map里面已经存在
     *
     */
    public Long hset(String keyFormat, String field, byte[] value,
                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hset(key.getBytes(), field.getBytes(), value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置hash的一个字段,只有当这个字段不存在时有效
     *
     * <pre>
     * 只在 key 指定的哈希集中不存在指定的字段时,设置字段的值。
     * 如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。
     * 如果字段已存在,该操作无效果。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param field
     *            字段
     * @param value
     *            值
     * @param keyValues
     *            key变量
     * @return 1:如果字段是个新的字段,并成功赋值 0:如果哈希集中已存在该字段,没有操作被执行
     */
    public Long hsetnx(String keyFormat, String field, String value,
                       String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hsetnx(key, field, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获得hash的所有值
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 哈希集中的值的列表,当 key 指定的哈希集不存在时返回空列表。
     */
    public List<String> hvals(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hvals(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /******************************* SET 操作 *************************/

    /**
     * 添加一个元素到集合(set)里
     *
     * <pre>
     * 添加一个指定的member元素到集合的 key中.
     * 如果已经在集合key中存在则忽略.如果集合key 不存在,则新建集合key,并添加member元素到集合key中.
     * 如果key 的类型不是集合则返回错误.
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            元素
     * @param keyValues
     *            key变量
     * @return 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素.
     */
    public Long sadd(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.sadd(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 批量添加元素到集合(set)里
     *
     * <pre>
     * 添加指定的member元素到集合的 key中.
     * 如果已经在集合key中存在则忽略.如果集合key 不存在,则新建集合key,并添加member元素到集合key中.
     * 如果key 的类型不是集合则返回错误.
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param values
     *            要添加的元素集合
     * @param keyValues
     *            key变量
     * @return 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素.
     */
    public Long sadd(String keyFormat, List<String> values, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.sadd(key, values.toArray(new String[values.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取集合里面的元素数量
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 集合的基数(元素的数量),如果key不存在,则返回 0.
     */
    public Long scard(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.scard(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 确定一个给定的值是一个集合的成员
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            给定的值
     * @param keyValues
     *            key变量
     * @return 返回成员 value是否是存储的集合 key的成员.
     */
    public Boolean sismember(String keyFormat, String value,
                             String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.sismember(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取集合里面的所有key
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 集合中的所有元素.
     */
    public Set<String> smembers(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.smembers(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 删除并获取一个集合里面的元素
     *
     * <pre>
     * 移除并返回一个集合中的随机元素
     * 该命令与 {@link #srandmember(String, String...)}相似,不同的是srandmember命令返回一个随机元素但是不移除.
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 被移除的元素, 当key不存在的时候返回 null .
     */
    public String spop(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.spop(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从集合里面随机获取一个key
     *
     * <pre>
     *  随机返回key集合中的一个元素.
     *  该命令作用类似于{@link #spop(String, String...)}命令,
     *  不同的是SPOP命令会将被选择的随机元素从集合中移除, 而SRANDMEMBER仅仅是返回该随记元素,而不做任何操作.
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 被移除的元素, 当key不存在的时候返回 null .
     */
    public String srandmember(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.srandmember(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从集合里删除一个元素
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            要删除的元素
     * @param keyValues
     *            key变量
     * @return 从集合中移除元素的个数,不包括不存在的成员.
     */
    public Long srem(String keyFormat, String member, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.srem(key, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 批量从集合里删除元素
     *
     * @param keyFormat
     *            key标识
     * @param members
     *            要删除的元素
     * @param keyValues
     *            key变量
     * @return 从集合中移除元素的个数,不包括不存在的成员.
     */
    public Long srem(String keyFormat, List<String> members,
                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.srem(key, members.toArray(new String[members.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /***************************** ZSET 操作 *****************************/

    /**
     * 添加到有序set的一个成员,如果它已经存在,则更新分数。
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            成员
     * @param score
     *            分值
     * @param keyValues
     *            key变量
     * @return 如果是新添加的,返回1,如果是更新,返回0
     */
    public Long zadd(String keyFormat, String member, double score,
                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zadd(key, score, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 批量添加到有序的成员,如果已经存在,则更新分数。
     *
     * @param keyFormat
     *            key标识
     * @param scoreMembers
     *            成员和对应的分值
     * @param keyValues
     *            key变量
     * @return 返回添加到有序集合中元素的个数,不包括那种已经存在只是更新分数的元素。
     */
    public Long zadd(String keyFormat, Map<String, Double> scoreMembers,
                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zadd(key, scoreMembers);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取一个排序的集合中的成员数量
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return key存在的时候,返回有序集的元素个数,否则返回0。
     */
    public Long zcard(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zcard(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取给定值范围内的成员数
     *
     * <pre>
     * 返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。
     * 关于参数min和max的详细使用方法,请参考ZRANGEBYSCORE命令。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param min
     *            范围下限
     * @param max
     *            范围上限
     * @param keyValues
     *            key变量
     * @return key存在的时候,返回有序集的元素个数,否则返回0。
     */
    public Long zcount(String keyFormat, double min, double max,
                       String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zcount(key, min, max);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 给一个有序集合中的成员增加指定的分值
     *
     * <pre>
     * 为有序集key的成员member的分值值加上score。如果key中不存在member,就在key中添加一个member,分值是score
     * 如果key不存在,就创建一个只含有指定member成员的有序集合。
     * 当key不是有序集类型时,返回一个错误。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            成员
     * @param score
     *            增加的分值
     * @param keyValues
     *            key变量
     * @return member成员的新分值。
     */
    public Double zincrby(String keyFormat, String member, double score,
                          String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zincrby(key, score, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取排名在[start, end]之间的成员
     *
     * <pre>
     * 返回有序集key中,指定区间内的成员。其中成员按score值递增(从小到大)来排序。具有相同score值的成员按字典序来排列。
     * 如果你需要成员按score值递减(score相等时按字典序递减)来排列,请使用ZREVRANGE命令。
     * 下标参数start和stop都以0为底,也就是说,以0表示有序集第一个成员,以1表示有序集第二个成员,以此类推。
     * 你也可以使用负数下标,以-1表示最后一个成员,-2表示倒数第二个成员,以此类推。
     * 超出范围的下标并不会引起错误。如果start的值比有序集的最大下标还要大,或是start > stop时,ZRANGE命令只是简单地返回一个空列表。
     * 另一方面,假如stop参数的值比有序集的最大下标还要大,那么Redis将stop当作最大下标来处理。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            排名开始
     * @param end
     *            排名结尾
     * @param keyValues
     *            key变量
     * @return 排名在[start, end]之间的成员
     */
    public Set<String> zrange(String keyFormat, long start, long end,
                              String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrange(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取排名在[start, end]之间的成员及分数
     *
     * <pre>
     * 该方法和{@link #zrange(String, long, long, String...)}相似,只是连带分数值一起返回
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            排名开始
     * @param end
     *            排名结尾
     * @param keyValues
     *            key变量
     * @return 排名在[start, end]之间的成员及分数
     * @see #zrange(String, long, long, String...)
     */
    public Set<Tuple> zrangeWithScores(String keyFormat, long start, long end,
                                       String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrangeWithScores(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取分数值在[min, max]之间的成员
     *
     * @param keyFormat
     *            key标识
     * @param min
     *            最小分值
     * @param max
     *            最大分值
     * @param keyValues
     *            keyValues key变量
     * @return 分值在[min, max]之间的成员
     */
    public Set<String> zrangeByScore(String keyFormat, double min, double max,
                                     String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrangeByScore(key, min, max);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取分数值在[min, max]之间的成员及分数
     *
     * @param keyFormat
     *            key标识
     * @param min
     *            最小分值
     * @param max
     *            最大分值
     * @param keyValues
     *            keyValues key变量
     * @return 分值在[min, max]之间的成员及分数
     */
    public Set<Tuple> zrangeByScoreWithScores(String keyFormat, double min,
                                              double max, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrangeByScoreWithScores(key, min, max);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取有序集合中某个成员的排名(从0开始)
     *
     * <pre>
     * 返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。
     * 排名以0为底,也就是说,score值最小的成员排名为0。
     * 使用ZREVRANK命令可以获得成员按score值递减(从大到小)排列的排名。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            指定的成员
     * @param keyValues
     *            key变量
     * @return 该元素的排名,如果集合中不存在该元素,返回null
     */
    public Long zrank(String keyFormat, String member, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrank(key, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从排序的集合中删除一个成员
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            要删除的成员
     * @param keyValues
     *            key变量
     * @return 删除成功返回1,如果集合中不存在返回0
     */
    public Long zrem(String keyFormat, String member, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrem(key, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 删除排名在[start,end](从小到大)之间的成员
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            排名的开始
     * @param end
     *            排名的结尾
     * @param keyValues
     *            key变量
     * @return 被移除成员的数量。
     */
    public Long zremrangeByRank(String keyFormat, long start, long end,
                                String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zremrangeByRank(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 删除分数值在[min,max]之间的成员
     *
     * @param keyFormat
     *            key标识
     * @param min
     *            最小分数值
     * @param max
     *            最大分数值
     * @param keyValues
     *            key变量
     * @return 被移除成员的数量。
     */
    public Long zremrangeByScore(String keyFormat, double min, double max,
                                 String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zremrangeByScore(key, min, max);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取排名在[start, end](从大到小)之间的成员
     *
     * <pre>
     * 返回有序集key中,指定区间内的成员。
     * 其中成员的位置按score值递减(从大到小)来排列。具有相同score值的成员按字典序的反序排列。
     * 除了成员按score值递减的次序排列这一点外,ZREVRANGE命令的其他方面和ZRANGE命令一样。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            排名开始
     * @param end
     *            排名结束
     * @param keyValues
     *            key变量
     * @return 取排名在[start, end](从大到小)之间的成员
     */
    public Set<String> zrevrange(String keyFormat, long start, long end,
                                 String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrevrange(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取排名在[start, end](从大到小)之间的成员及分数值
     *
     * <pre>
     * 返回有序集key中,指定区间内的成员。
     * 其中成员的位置按score值递减(从大到小)来排列。具有相同score值的成员按字典序的反序排列。
     * 除了成员按score值递减的次序排列这一点外,ZREVRANGEWITHSCORE命令的其他方面和ZRANGEWITHSCORE命令一样。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            排名开始
     * @param end
     *            排名结束
     * @param keyValues
     *            key变量
     * @return 排名在[start, end](从大到小)之间的成员及分数值
     */
    public Set<Tuple> zrevrangeWithScores(String keyFormat, long start,
                                          long end, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrevrangeWithScores(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获得成员按 score 值递减(从大到小)排列的排名
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            成员
     * @param keyValues
     *            key变量
     * @return 成员的排名
     */
    public Long zrevrank(String keyFormat, String member, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrevrank(key, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取分数值在[max, min](从大到小)之间的成员
     *
     * @param keyFormat
     *            key标识
     * @param max
     *            最大分数值
     * @param min
     *            最小分数值
     * @param keyValues
     *            key变量
     * @return 分数值在[max, min](从大到小)之间的成员
     */
    public Set<String> zrevrangeByScore(String keyFormat, double max,
                                        double min, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zrevrangeByScore(key, max, min);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取成员在有序集合中的分数值
     *
     * @param keyFormat
     *            key标识
     * @param member
     *            成员
     * @param keyValues
     *            key变量
     * @return member成员的score值,如果member元素不是有序集key的成员,或key不存在,返回null。
     */
    public Double zscore(String keyFormat, String member, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.zscore(key, member);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /***************************** LIST 操作 *************************************/

    /**
     * 删除,并获得该列表中的第一元素,或阻塞,直到有一个可用
     *
     * <pre>
     * 该操作是从left 到 right获取第一个元素
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param timeout
     *            指定阻塞的最大秒数的整型值。当 timeout 为 0 是表示阻塞时间无限制。
     * @param keyValues
     *            key变量
     * @return 如果阻塞超时还没有获取值,则返回空(列表)。如果有值则返回一个List,第一个值表示key名称,第二个元素为value
     */
    public List<String> blpop(String keyFormat, int timeout,
                              String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.blpop(timeout, key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 删除,并获得该列表中的第一元素,或阻塞,直到有一个可用
     *
     * <pre>
     * 该操作是从right 到 left获取第一个元素
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param timeout
     *            指定阻塞的最大秒数的整型值。当 timeout 为 0 是表示阻塞时间无限制。
     * @param keyValues
     *            key变量
     * @return 如果阻塞超时还没有获取值,则返回空(列表)。如果有值则返回一个List,第一个值表示key名称,第二个元素为value
     */
    public List<String> brpop(String keyFormat, int timeout,
                              String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.brpop(timeout, key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获得队列(List)的长度
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return list长度
     */
    public Long llen(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.llen(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的左边出队一个元素
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 返回第一个元素的值,或者当 key 不存在时返回 null。
     */
    public String lpop(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.lpop(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的左边入队一个元素
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            元素值
     * @param keyValues
     *            key变量
     * @return 在 push 操作后的 list 长度。
     */
    public Long lpush(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.lpush(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的左边入队多个元素
     *
     * @param keyFormat
     *            key标识
     * @param values
     *            元素值列表
     * @param keyValues
     *            key变量
     * @return 在 push 操作后的 list 长度。
     */
    public Long lpush(String keyFormat, List<String> values,
                      String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.lpush(key, values.toArray(new String[values.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的右边入队一个元素
     *
     * @param keyFormat
     *            key标识
     * @param value
     *            元素值
     * @param keyValues
     *            key变量
     * @return 在 push 操作后的 list 长度。
     */
    public Long rpush(String keyFormat, String value, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.rpush(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的右边入队多个元素
     *
     * @param keyFormat
     *            key标识
     * @param values
     *            元素值列表
     * @param keyValues
     *            key变量
     * @return 在 push 操作后的 list 长度。
     */
    public Long rpush(String keyFormat, List<String> values,
                      String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.rpush(key, values.toArray(new String[values.size()]));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从队列的右边出队一个元素
     *
     * @param keyFormat
     *            key标识
     * @param keyValues
     *            key变量
     * @return 返回第一个元素的值,或者当 key 不存在时返回 null。
     */
    public String rpop(String keyFormat, String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.rpop(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 从列表中获取指定返回的元素
     *
     * <pre>
     * 返回存储在 key 的列表里指定范围内的元素。
     * start 和 end 偏移量都是基于0的下标,即list的第一个元素下标是0(list的表头),第二个元素下标是1,以此类推。
     * 偏移量也可以是负数,表示偏移量是从list尾部开始计数。 例如, -1 表示列表的最后一个元素,-2 是倒数第二个,以此类推。
     * </pre>
     *
     * @param keyFormat
     *            key标识
     * @param start
     *            开始偏移量
     * @param end
     *            结束偏移量
     * @param keyValues
     *            key变量
     * @return
     */
    public List<String> lrange(String keyFormat, long start, long end,
                               String... keyValues) {
        String key = format(keyFormat, keyValues);
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.lrange(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

//	/**
//	 * 使用管道进行批量的操作
//	 *
//	 * @param keyFormat
//	 *            key标识
//	 * @param executeInPipeline
//	 *            批量执行的回调
//	 */
//	public void pipelined(String keyFormat, ExecuteInPipeline executeInPipeline) {
//		Jedis jedis = null;
//		try {
//			jedis = getJedis();
//			Pipeline pipeline = jedis.pipelined();
//			executeInPipeline.execute(pipeline);
//		} finally {
//			if (jedis != null) {
//				jedis.close();
//			}
//		}
//	}
//
//	public String getConfigFile() {
//		return configFile;
//	}

//	public void setConfigFile(String configFile) {
//		this.configFile = configFile;
//	}

}

4、测试接口:

package com.demo.controller;

import com.demo.config.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("index")
public class IndexController {

    @Autowired
    private RedisClient redisClient;

    private String nameFormat = "redis:name:{name}";

    @RequestMapping("/setName")
    public void setName(String key,String value){
        redisClient.set(nameFormat,value,key);
    }

    @RequestMapping("/getName")
    public String getName(String key){
        return  redisClient.get(nameFormat,key);
    }

    @RequestMapping("/sessionSetName")
    public void sessionSetName(HttpServletRequest request,String value){
        request.getSession().setAttribute("test",value);
    }

    @RequestMapping("/sessionGetName")
    public String sessionGetName(HttpServletRequest request){
        return (String) request.getSession().getAttribute("test");
    }
}

5、启动类:

package com.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String args[]){
        SpringApplication.run(Application.class,args);
    }
}

*********************

6、测试:启动项目后,修改端口号为7777再启动一次。

(1)测试redis存:

测试redis取:

从redis可视化工具也可以看到值存储成功:

(2)测试session 存:

测试session取:

9999端口

7777端口: 

可以看到redis中也有值了:

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/w_t_y_y/article/details/106548970

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签