package com.liying.monkey.core.util; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.log4j.Logger; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import com.liying.monkey.core.common.Constants.Zero; public class RedisUtil { private static final Logger log = Logger.getLogger(RedisUtil.class); //等待可用連接的最大時間,單位毫秒,默認值為-1,表示永不超時。如果超過等待時間,則直接拋出JedisConnectionException; private static int MAX_WAIT = 15 * 1000; //超時時間 private static int TIMEOUT = 10 * 1000; private static JedisPool jedisPool = null; /** * Jedis實例獲取返回碼 * * @author jqlin * */ public static class JedisStatus{ /**Jedis實例獲取失敗*/ public static final long FAIL_LONG = -5L; /**Jedis實例獲取失敗*/ public static final int FAIL_INT = -5; /**Jedis實例獲取失敗*/ public static final String FAIL_STRING = "-5"; } private static void initialPool() { //Redis服務器IP String HOST = PropertyReader.get("redis.native.host"); //Redis的端口號 int PORT = NumberUtils.toInt(PropertyReader.get("redis.native.port"), 6379); //訪問密碼 String AUTH = PropertyReader.get("redis.native.password"); try { JedisPoolConfig config = new JedisPoolConfig(); //最大連接數,如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis實例,則此時pool的狀態為exhausted(耗盡)。 config.setMaxTotal(NumberUtils.toInt(PropertyReader.get("redis.native.maxTotal"), 400)); //最大空閑數,控制一個pool最多有多少個狀態為idle(空閑的)的jedis實例,默認值也是8。 config.setMaxIdle(NumberUtils.toInt(PropertyReader.get("redis.native.maxIdle"), 50)); //最小空閑數 config.setMinIdle(NumberUtils.toInt(PropertyReader.get("redis.native.minIdle"), 10)); //是否在從池中取出連接前進行檢驗,如果檢驗失敗,則從池中去除連接並嘗試取出另一個 config.setTestOnBorrow(true); //在return給pool時,是否提前進行validate操作 config.setTestOnReturn(true); //在空閑時檢查有效性,默認false config.setTestWhileIdle(true); //表示一個對象至少停留在idle狀態的最短時間,然后才能被idle object evitor掃描並驅逐; //這一項只有在timeBetweenEvictionRunsMillis大於0時才有意義 config.setMinEvictableIdleTimeMillis(30000); //表示idle object evitor兩次掃描之間要sleep的毫秒數 config.setTimeBetweenEvictionRunsMillis(60000); //表示idle object evitor每次掃描的最多的對象數 config.setNumTestsPerEvictionRun(1000); //等待可用連接的最大時間,單位毫秒,默認值為-1,表示永不超時。如果超過等待時間,則直接拋出JedisConnectionException; config.setMaxWaitMillis(MAX_WAIT); if (StringUtils.isNotBlank(AUTH)) { jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT, AUTH); } else { jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT); } } catch (Exception e) { if(jedisPool != null){ jedisPool.close(); } log.error("初始化Redis連接池失敗", e); } } /** * 初始化Redis連接池 */ static { initialPool(); } /** * 在多線程環境同步初始化 */ private static synchronized void poolInit() { if (jedisPool == null) { initialPool(); } } /** * 同步獲取Jedis實例 * * @return Jedis */ public static Jedis getJedis() { if (jedisPool == null) { poolInit(); } Jedis jedis = null; try { if (jedisPool != null) { jedis = jedisPool.getResource(); } } catch (Exception e) { log.error("同步獲取Jedis實例失敗" + e.getMessage(), e); returnBrokenResource(jedis); } return jedis; } /** * 釋放jedis資源 * * @param jedis */ @SuppressWarnings("deprecation") public static void returnResource(final Jedis jedis) { if (jedis != null && jedisPool != null) { jedisPool.returnResource(jedis); } } @SuppressWarnings("deprecation") public static void returnBrokenResource(final Jedis jedis) { if (jedis != null && jedisPool != null) { jedisPool.returnBrokenResource(jedis); } } /** * 設置值 * * @param key * @param value * @return -5:Jedis實例獲取失敗<br/>OK:操作成功<br/>null:操作失敗 * @author jqlin */ public static String set(String key, String value) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_STRING; } String result = null; try { result = jedis.set(key, value); } catch (Exception e) { log.error("設置值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 設置值 * * @param key * @param value * @param expire 過期時間,單位:秒 * @return -5:Jedis實例獲取失敗<br/>OK:操作成功<br/>null:操作失敗 * @author jqlin */ public static String set(String key, String value, int expire) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_STRING; } String result = null; try { result = jedis.set(key, value); jedis.expire(key, expire); } catch (Exception e) { log.error("設置值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取值 * * @param key * @return * @author jqlin */ public static String get(String key) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_STRING; } String result = null; try { result = jedis.get(key); } catch (Exception e) { log.error("獲取值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 設置key的過期時間 * * @param key * @param value -5:Jedis實例獲取失敗,1:成功,0:失敗 * @return * @author jqlin */ public static long expire(String key, int seconds) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_LONG; } long result = Zero.LONG; try { result = jedis.expire(key, seconds); } catch (Exception e) { log.error(String.format("設置key=%s的過期時間失敗:" + e.getMessage(), key), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 判斷key是否存在 * * @param key * @return * @author jqlin */ public static boolean exists(String key) { Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return false; } boolean result = false; try { result = jedis.exists(key); } catch (Exception e) { log.error(String.format("判斷key=%s是否存在失敗:" + e.getMessage(), key), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 刪除key * * @param keys * @return -5:Jedis實例獲取失敗,1:成功,0:失敗 * @author jqlin */ public static long del(String... keys) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_LONG; } long result = JedisStatus.FAIL_LONG; try { result = jedis.del(keys); } catch (Exception e) { log.error(String.format("刪除key=%s失敗:" + e.getMessage(), keys), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * set if not exists,若key已存在,則setnx不做任何操作 * * @param key * @param value key已存在,1:key賦值成功 * @return * @author jqlin */ public static long setnx(String key, String value) { long result = JedisStatus.FAIL_LONG; Jedis jedis = getJedis(); if(jedis == null){ return result; } try { result = jedis.setnx(key, value); } catch (Exception e) { log.error("設置值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * set if not exists,若key已存在,則setnx不做任何操作 * * @param key * @param value key已存在,1:key賦值成功 * @param expire 過期時間,單位:秒 * @return * @author jqlin */ public static long setnx(String key, String value, int expire) { long result = JedisStatus.FAIL_LONG; Jedis jedis = getJedis(); if(jedis == null){ return result; } try { result = jedis.setnx(key, value); jedis.expire(key, expire); } catch (Exception e) { log.error("設置值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 在列表key的頭部插入元素 * * @param key * @param values -5:Jedis實例獲取失敗,>0:返回操作成功的條數,0:失敗 * @return * @author jqlin */ public static long lpush(String key, String... values) { long result = JedisStatus.FAIL_LONG; Jedis jedis = getJedis(); if(jedis == null){ return result; } try { result = jedis.lpush(key, values); } catch (Exception e) { log.error("在列表key的頭部插入元素失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 在列表key的尾部插入元素 * * @param key * @param values -5:Jedis實例獲取失敗,>0:返回操作成功的條數,0:失敗 * @return * @author jqlin */ public static long rpush(String key, String... values) { long result = JedisStatus.FAIL_LONG; Jedis jedis = getJedis(); if(jedis == null){ return result; } try { result = jedis.rpush(key, values); } catch (Exception e) { log.error("在列表key的尾部插入元素失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 返回存儲在key列表的特定元素 * * * @param key * @param start 開始索引,索引從0開始,0表示第一個元素,1表示第二個元素 * @param end 結束索引,-1表示最后一個元素,-2表示倒數第二個元素 * @return redis client獲取失敗返回null * @author jqlin */ public static List<String> lrange(String key, long start, long end) { Jedis jedis = getJedis(); if(jedis == null){ return null; } List<String> result = null; try { result = jedis.lrange(key, start, end); } catch (Exception e) { log.error("查詢列表元素失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取List緩存對象 * * @param key * @param start * @param end * @return List<T> 返回類型 * @author jqlin */ public static <T> List<T> range(String key, long start, long end, Class<T> clazz){ List<String> dataList = lrange(key, start, end); if(CollectionUtils.isEmpty(dataList)){ return new ArrayList<T>(); } return JavaJsonConvert.json2List(dataList.toString(), clazz); } /** * 獲取列表長度 * * @param key -5:Jedis實例獲取失敗 * @return * @author jqlin */ public static long llen(String key) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_LONG; } long result = 0; try { result = jedis.llen(key); } catch (Exception e) { log.error("獲取列表長度失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 移除等於value的元素<br/><br/> * 當count>0時,從表頭開始查找,移除count個;<br/> * 當count=0時,從表頭開始查找,移除所有等於value的;<br/> * 當count<0時,從表尾開始查找,移除count個 * * @param key * @param count * @param value * @return -5:Jedis實例獲取失敗 * @author jqlin */ public static long lrem(String key, long count, String value) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_LONG; } long result = 0; try { result = jedis.lrem(key, count, value); } catch (Exception e) { log.error("獲取列表長度失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 對列表進行修剪 * * @param key * @param start * @param end * @return -5:Jedis實例獲取失敗,OK:命令執行成功 * @author jqlin */ public static String ltrim(String key, long start, long end) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_STRING; } String result = ""; try { result = jedis.ltrim(key, start, end); } catch (Exception e) { log.error("獲取列表長度失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 設置對象 * * @param key * @param obj * @return * @author jqlin */ public static <T> String setObject(String key ,T obj){ Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_STRING; } String result = null; try { byte[] data=SerializeUtil.serialize(obj); result = jedis.set(key.getBytes(), data); } catch (Exception e) { log.error("設置對象失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取對象 * * @param key * @return * @author jqlin */ @SuppressWarnings("unchecked") public static <T> T getObject(String key){ Jedis jedis = getJedis(); if(jedis == null){ return null; } T result = null; try { byte[] data = jedis.get(key.getBytes()); if(data != null && data.length > 0){ result=(T)SerializeUtil.unserialize(data); } } catch (Exception e) { log.error("獲取對象失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 設置List集合(慎用) * * @param key * @param dataList * @return * @author jqlin */ public synchronized static <T> T setList(String key, List<T> dataList){ Jedis jedis = getJedis(); if(jedis == null){ return null; } T result = null; try { List<T> list = getList(key); if(CollectionUtils.isNotEmpty(list)){ dataList.addAll(list); } if(CollectionUtils.isNotEmpty(dataList)){ byte[] data = SerializeUtil.serializeToList(dataList); jedis.set(key.getBytes(), data); }else{//如果list為空,則設置一個空 jedis.set(key.getBytes(), "".getBytes()); } } catch (Exception e) { log.error("設置List集合失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取List集合(慎用) * * @param key * @return * @author jqlin */ public static <T> List<T> getList(String key){ Jedis jedis = getJedis(); if(jedis == null){ return null; } try { byte[] data = getJedis().get(key.getBytes()); if(data != null && data.length > 0){ return SerializeUtil.unserializeToList(data); } } catch (Exception e) { log.error("獲取List集合失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return null; } /** * 緩存Map賦值 * * @param key * @param field * @param value * @return -5:Jedis實例獲取失敗 * @author jqlin */ public static long hset(String key, String field, String value) { Jedis jedis = getJedis(); if(jedis == null){ return JedisStatus.FAIL_LONG; } long result = 0L; try { result = jedis.hset(key, field, value); } catch (Exception e) { log.error("緩存Map賦值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取緩存的Map值 * * @param key * @return */ public static String hget(String key, String field){ Jedis jedis = getJedis(); if(jedis == null){ return null; } String result = null; try { result = jedis.hget(key, field); } catch (Exception e) { log.error("獲取緩存的Map值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return result; } /** * 獲取map所有的字段和值 * * @param key * @return * @author jqlin */ public static Map<String, String> hgetAll(String key){ Map<String, String> map = new HashMap<String, String>(); Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return map; } try { map = jedis.hgetAll(key); } catch (Exception e) { log.error("獲取map所有的字段和值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return map; } /** * 查看哈希表 key 中,指定的field字段是否存在。 * * @param key * @param field * @return * @author jqlin */ public static Boolean hexists(String key, String field){ Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return null; } try { return jedis.hexists(key, field); } catch (Exception e) { log.error("查看哈希表field字段是否存在失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return null; } /** * 獲取所有哈希表中的字段 * * @param key * @return * @author jqlin */ public static Set<String> hkeys(String key) { Set<String> set = new HashSet<String>(); Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return set; } try { return jedis.hkeys(key); } catch (Exception e) { log.error("獲取所有哈希表中的字段失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return null; } /** * 獲取所有哈希表中的值 * * @param key * @return * @author jqlin */ public static List<String> hvals(String key) { List<String> list = new ArrayList<String>(); Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return list; } try { return jedis.hvals(key); } catch (Exception e) { log.error("獲取所有哈希表中的值失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return null; } /** * 從哈希表 key 中刪除指定的field * * @param key * @param field * @return * @author jqlin */ public static long hdel(String key, String... fields){ Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return JedisStatus.FAIL_LONG; } try { return jedis.hdel(key, fields); } catch (Exception e) { log.error("map刪除指定的field失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return 0; } public static Set<String> keys(String pattern){ Set<String> keyList = new HashSet<String>(); Jedis jedis = getJedis(); if(jedis == null){ log.warn("Jedis實例獲取為空"); return keyList; } try { keyList = jedis.keys(pattern); } catch (Exception e) { log.error("操作keys失敗:" + e.getMessage(), e); returnBrokenResource(jedis); } finally { returnResource(jedis); } return keyList; } public static void main(String[] args) throws IOException { // System.out.println(hset("map", "a","3")); // System.out.println(hset("map", "b","3")); // System.out.println(hset("map", "c","3")); Set<String> set = keys("lock*"); for(String key : set){ System.out.println(key); } } }