一、前言
前一段時間,項目中要開發一個活動,爲了提高接口的吞吐量,把一些完成後的操作使用異步的方法來操作。剛開始的時候想的是使用一個異步的方法,處理方法完成後的其他操作。但是在壓測的時候發現,併發量很多的時候,線程池就會被沾滿了,然後所有的操作都會堆積在這裏,吞吐量就下來了。爲了解決這個問題。就想用隊列來處理,但是爲了這麼一個小的優化,接入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使用了纔會有更深刻的印象。