封裝JedisClient.提供API實現對redis的操做

須要導包,jedis-2.8.1.jar和博主的序列化工具類SerializeUtils

package com.demo.redis; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import redis.clients.jedis.BinaryJedisCluster; import redis.clients.jedis.BinaryJedisPubSub; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPubSub; import redis.clients.util.Pool; import redis.clients.util.SafeEncoder; import com.demo.utils.SerializeUtils; /** * JedisClient api 添加了中文註釋,便於工程師更方便使用,另外還原樣保持了 Jedis api 的方法名稱及使用方法,以便於僅僅經過查看 * Redis 文檔 便可快速掌握使用方法 Redis 命令參考: http://redisdoc.com/ */ public class JedisClient { private final String name; private final JedisPool jedisPool; private final BinaryJedisCluster cluster; private final boolean isCluster; public BinaryJedisCluster getCluster() { return cluster; } public Pool<Jedis> getJedisPool() { return jedisPool; } private final ThreadLocal<Jedis> threadLocalJedis = new ThreadLocal<Jedis>(); public JedisClient(String name, JedisPool jedisPool, BinaryJedisCluster cluster) { this.name = name; this.jedisPool = jedisPool; this.cluster = cluster; this.isCluster = this.cluster != null; } /** * 存放 key value 對到 redis 若是 key 已經持有其餘值, SET 就覆寫舊值,無視類型。 * 對於某個本來帶有生存時間(TTL)的鍵來講, 當 SET 命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。 */ public String set(String key, Object value) { return isCluster ? clusterSet(key, value) : jedisSet(key, value); } private String clusterSet(String key, Object value) { if (value == null) { cluster.del(keyToBytes(key)); return null; } else { return cluster.set(keyToBytes(key), valueToBytes(value)); } } private String jedisSet(String key, Object value) { Jedis jedis = getJedis(); try { if (value == null) { jedis.del(keyToBytes(key)); return null; } else { return jedis.set(keyToBytes(key), valueToBytes(value)); } } finally { close(jedis); } } /** * 存放 key value 對到 redis 若是 key 已經持有其餘值, SET 就覆寫舊值,無視類型。 * 對於某個本來帶有生存時間(TTL)的鍵來講, 當 SET 命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。 */ public void update(String key, Object value) { if (isCluster) { clusterUpdate(key, value); } else { jedisUpdate(key, value); } } private void clusterUpdate(String key, Object value) { Jedis jedis = getJedis(); try { byte[] bytes = keyToBytes(key); if (value == null) { cluster.del(bytes); } else { Long ttl = cluster.ttl(bytes); if (ttl > 0) { cluster.setex(bytes, ttl.intValue(), valueToBytes(value)); } else { cluster.set(bytes, valueToBytes(value)); } } } finally { close(jedis); } } private void jedisUpdate(String key, Object value) { Jedis jedis = getJedis(); try { byte[] bytes = keyToBytes(key); if (value == null) { jedis.del(bytes); } else { Long ttl = jedis.pttl(bytes); if (ttl > 0) { jedis.psetex(bytes, ttl, valueToBytes(value)); } else { jedis.set(bytes, valueToBytes(value)); } } } finally { close(jedis); } } /** * 存放 key value 對到 redis,並將 key 的生存時間設爲 seconds (以秒爲單位)。 若是 key 已經存在, SETEX * 命令將覆寫舊值。 */ public String setex(String key, int seconds, Object value) { return isCluster ? clusterSetex(key, seconds, value) : jedisSetex(key, seconds, value); } public String clusterSetex(String key, int seconds, Object value) { if (value == null) { cluster.del(keyToBytes(key)); return null; } return cluster.setex(keyToBytes(key), seconds, valueToBytes(value)); } public String jedisSetex(String key, int seconds, Object value) { Jedis jedis = getJedis(); try { if (value == null) { jedis.del(keyToBytes(key)); return null; } return jedis.setex(keyToBytes(key), seconds, valueToBytes(value)); } finally { close(jedis); } } /** * 返回 key 所關聯的 value 值 若是 key 不存在那麼返回特殊值 nil 。 */ @SuppressWarnings("unchecked") public <T> T get(String key) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.get(keyToBytes(key))); } finally { close(jedis); } } /** * 返回 key 所關聯的 value 值 若是 key 不存在那麼返回特殊值 nil 。 */ @SuppressWarnings("unchecked") public <T> List<T> getList(List<String> keys) { if (keys == null) { return Collections.emptyList(); } Jedis jedis = getJedis(); try { List<T> list = new ArrayList<T>(); for (String key : keys) { list.add((T) valueFromBytes(jedis.get(keyToBytes(key)))); } return list; } finally { close(jedis); } } /** * 刪除給定的一個 key 不存在的 key 會被忽略。 */ public long del(String key) { Jedis jedis = getJedis(); try { return jedis.del(keyToBytes(key)); } finally { close(jedis); } } /** * 刪除給定的多個 key 不存在的 key 會被忽略。 * * @param <T> */ public <T> long del(List<T> keys) { if (keys == null) { return 0; } Jedis jedis = getJedis(); try { return jedis.del(keysToBytesList(keys)); } finally { close(jedis); } } /** * 刪除給定的多個 key 開頭的 * * @param <T> */ public void clear(String region) { Jedis jedis = getJedis(); try { Set<String> keys = jedis.keys(region + ":*"); if (keys == null || keys.size() == 0) { return; } jedis.del(keysToBytesSet(keys)); } finally { close(jedis); } } /** * 刪除給定的多個 key 不存在的 key 會被忽略。 */ public long del(String... keys) { if (keys == null) { return 0; } Jedis jedis = getJedis(); try { return jedis.del(keysToBytesArray(keys)); } finally { close(jedis); } } /** * 查找全部符合給定模式 pattern 的 key 。 KEYS * 匹配數據庫中全部 key 。 KEYS h?llo 匹配 hello , * hallo 和 hxllo 等。 KEYS h*llo 匹配 hllo 和 heeeeello 等。 KEYS h[ae]llo 匹配 hello * 和 hallo ,但不匹配 hillo 。 特殊符號用 \ 隔開 */ public Set<String> keys(String pattern) { Jedis jedis = getJedis(); try { return jedis.keys(pattern); } finally { close(jedis); } } /** * 同時設置一個或多個 key-value 對。 若是某個給定 key 已經存在,那麼 MSET * 會用新值覆蓋原來的舊值,若是這不是你所但願的效果,請考慮使用 MSETNX 命令:它只會在全部給定 key 都不存在的狀況下進行設置操做。 * MSET 是一個原子性(atomic)操做,全部給定 key 都會在同一時間內被設置,某些給定 key 被更新而另外一些給定 key * 沒有改變的狀況,不可能發生。 * * <pre> * 例子: * Cache cache = RedisKit.use(); // 使用 Redis 的 cache * cache.mset("k1", "v1", "k2", "v2"); // 放入多個 key value 鍵值對 * List list = cache.mget("k1", "k2"); // 利用多個鍵值獲得上面代碼放入的值 * </pre> */ public String mset(String... keysValues) { if (keysValues.length % 2 != 0) throw new IllegalArgumentException("wrong number of arguments for met, keysValues length can not be odd"); Jedis jedis = getJedis(); try { byte[][] kv = new byte[keysValues.length][]; for (int i = 0; i < keysValues.length; i++) { if (i % 2 == 0) kv[i] = keyToBytes(keysValues[i]); else kv[i] = valueToBytes(keysValues[i]); } return jedis.mset(kv); } finally { close(jedis); } } /** * 返回全部(一個或多個)給定 key 的值。 若是給定的 key 裏面,有某個 key 不存在,那麼這個 key 返回特殊值 nil * 。所以,該命令永不失敗。 */ @SuppressWarnings("rawtypes") public List mget(String... keys) { Jedis jedis = getJedis(); try { byte[][] keysBytesArray = keysToBytesArray(keys); List<byte[]> data = jedis.mget(keysBytesArray); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 將 key 中儲存的數字值減一。 若是 key 不存在,那麼 key 的值會先被初始化爲 0 ,而後再執行 DECR 操做。 * 若是值包含錯誤的類型,或字符串類型的值不能表示爲數字,那麼返回一個錯誤。 本操做的值限制在 64 位(bit)有符號數字表示以內。 * 關於遞增(increment) / 遞減(decrement)操做的更多信息,請參見 INCR 命令。 */ public Long decr(String key) { Jedis jedis = getJedis(); try { return jedis.decr(keyToBytes(key)); } finally { close(jedis); } } /** * 將 key 所儲存的值減去減量 decrement 。 若是 key 不存在,那麼 key 的值會先被初始化爲 0 ,而後再執行 DECRBY * 操做。 若是值包含錯誤的類型,或字符串類型的值不能表示爲數字,那麼返回一個錯誤。 本操做的值限制在 64 位(bit)有符號數字表示以內。 * 關於更多遞增(increment) / 遞減(decrement)操做的更多信息,請參見 INCR 命令。 */ public Long decrBy(String key, long longValue) { Jedis jedis = getJedis(); try { return jedis.decrBy(keyToBytes(key), longValue); } finally { close(jedis); } } /** * 將 key 中儲存的數字值增一。 若是 key 不存在,那麼 key 的值會先被初始化爲 0 ,而後再執行 INCR 操做。 * 若是值包含錯誤的類型,或字符串類型的值不能表示爲數字,那麼返回一個錯誤。 本操做的值限制在 64 位(bit)有符號數字表示以內。 */ public Long incr(String key) { Jedis jedis = getJedis(); try { return jedis.incr(keyToBytes(key)); } finally { close(jedis); } } /** * 將 key 所儲存的值加上增量 increment 。 若是 key 不存在,那麼 key 的值會先被初始化爲 0 ,而後再執行 INCRBY * 命令。 若是值包含錯誤的類型,或字符串類型的值不能表示爲數字,那麼返回一個錯誤。 本操做的值限制在 64 位(bit)有符號數字表示以內。 * 關於遞增(increment) / 遞減(decrement)操做的更多信息,參見 INCR 命令。 */ public Long incrBy(String key, long longValue) { Jedis jedis = getJedis(); try { return jedis.incrBy(keyToBytes(key), longValue); } finally { close(jedis); } } /** * 檢查給定 key 是否存在。 */ public boolean exists(String key) { Jedis jedis = getJedis(); try { return jedis.exists(keyToBytes(key)); } finally { close(jedis); } } /** * 從當前數據庫中隨機返回(不刪除)一個 key 。 */ public String randomKey() { Jedis jedis = getJedis(); try { return jedis.randomKey(); } finally { close(jedis); } } /** * 將 key 更名爲 newkey 。 當 key 和 newkey 相同,或者 key 不存在時,返回一個錯誤。 當 newkey 已經存在時, * RENAME 命令將覆蓋舊值。 */ public String rename(String oldkey, String newkey) { Jedis jedis = getJedis(); try { return jedis.rename(keyToBytes(oldkey), keyToBytes(newkey)); } finally { close(jedis); } } /** * 將當前數據庫的 key 移動到給定的數據庫 db 當中。 若是當前數據庫(源數據庫)和給定數據庫(目標數據庫)有相同名字的給定 key ,或者 * key 不存在於當前數據庫,那麼 MOVE 沒有任何效果。 所以,也能夠利用這一特性,將 MOVE * 看成鎖(locking)原語(primitive)。 */ public Long move(String key, int dbIndex) { Jedis jedis = getJedis(); try { return jedis.move(keyToBytes(key), dbIndex); } finally { close(jedis); } } /** * 將 key 原子性地從當前實例傳送到目標實例的指定數據庫上,一旦傳送成功, key 保證會出如今目標實例上,而當前實例上的 key 會被刪除。 */ public String migrate(String host, int port, String key, int destinationDb, int timeout) { Jedis jedis = getJedis(); try { return jedis.migrate(valueToBytes(host), port, keyToBytes(key), destinationDb, timeout); } finally { close(jedis); } } /** * 切換到指定的數據庫,數據庫索引號 index 用數字值指定,以 0 做爲起始索引值。 默認使用 0 號數據庫。 注意:在 Jedis * 對象被關閉時,數據庫又會從新被設置爲初始值,因此本方法 select(...) 正常工做須要使用以下方式之一: 1:使用 * RedisInterceptor,在本線程內共享同一個 Jedis 對象 2:使用 Redis.call(ICallback) 進行操做 * 3:自行獲取 Jedis 對象進行操做 */ public String select(int databaseIndex) { Jedis jedis = getJedis(); try { return jedis.select(databaseIndex); } finally { close(jedis); } } /** * 爲給定 key 設置生存時間,當 key 過時時(生存時間爲 0 ),它會被自動刪除。 在 Redis 中,帶有生存時間的 key * 被稱爲『易失的』(volatile)。 */ public Long expire(String key, int seconds) { Jedis jedis = getJedis(); try { return jedis.expire(keyToBytes(key), seconds); } finally { close(jedis); } } /** * EXPIREAT 的做用和 EXPIRE 相似,都用於爲 key 設置生存時間。不一樣在於 EXPIREAT 命令接受的時間參數是 UNIX * 時間戳(unix timestamp)。 */ public Long expireAt(String key, long unixTime) { Jedis jedis = getJedis(); try { return jedis.expireAt(keyToBytes(key), unixTime); } finally { close(jedis); } } /** * 這個命令和 EXPIRE 命令的做用相似,可是它以毫秒爲單位設置 key 的生存時間,而不像 EXPIRE 命令那樣,以秒爲單位。 */ public Long pexpire(String key, long milliseconds) { Jedis jedis = getJedis(); try { return jedis.pexpire(keyToBytes(key), milliseconds); } finally { close(jedis); } } /** * 這個命令和 EXPIREAT 命令相似,但它以毫秒爲單位設置 key 的過時 unix 時間戳,而不是像 EXPIREAT 那樣,以秒爲單位。 */ public Long pexpireAt(String key, long millisecondsTimestamp) { Jedis jedis = getJedis(); try { return jedis.pexpireAt(keyToBytes(key), millisecondsTimestamp); } finally { close(jedis); } } /** * 將給定 key 的值設爲 value ,並返回 key 的舊值(old value)。 當 key 存在但不是字符串類型時,返回一個錯誤。 */ @SuppressWarnings("unchecked") public <T> T getSet(String key, Object value) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.getSet(keyToBytes(key), valueToBytes(value))); } finally { close(jedis); } } /** * 移除給定 key 的生存時間,將這個 key 從『易失的』(帶生存時間 key )轉換成『持久的』(一個不帶生存時間、永不過時的 key )。 */ public Long persist(String key) { Jedis jedis = getJedis(); try { return jedis.persist(keyToBytes(key)); } finally { close(jedis); } } /** * 返回 key 所儲存的值的類型。 */ public String type(String key) { Jedis jedis = getJedis(); try { return jedis.type(keyToBytes(key)); } finally { close(jedis); } } /** * 以秒爲單位,返回給定 key 的剩餘生存時間(TTL, time to live)。 */ public Long ttl(String key) { Jedis jedis = getJedis(); try { return jedis.ttl(keyToBytes(key)); } finally { close(jedis); } } /** * 這個命令相似於 TTL 命令,但它以毫秒爲單位返回 key 的剩餘生存時間,而不是像 TTL 命令那樣,以秒爲單位。 */ public Long pttl(String key) { Jedis jedis = getJedis(); try { return jedis.pttl(keyToBytes(key)); } finally { close(jedis); } } /** * 對象被引用的數量 */ public Long objectRefcount(String key) { Jedis jedis = getJedis(); try { return jedis.objectRefcount(keyToBytes(key)); } finally { close(jedis); } } /** * 對象沒有被訪問的空閒時間 */ public Long objectIdletime(String key) { Jedis jedis = getJedis(); try { return jedis.objectIdletime(keyToBytes(key)); } finally { close(jedis); } } /** * 將哈希表 key 中的域 field 的值設爲 value 。 若是 key 不存在,一個新的哈希表被建立並進行 HSET 操做。 若是域 * field 已經存在於哈希表中,舊值將被覆蓋。 */ public Long hset(String key, Object field, Object value) { Jedis jedis = getJedis(); try { return jedis.hset(keyToBytes(key), keyToBytes(field), valueToBytes(value)); } finally { close(jedis); } } /** * 將哈希表 key 中的域 field 的值設爲 value 。並設置超時時間 若是 key 不存在,一個新的哈希表被建立並進行 HSET 操做。 若是域 * field 已經存在於哈希表中,舊值將被覆蓋。 * @return */ public Long hsetEx(String key, Object field, Object value, int expire) { Jedis jedis = getJedis(); try { Long hset = jedis.hset(keyToBytes(key), keyToBytes(field), valueToBytes(value)); jedis.expire(keyToBytes(key + ":" + field), expire); return hset; } finally { close(jedis); } } /** * 同時將多個 field-value (域-值)對設置到哈希表 key 中。 此命令會覆蓋哈希表中已存在的域。 若是 key * 不存在,一個空哈希表被建立並執行 HMSET 操做。 */ public String hmset(String key, Map<Object, Object> hash) { Jedis jedis = getJedis(); try { Map<byte[], byte[]> para = new HashMap<byte[], byte[]>(); for (Entry<Object, Object> e : hash.entrySet()) para.put(keyToBytes(e.getKey()), valueToBytes(e.getValue())); return jedis.hmset(keyToBytes(key), para); } finally { close(jedis); } } /** * 返回哈希表 key 中給定域 field 的值。 */ @SuppressWarnings("unchecked") public <T> T hget(String key, Object field) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.hget(keyToBytes(key), keyToBytes(field))); } finally { close(jedis); } } /** * 返回哈希表 key 中,一個或多個給定域的值。 若是給定的域不存在於哈希表,那麼返回一個 nil 值。 由於不存在的 key * 被看成一個空哈希表來處理,因此對一個不存在的 key 進行 HMGET 操做將返回一個只帶有 nil 值的表。 */ @SuppressWarnings("rawtypes") public List hmget(String key, Object... fields) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.hmget(keyToBytes(key), keysToBytesArray(fields)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 刪除哈希表 key 中的一個或多個指定域,不存在的域將被忽略。 */ public Long hdel(String key, Object... fields) { Jedis jedis = getJedis(); try { return jedis.hdel(keyToBytes(key), keysToBytesArray(fields)); } finally { close(jedis); } } /** * 查看哈希表 key 中,給定域 field 是否存在。 */ public boolean hexists(String key, Object field) { Jedis jedis = getJedis(); try { return jedis.hexists(keyToBytes(key), keyToBytes(field)); } finally { close(jedis); } } /** * 返回哈希表 key 中,全部的域和值。 在返回值裏,緊跟每一個域名(field * name)以後是域的值(value),因此返回值的長度是哈希表大小的兩倍。 */ @SuppressWarnings("rawtypes") public Map hgetAll(String key) { Jedis jedis = getJedis(); try { Map<byte[], byte[]> data = jedis.hgetAll(keyToBytes(key)); Map<Object, Object> result = new HashMap<Object, Object>(); for (Entry<byte[], byte[]> e : data.entrySet()) result.put(keyFromBytes(e.getKey()), valueFromBytes(e.getValue())); return result; } finally { close(jedis); } } /** * 返回哈希表 key 中全部域的值。 */ @SuppressWarnings("rawtypes") public List hvals(String key) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.hvals(keyToBytes(key)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 返回哈希表 key 中的全部域。 */ public Set<String> hkeys(String key) { Jedis jedis = getJedis(); try { Set<byte[]> keySet = jedis.hkeys(keyToBytes(key)); return keySetFromBytesSet(keySet); // 返回 key 的方法不能使用 // valueSetFromBytesSet(...) } finally { close(jedis); } } /** * 返回哈希表 key 中域的數量。 */ public Long hlen(String key) { Jedis jedis = getJedis(); try { return jedis.hlen(keyToBytes(key)); } finally { close(jedis); } } /** * 返回列表 key 中,下標爲 index 的元素。 下標(index)參數 start 和 stop 都以 0 爲底,也就是說,以 0 * 表示列表的第一個元素,以 1 表示列表的第二個元素,以此類推。 你也可使用負數下標,以 -1 表示列表的最後一個元素, -2 * 表示列表的倒數第二個元素,以此類推。 若是 key 不是列表類型,返回一個錯誤。 */ @SuppressWarnings("unchecked") /** * 返回列表 key 中,下標爲 index 的元素。 下標(index)參數 start 和 stop 都以 0 爲底,也就是說,以 0 * 表示列表的第一個元素, 以 1 表示列表的第二個元素,以此類推。 你也可使用負數下標,以 -1 表示列表的最後一個元素, -2 * 表示列表的倒數第二個元素,以此類推。 若是 key 不是列表類型,返回一個錯誤。 */ public <T> T lindex(String key, long index) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.lindex(keyToBytes(key), index)); } finally { close(jedis); } } /** * 獲取記數器的值 */ public Long getCounter(String key) { Jedis jedis = getJedis(); try { return Long.parseLong((String) jedis.get(key.toString())); } finally { close(jedis); } } /** * 返回列表 key 的長度。 若是 key 不存在,則 key 被解釋爲一個空列表,返回 0 . 若是 key 不是列表類型,返回一個錯誤。 */ public Long llen(String key) { Jedis jedis = getJedis(); try { return jedis.llen(keyToBytes(key)); } finally { close(jedis); } } /** * 移除並返回列表 key 的頭元素。 */ @SuppressWarnings("unchecked") public <T> T lpop(String key) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.lpop(keyToBytes(key))); } finally { close(jedis); } } /** * 將一個或多個值 value 插入到列表 key 的表頭 若是有多個 value 值,那麼各個 value 值按從左到右的順序依次插入到表頭: * 好比說, 對空列表 mylist 執行命令 LPUSH mylist a b c ,列表的值將是 c b a , 這等同於原子性地執行 LPUSH * mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三個命令。 若是 key 不存在,一個空列表會被建立並執行 * LPUSH 操做。 當 key 存在但不是列表類型時,返回一個錯誤。 */ public Long lpush(String key, Object... values) { Jedis jedis = getJedis(); try { return jedis.lpush(keyToBytes(key), valuesToBytesArray(values)); } finally { close(jedis); } } /** * 將列表 key 下標爲 index 的元素的值設置爲 value 。 當 index 參數超出範圍,或對一個空列表( key 不存在)進行 * LSET 時,返回一個錯誤。 關於列表下標的更多信息,請參考 LINDEX 命令。 */ public String lset(String key, long index, Object value) { Jedis jedis = getJedis(); try { return jedis.lset(keyToBytes(key), index, valueToBytes(value)); } finally { close(jedis); } } /** * 根據參數 count 的值,移除列表中與參數 value 相等的元素。 count 的值能夠是如下幾種: count > 0 : * 從表頭開始向表尾搜索,移除與 value 相等的元素,數量爲 count 。 count < 0 : 從表尾開始向表頭搜索,移除與 value * 相等的元素,數量爲 count 的絕對值。 count = 0 : 移除表中全部與 value 相等的值。 */ public Long lrem(String key, long count, Object value) { Jedis jedis = getJedis(); try { return jedis.lrem(keyToBytes(key), count, valueToBytes(value)); } finally { close(jedis); } } /** * 返回列表 key 中指定區間內的元素,區間以偏移量 start 和 stop 指定。 下標(index)參數 start 和 stop 都以 0 * 爲底,也就是說,以 0 表示列表的第一個元素,以 1 表示列表的第二個元素,以此類推。 你也可使用負數下標,以 -1 表示列表的最後一個元素, * -2 表示列表的倒數第二個元素,以此類推。 * * <pre> * 例子: * 獲取 list 中全部數據:cache.lrange(listKey, 0, -1); * 獲取 list 中下標 1 到 3 的數據: cache.lrange(listKey, 1, 3); * </pre> */ @SuppressWarnings("rawtypes") public List lrange(String key, long start, long end) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.lrange(keyToBytes(key), start, end); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 對一個列表進行修剪(trim),就是說,讓列表只保留指定區間內的元素,不在指定區間以內的元素都將被刪除。 舉個例子,執行命令 LTRIM list * 0 2 ,表示只保留列表 list 的前三個元素,其他元素所有刪除。 下標(index)參數 start 和 stop 都以 0 * 爲底,也就是說,以 0 表示列表的第一個元素,以 1 表示列表的第二個元素,以此類推。 你也可使用負數下標,以 -1 表示列表的最後一個元素, * -2 表示列表的倒數第二個元素,以此類推。 當 key 不是列表類型時,返回一個錯誤。 */ public String ltrim(String key, long start, long end) { Jedis jedis = getJedis(); try { return jedis.ltrim(keyToBytes(key), start, end); } finally { close(jedis); } } /** * 移除並返回列表 key 的尾元素。 */ @SuppressWarnings("unchecked") public <T> T rpop(String key) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.rpop(keyToBytes(key))); } finally { close(jedis); } } /** * 命令 RPOPLPUSH 在一個原子時間內,執行如下兩個動做: 將列表 source 中的最後一個元素(尾元素)彈出,並返回給客戶端。 將 * source 彈出的元素插入到列表 destination ,做爲 destination 列表的的頭元素。 */ @SuppressWarnings("unchecked") public <T> T rpoplpush(String srcKey, String dstKey) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.rpoplpush(keyToBytes(srcKey), keyToBytes(dstKey))); } finally { close(jedis); } } /** * 將一個或多個值 value 插入到列表 key 的表尾(最右邊)。 若是有多個 value 值,那麼各個 value * 值按從左到右的順序依次插入到表尾:好比 對一個空列表 mylist 執行 RPUSH mylist a b c ,得出的結果列表爲 a b c , * 等同於執行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。 若是 key * 不存在,一個空列表會被建立並執行 RPUSH 操做。 當 key 存在但不是列表類型時,返回一個錯誤。 */ public Long rpush(String key, Object... values) { Jedis jedis = getJedis(); try { return jedis.rpush(keyToBytes(key), valuesToBytesArray(values)); } finally { close(jedis); } } /** * BLPOP 是列表的阻塞式(blocking)彈出原語。 它是 LPOP 命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,鏈接將被 * BLPOP 命令阻塞,直到等待超時或發現可彈出元素爲止。 當給定多個 key 參數時,按參數 key * 的前後順序依次檢查各個列表,彈出第一個非空列表的頭元素。 */ @SuppressWarnings("rawtypes") public List blpop(String... keys) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.blpop(keysToBytesArray(keys)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * BLPOP 是列表的阻塞式(blocking)彈出原語。 它是 LPOP 命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,鏈接將被 * BLPOP 命令阻塞,直到等待超時或發現可彈出元素爲止。 當給定多個 key 參數時,按參數 key * 的前後順序依次檢查各個列表,彈出第一個非空列表的頭元素。 */ @SuppressWarnings("rawtypes") public List blpop(int timeout, String... keys) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.blpop(timeout, keysToBytesArray(keys)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * BRPOP 是列表的阻塞式(blocking)彈出原語。 它是 RPOP 命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,鏈接將被 * BRPOP 命令阻塞,直到等待超時或發現可彈出元素爲止。 當給定多個 key 參數時,按參數 key * 的前後順序依次檢查各個列表,彈出第一個非空列表的尾部元素。 關於阻塞操做的更多信息,請查看 BLPOP 命令, BRPOP 除了彈出元素的位置和 * BLPOP 不一樣以外,其餘表現一致。 */ @SuppressWarnings("rawtypes") public List brpop(String... keys) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.brpop(keysToBytesArray(keys)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * BRPOP 是列表的阻塞式(blocking)彈出原語。 它是 RPOP 命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,鏈接將被 * BRPOP 命令阻塞,直到等待超時或發現可彈出元素爲止。 當給定多個 key 參數時,按參數 key * 的前後順序依次檢查各個列表,彈出第一個非空列表的尾部元素。 關於阻塞操做的更多信息,請查看 BLPOP 命令, BRPOP 除了彈出元素的位置和 * BLPOP 不一樣以外,其餘表現一致。 */ @SuppressWarnings("rawtypes") public List brpop(int timeout, String... keys) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.brpop(timeout, keysToBytesArray(keys)); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 使用客戶端向 Redis 服務器發送一個 PING ,若是服務器運做正常的話,會返回一個 PONG 。 * 一般用於測試與服務器的鏈接是否仍然生效,或者用於測量延遲值。 */ public String ping() { Jedis jedis = getJedis(); try { return jedis.ping(); } finally { close(jedis); } } /** * 將一個或多個 member 元素加入到集合 key 當中,已經存在於集合的 member 元素將被忽略。 假如 key 不存在,則建立一個只包含 * member 元素做成員的集合。 當 key 不是集合類型時,返回一個錯誤。 */ public Long sadd(String key, Object... members) { Jedis jedis = getJedis(); try { return jedis.sadd(keyToBytes(key), valuesToBytesArray(members)); } finally { close(jedis); } } /** * 返回集合 key 的基數(集合中元素的數量)。 */ public Long scard(String key) { Jedis jedis = getJedis(); try { return jedis.scard(keyToBytes(key)); } finally { close(jedis); } } /** * 移除並返回集合中的一個隨機元素。 若是隻想獲取一個隨機元素,但不想該元素從集合中被移除的話,可使用 SRANDMEMBER 命令。 */ @SuppressWarnings("unchecked") public <T> T spop(String key) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.spop(keyToBytes(key))); } finally { close(jedis); } } /** * 返回集合 key 中的全部成員。 不存在的 key 被視爲空集合。 */ @SuppressWarnings("rawtypes") public Set smembers(String key) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.smembers(keyToBytes(key)); Set<Object> result = new HashSet<Object>(); valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 判斷 member 元素是否集合 key 的成員。 */ public boolean sismember(String key, Object member) { Jedis jedis = getJedis(); try { return jedis.sismember(keyToBytes(key), valueToBytes(member)); } finally { close(jedis); } } /** * 返回多個集合的交集,多個集合由 keys 指定 */ @SuppressWarnings("rawtypes") public Set sinter(String... keys) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.sinter(keysToBytesArray(keys)); Set<Object> result = new HashSet<Object>(); valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 返回集合中的一個隨機元素。 */ @SuppressWarnings("unchecked") public <T> T srandmember(String key) { Jedis jedis = getJedis(); try { return (T) valueFromBytes(jedis.srandmember(keyToBytes(key))); } finally { close(jedis); } } /** * 返回集合中的 count 個隨機元素。 從 Redis 2.6 版本開始, SRANDMEMBER 命令接受可選的 count 參數: 若是 * count 爲正數,且小於集合基數,那麼命令返回一個包含 count 個元素的數組,數組中的元素各不相同。 若是 count * 大於等於集合基數,那麼返回整個集合。 若是 count 爲負數,那麼命令返回一個數組,數組中的元素可能會重複出現屢次,而數組的長度爲 count * 的絕對值。 該操做和 SPOP 類似,但 SPOP 將隨機元素從集合中移除並返回,而 SRANDMEMBER * 則僅僅返回隨機元素,而不對集合進行任何改動。 */ @SuppressWarnings("rawtypes") public List srandmember(String key, int count) { Jedis jedis = getJedis(); try { List<byte[]> data = jedis.srandmember(keyToBytes(key), count); return valueListFromBytesList(data); } finally { close(jedis); } } /** * 移除集合 key 中的一個或多個 member 元素,不存在的 member 元素會被忽略。 */ public Long srem(String key, Object... members) { Jedis jedis = getJedis(); try { return jedis.srem(keyToBytes(key), valuesToBytesArray(members)); } finally { close(jedis); } } /** * 返回多個集合的並集,多個集合由 keys 指定 不存在的 key 被視爲空集。 */ @SuppressWarnings("rawtypes") public Set sunion(String... keys) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.sunion(keysToBytesArray(keys)); Set<Object> result = new HashSet<Object>(); valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 返回一個集合的所有成員,該集合是全部給定集合之間的差集。 不存在的 key 被視爲空集。 */ @SuppressWarnings("rawtypes") public Set sdiff(String... keys) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.sdiff(keysToBytesArray(keys)); Set<Object> result = new HashSet<Object>(); valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 將一個或多個 member 元素及其 score 值加入到有序集 key 當中。 若是某個 member 已是有序集的成員,那麼更新這個 * member 的 score 值, 並經過從新插入這個 member 元素,來保證該 member 在正確的位置上。 */ public Long zadd(String key, double score, Object member) { Jedis jedis = getJedis(); try { return jedis.zadd(keyToBytes(key), score, valueToBytes(member)); } finally { close(jedis); } } public Long zadd(String key, Map<Object, Double> scoreMembers) { Jedis jedis = getJedis(); try { Map<byte[], Double> para = new HashMap<byte[], Double>(); for (Entry<Object, Double> e : scoreMembers.entrySet()) para.put(valueToBytes(e.getKey()), e.getValue()); // valueToBytes // is // important return jedis.zadd(keyToBytes(key), para); } finally { close(jedis); } } /** * 返回有序集 key 的基數。 */ public Long zcard(String key) { Jedis jedis = getJedis(); try { return jedis.zcard(keyToBytes(key)); } finally { close(jedis); } } /** * 返回有序集 key 中, score 值在 min 和 max 之間(默認包括 score 值等於 min 或 max )的成員的數量。 關於參數 * min 和 max 的詳細使用方法,請參考 ZRANGEBYSCORE 命令。 */ public Long zcount(String key, double min, double max) { Jedis jedis = getJedis(); try { return jedis.zcount(keyToBytes(key), min, max); } finally { close(jedis); } } /** * 爲有序集 key 的成員 member 的 score 值加上增量 increment 。 */ public Double zincrby(String key, double score, Object member) { Jedis jedis = getJedis(); try { return jedis.zincrby(keyToBytes(key), score, valueToBytes(member)); } finally { close(jedis); } } /** * 返回有序集 key 中,指定區間內的成員。 其中成員的位置按 score 值遞增(從小到大)來排序。 具備相同 score * 值的成員按字典序(lexicographical order )來排列。 若是你須要成員按 score 值遞減(從大到小)來排列,請使用 * ZREVRANGE 命令。 */ @SuppressWarnings("rawtypes") public Set zrange(String key, long start, long end) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.zrange(keyToBytes(key), start, end); Set<Object> result = new LinkedHashSet<Object>(); // 有序集合必須 // LinkedHashSet valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 返回有序集 key 中,指定區間內的成員。 其中成員的位置按 score 值遞減(從大到小)來排列。 具備相同 score * 值的成員按字典序的逆序(reverse lexicographical order)排列。 除了成員按 score 值遞減的次序排列這一點外, * ZREVRANGE 命令的其餘方面和 ZRANGE 命令同樣。 */ @SuppressWarnings("rawtypes") public Set zrevrange(String key, long start, long end) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.zrevrange(keyToBytes(key), start, end); Set<Object> result = new LinkedHashSet<Object>(); // 有序集合必須 // LinkedHashSet valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 返回有序集 key 中,全部 score 值介於 min 和 max 之間(包括等於 min 或 max )的成員。 有序集成員按 score * 值遞增(從小到大)次序排列。 */ @SuppressWarnings("rawtypes") public Set zrangeByScore(String key, double min, double max) { Jedis jedis = getJedis(); try { Set<byte[]> data = jedis.zrangeByScore(keyToBytes(key), min, max); Set<Object> result = new LinkedHashSet<Object>(); // 有序集合必須 // LinkedHashSet valueSetFromBytesSet(data, result); return result; } finally { close(jedis); } } /** * 返回有序集 key 中成員 member 的排名。其中有序集成員按 score 值遞增(從小到大)順序排列。 排名以 0 爲底,也就是說, * score 值最小的成員排名爲 0 。 使用 ZREVRANK 命令能夠得到成員按 score 值遞減(從大到小)排列的排名。 */ public Long zrank(String key, Object member) { Jedis jedis = getJedis(); try { return jedis.zrank(keyToBytes(key), valueToBytes(member)); } finally { close(jedis); } } /** * 返回有序集 key 中成員 member 的排名。其中有序集成員按 score 值遞減(從大到小)排序。 排名以 0 爲底,也就是說, score * 值最大的成員排名爲 0 。 使用 ZRANK 命令能夠得到成員按 score 值遞增(從小到大)排列的排名。 */ public Long zrevrank(String key, Object member) { Jedis jedis = getJedis(); try { return jedis.zrevrank(keyToBytes(key), valueToBytes(member)); } finally { close(jedis); } } /** * 移除有序集 key 中的一個或多個成員,不存在的成員將被忽略。 當 key 存在但不是有序集類型時,返回一個錯誤。 */ public Long zrem(String key, Object... members) { Jedis jedis = getJedis(); try { return jedis.zrem(keyToBytes(key), valuesToBytesArray(members)); } finally { close(jedis); } } /** * 返回有序集 key 中,成員 member 的 score 值。 若是 member 元素不是有序集 key 的成員,或 key 不存在,返回 * nil 。 */ public Double zscore(String key, Object member) { Jedis jedis = getJedis(); try { return jedis.zscore(keyToBytes(key), valueToBytes(member)); } finally { close(jedis); } } public void subscribe(JedisPubSub jedisPubSub, String... channels) { Jedis jedis = getJedis(); try { jedis.subscribe(jedisPubSub, channels); } finally { close(jedis); } } public void publish(String channel, byte[] message) { Jedis jedis = getJedis(); try { jedis.publish(keyToBytes(channel), message); } finally { close(jedis); } } // --------- public byte[] keyToBytes(String key) { return SafeEncoder.encode(key); } private byte[] keyToBytes(Object key) { return SafeEncoder.encode(key.toString()); } private String keyFromBytes(byte[] bytes) { return SafeEncoder.encode(bytes); } private byte[][] keysToBytesArray(String... keys) { byte[][] result = new byte[keys.length][]; for (int i = 0; i < result.length; i++) result[i] = keyToBytes(keys[i]); return result; } private <T> byte[][] keysToBytesList(List<T> keys) { if (keys == null) { return null; } byte[][] result = new byte[keys.size()][]; for (int i = 0; i < result.length; i++) result[i] = keyToBytes(keys.get(i)); return result; } private <T> byte[][] keysToBytesSet(Set<T> keys) { if (keys == null) { return null; } byte[][] result = new byte[keys.size()][]; int i = 0; for (T key : keys) { result[i++] = keyToBytes(key); } return result; } private byte[][] keysToBytesArray(Object... keys) { byte[][] result = new byte[keys.length][]; for (int i = 0; i < result.length; i++) result[i] = keyToBytes(keys[i]); return result; } private Set<String> keySetFromBytesSet(Set<byte[]> data) { Set<String> result = new HashSet<String>(); for (byte[] keyBytes : data) result.add(keyFromBytes(keyBytes)); return result; } private byte[] valueToBytes(Object object) { return SerializeUtils.fstserialize(object); } protected Object valueFromBytes(byte[] bytes) { if (bytes != null) return SerializeUtils.fstdeserialize(bytes); return null; } private byte[][] valuesToBytesArray(Object... objectArray) { byte[][] data = new byte[objectArray.length][]; for (int i = 0; i < data.length; i++) data[i] = valueToBytes(objectArray[i]); return data; } private void valueSetFromBytesSet(Set<byte[]> data, Set<Object> result) { for (byte[] d : data) result.add(valueFromBytes(d)); } @SuppressWarnings("rawtypes") private List valueListFromBytesList(List<byte[]> data) { List<Object> result = new ArrayList<Object>(); for (byte[] d : data) result.add(valueFromBytes(d)); return result; } public String getName() { return name; } public Jedis getJedis() { Jedis jedis = threadLocalJedis.get(); if (jedis == null) { if (jedisPool != null) { jedis = jedisPool.getResource(); } } return jedis; } public void close(Jedis jedis) { if (threadLocalJedis.get() == null && jedis != null) jedis.close(); } public Jedis getThreadLocalJedis() { return threadLocalJedis.get(); } public void setThreadLocalJedis(Jedis jedis) { threadLocalJedis.set(jedis); } public void removeThreadLocalJedis() { threadLocalJedis.remove(); } public void puffsubscribe(BinaryJedisPubSub jedisPubSub, String... channels) { final byte[][] cs = new byte[channels.length][]; for (int i = 0; i < cs.length; i++) { cs[i] = SafeEncoder.encode(channels[i]); } if (cluster == null) { Jedis jedis = getJedis(); try { jedis.subscribe(jedisPubSub, cs); } finally { close(jedis); } } else { cluster.subscribe(jedisPubSub, cs); } } public void puffpublish(String channel, byte[] message) { if (cluster == null) { Jedis jedis = getJedis(); try { jedis.publish(keyToBytes(channel), message); } finally { close(jedis); } } else { cluster.publish(keyToBytes(channel), message); } } }
相關文章
相關標籤/搜索