一、前言
前一段时间,项目中要开发一个活动,为了提高接口的吞吐量,把一些完成后的操作使用异步的方法来操作。刚开始的时候想的是使用一个异步的方法,处理方法完成后的其他操作。但是在压测的时候发现,并发量很多的时候,线程池就会被沾满了,然后所有的操作都会堆积在这里,吞吐量就下来了。为了解决这个问题。就想用队列来处理,但是为了这么一个小的优化,接入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使用了才会有更深刻的印象。