Jedis是Redis的Java客户端开发包,具体操作代码如下:
public abstract class RedisCache implements ICache { private static final Logger LOG = LoggerFactory.getLogger(RedisCache.class); public static final int CACHE_RETRY_COUNT = 3; @Resource(name = "persistenceJedisPool") protected ShardedJedisPoolWrapper shardedJedisPoolWrapper = null; protected ShardedJedisPool pool = null; private BeanUtilsBean beanUtilsBean = null; @PostConstruct public void postConstruct() { this.pool = shardedJedisPoolWrapper.getJedisPool(); this.beanUtilsBean = BeanUtilsBean.getInstance(); } public ShardedJedisPool getPool() { return pool; } /** * transaction cache operation * @param key * @throws java.io.IOException */ public void transaction(String key, CacheOperationFactory factory) throws IOException { boolean isFailed = false; ShardedJedis jedis = pool.getResource(); try { Jedis shard = jedis.getShard(key); shard.watch(SafeEncoder.encode(key)); Transaction t = shard.multi(); factory.setJedis(shard); factory.cache(); t.exec(); } catch (JedisException e) { isFailed = true; throw e; } finally { if (isFailed) { pool.returnBrokenResource(jedis); } else { pool.returnResource(jedis); } } } @Override public String set(final String key, final Object value) throws IOException { return new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.set(SafeEncoder.encode(key), SerializerUtil.write(value)); } }.execute(); } @Override public List<String> set(final String[] keys, final Object[] values) throws IOException { if (keys.length != values.length || keys.length == 0) { return null; } return new CacheOperation<List<String>>(CACHE_RETRY_COUNT) { public List<String> cacheExecute(ShardedJedis jedis) throws JedisException, IOException { List<String> results = new ArrayList<String>(keys.length); ArrayList<Response<String>> responses = new ArrayList<Response<String>>(keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); for (int i = 0; i < keys.length; i++) { responses.add(pipeline.set(keys[i], SerializerUtil.write(values[i]))); } pipeline.sync(); for (Response<String> response : responses) { results.add(response.get()); } return results; } }.execute(); } @Override public String set(final String key, final Object value, final int expireTime) throws IOException { return new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.setex(SafeEncoder.encode(key), expireTime, SerializerUtil.write(value)); } }.execute(); } @Override public Long setnx(final String key, final Object o) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.setnx(SafeEncoder.encode(key), SerializerUtil.write(o)); } }.execute(); } @Override public void delete(final String key) throws IOException { new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.getShard(key).del(SafeEncoder.encode(key)); } }.execute(); } @Override public <T> T get(final String key) throws IOException { try { return new CacheOperation<T>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public T cacheExecute(ShardedJedis jedis) throws JedisException, IOException { byte[] a = jedis.get(SafeEncoder.encode(key)); Object t = SerializerUtil.read(a); return (T) t; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when get a object, key: " + key, e); return null; } } public <T> T getSet(final String key, final String value) throws IOException { try { return new CacheOperation<T>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public T cacheExecute(ShardedJedis jedis) throws JedisException, IOException { byte[] result = jedis.getSet(SafeEncoder.encode(key), SafeEncoder.encode(value)); Object t = SerializerUtil.read(result); return (T) t; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when get a object, key: " + key, e); return null; } } @Override public <T> List<T> get(final String[] keys) throws IOException { try { return new CacheOperation<List<T>>(CACHE_RETRY_COUNT) { @SuppressWarnings({ "rawtypes", "unchecked" }) public List<T> cacheExecute(ShardedJedis jedis) throws JedisException, IOException { List<T> ts = new ArrayList<T>(keys.length); List<Response<byte[]>> responses = new ArrayList<Response<byte[]>>(keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); for (String key : keys) { responses.add(pipeline.getByte(key)); } pipeline.sync(); for (Response response : responses) { T t = (T) SerializerUtil.read((byte[]) response.get()); ts.add(t); } return ts; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when get a object, keys: " + keys, e); return null; } } @Override public Long incrby(final String key, final long increment) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.incrBy(SafeEncoder.encode(key), increment); } }.execute(); } @Override public Long decrby(final String key, final long increment) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.decrBy(SafeEncoder.encode(key), increment); } }.execute(); } public void listTrim(final String key, final int start, final int end) throws IOException { new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { jedis.ltrim(key, start, end); return 0L; } }.execute(); } @Override public <T> long listAppend(final String key, final T value) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { if (value == null) { return 0L; } byte[] bytes = SerializerUtil.write(value); return jedis.lpush(SafeEncoder.encode(key), bytes); } }.execute(); } @Override public <T> long listAppend(final String key, final T[] values) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { if (values == null || values.length == 0) { return 0L; } byte[][] bytes = new byte[values.length][]; int lastIndex = bytes.length - 1; for (int i = lastIndex; i >= 0; i--) { bytes[lastIndex - i] = SerializerUtil.write(values[i]); } return jedis.lpush(SafeEncoder.encode(key), bytes); } }.execute(); } @Override public <T> T rPop(final String key) throws IOException { return new CacheOperation<T>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public T cacheExecute(ShardedJedis jedis) throws JedisException, IOException { byte[] bytes = jedis.rpop(SafeEncoder.encode(key)); if (bytes == null) { return null; } return (T) SerializerUtil.read(bytes); } }.execute(); } @Override public <T> void listDel(final String key, final T value) throws IOException { new CacheOperation<Void>(CACHE_RETRY_COUNT, key) { public Void cacheExecute(ShardedJedis jedis) throws JedisException, IOException { if (value == null) { return null; } jedis.lrem(SafeEncoder.encode(key), 1, SerializerUtil.write(value)); return null; } }.execute(); } @Override public <T> void listDel(final String key, final T[] values) throws IOException { new CacheOperation<Void>(CACHE_RETRY_COUNT, key) { public Void cacheExecute(ShardedJedis jedis) throws JedisException, IOException { if (values == null || values.length == 0) { return null; } byte[][] bytes = new byte[values.length][]; int lastIndex = bytes.length - 1; for (int i = lastIndex; i >= 0; i--) { jedis.lrem(SafeEncoder.encode(key), 1, SerializerUtil.write(values[i])); } return null; } }.execute(); } @Override public Long listLength(final String key) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { try { return jedis.llen(SafeEncoder.encode(key)); } catch (Exception e) { LOG.error("cache error when calling listlength, key=" + key, e); return 0L; } } }.execute(); } @Override public <T> List<T> listRange(final String key, final int start, final int end) throws IOException { final int includeEnd = end - 1; if (start < 0 || includeEnd < start) { return Collections.emptyList(); } final List<T> objs = new ArrayList<T>(includeEnd - start + 1); try { return new CacheOperation<List<T>>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public List<T> cacheExecute(ShardedJedis jedis) throws IOException { List<byte[]> values = jedis.lrange(SafeEncoder.encode(key), start, includeEnd); for (byte[] v : values) { try { objs.add((T) SerializerUtil.read(v)); } catch (Exception e) { throw new JedisException(e); } } return objs; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling listRange, key: " + key, e); return objs; } } @Override public long zAdd(final String key, final double score, final Object value) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zadd(SafeEncoder.encode(key), score, SerializerUtil.write(value)); } }.execute(); } @Override public List<Long> zAdd(final String[] keys, final Double[] scores, final Object[] values) throws IOException { if (keys.length != values.length || keys.length != values.length || keys.length == 0) { return null; } try { return new CacheOperation<List<Long>>(CACHE_RETRY_COUNT) { @SuppressWarnings("rawtypes") public List<Long> cacheExecute(ShardedJedis jedis) throws IOException { List<Response<Long>> responses = new ArrayList<Response<Long>>(keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); for (int i = 0; i < keys.length; i++) { responses.add(pipeline.zadd(keys[i], scores[i], SerializerUtil.write(values[i]))); } pipeline.sync(); List<Long> results = new ArrayList<Long>(keys.length); for (Response response : responses) { results.add((Long) response.get()); } return results; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when zAdd, keys: " + keys, e); return null; } } @Override public long zAdd(String key, double score, Object value, long len) throws IOException { long rt = zAdd(key, score, value); ShardedJedis jedis = null; boolean isFailed = false; try { jedis = pool.getResource(); long total = jedis.zcard(SafeEncoder.encode(key)); if (total > len) { jedis.zremrangeByRank(SafeEncoder.encode(key), 0, (int) (total- len - 1)); } } catch (JedisException e) { LOG.error("exception occur when calling zcard, key: " + key, e); isFailed = true; } finally { if (jedis != null) { if (isFailed) { pool.returnBrokenResource(jedis); } else { pool.returnResource(jedis); } } } return rt; } @Override public long zAdd(final String key, final Map<Double, Object> map, long len) throws IOException { long rt = new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { Map<Double, byte[]> resultMap = new HashMap<Double, byte[]>(); for (Double mkey : map.keySet()) { resultMap.put(mkey, SerializerUtil.write(map.get(mkey))); } return jedis.zadd(SafeEncoder.encode(key), resultMap); } }.execute(); ShardedJedis jedis = null; boolean isFailed = false; try { jedis = pool.getResource(); long total = jedis.zcard(SafeEncoder.encode(key)); if (total > len) { jedis.zremrangeByRank(SafeEncoder.encode(key), 0, (int) (total - len - 1)); } } catch (JedisException e) { LOG.error("exception occur when calling zcard, key: " + key, e); isFailed = true; } finally { if (jedis != null) { if (isFailed) { pool.returnBrokenResource(jedis); } else { pool.returnResource(jedis); } } } return rt; } /** * 以Map<Object, Double>的形式批量设置redis缓存,object-member、Double-score, * 当score值有重复时,调用该方法可以避免调用zAdd时map的key冲突 * 注意:当score值大量重复时,循环中会有很多冗余判断,会影响性能 数据太大时,redis处理会失败 */ @Override public long zAddWithMap(final String key, final Map<Object, Double> map, long len) throws IOException { long rt = new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { Long addedNum = 0l; try { while (map.size() > 0) { Map<Double, byte[]> serMap = new HashMap<Double, byte[]>(); Set<Object> keySet = new HashSet<Object>(map.keySet()); int mapSize = 0; for (Object mkey : keySet) { if (!serMap.containsKey(map.get(mkey))) { serMap.put(map.remove(mkey), SerializerUtil.write(mkey)); mapSize++; } if (mapSize >= 10000) { break; } } addedNum += jedis.zadd(SafeEncoder.encode(key), serMap); } // 如果catch异常,删掉key, 因为可能只加了一半, 异常继续往外抛 } catch (IOException e) { jedis.del(key); LOG.warn("Exception when zAddWithMap, key=" + key); throw e; } catch (JedisException e) { jedis.del(key); LOG.warn("Exception when zAddWithMap, key=" + key); throw e; } return addedNum; } }.execute(); ShardedJedis jedis = null; boolean isFailed = false; try { jedis = pool.getResource(); long total = jedis.zcard(SafeEncoder.encode(key)); if (total > len) { jedis.zremrangeByRank(SafeEncoder.encode(key), 0, (int) (total - len - 1)); } } catch (JedisException e) { LOG.error("exception occur when calling zcard, key: " + key, e); isFailed = true; } finally { if (jedis != null) { if (isFailed) { pool.returnBrokenResource(jedis); } else { pool.returnResource(jedis); } } } return rt; } @Override public Double zIncrby(final String key, final long increment, final Object member) throws IOException { return new CacheOperation<Double>(CACHE_RETRY_COUNT, key) { public Double cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zincrby(SafeEncoder.encode(key), increment, SerializerUtil.write(member)); } }.execute(); } @Override public Double zScore(final String key, final Object value) throws IOException { try { return new CacheOperation<Double>(CACHE_RETRY_COUNT, key) { public Double cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zscore(SafeEncoder.encode(key), SerializerUtil.write(value)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zScore, key: " + key, e); return null; } } @Override public long zCard(final String key) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zcard(SafeEncoder.encode(key)); } }.execute(); } @Override public long zCount(final String key, final double min, final double max) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zcount(SafeEncoder.encode(key), min, max); } }.execute(); } @Override public long zRemByValue(final String key, final Object value) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zrem(SafeEncoder.encode(key), SerializerUtil.write(value)); } }.execute(); } @Override public List<Long> zRemByValue(final String[] keys, final Object[] values) throws IOException { if (keys.length != values.length || keys.length != values.length || keys.length == 0) { return null; } try { return new CacheOperation<List<Long>>(CACHE_RETRY_COUNT) { @SuppressWarnings("rawtypes") public List<Long> cacheExecute(ShardedJedis jedis) throws IOException { List<Response<Long>> responses = new ArrayList<Response<Long>>(keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); for (int i = 0; i < keys.length; i++) { responses.add(pipeline.zrem(keys[i], SerializerUtil.write(values[i]))); } pipeline.sync(); List<Long> res = new ArrayList<Long>(keys.length); for (Response response : responses) { res.add((Long) response.get()); } return res; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when zAdd, keys: " + keys, e); return null; } } @Override public long zRemRangeByRank(final String key, final int start, final int end) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zremrangeByRank(SafeEncoder.encode(key), start, end); } }.execute(); } @Override public long zRemRangeByScore(final String key, final double start, final double end) throws IOException { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zremrangeByScore(SafeEncoder.encode(key), start, end); } }.execute(); } @Override public <T> Set<T> zRevRange(final String key, final int start, final int end) throws IOException { final Set<T> objs = new LinkedHashSet<T>(); if (start < 0 || end < start) { return objs; } try { return new CacheOperation<Set<T>>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public Set<T> cacheExecute(ShardedJedis jedis) throws IOException { Set<byte[]> rt = jedis.zrevrange(SafeEncoder.encode(key), start, end); for (byte[] it : rt) { try { objs.add((T) SerializerUtil.read(it)); } catch (Exception e) { throw new JedisException(e); } } return objs; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRevRange, key: " + key, e); return objs; } } @Override public <T> Set<T> zRevRangeByOffset(final String key, final int start, final int end) throws IOException { final Set<T> objs = new LinkedHashSet<T>(); if (start < 0 || end < start) { return objs; } try { return new CacheOperation<Set<T>>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public Set<T> cacheExecute(ShardedJedis jedis) throws IOException { Set<byte[]> rt = jedis.zrevrange(SafeEncoder.encode(key), start, end - 1); for (byte[] it : rt) { try { objs.add((T) SerializerUtil.read(it)); } catch (Exception e) { throw new JedisException(e); } } return objs; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when zRangeByScore, key: " + key, e); return objs; } } @Override public Set<Tuple> zRevWithScores(final String key, final int start, final int end) throws IOException { try { return new CacheOperation<Set<Tuple>>(CACHE_RETRY_COUNT, key) { public Set<Tuple> cacheExecute(ShardedJedis jedis) throws IOException { return jedis.zrevrangeWithScores(SafeEncoder.encode(key), start, end); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRangeByScore, key: " + key, e); return new LinkedHashSet<Tuple>(); } } @Override public <T> Set<T> zRangeByScore(final String key, final double min, final double max, final boolean rev) throws IOException { final Set<T> rt = new LinkedHashSet<T>(); try { return new CacheOperation<Set<T>>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public Set<T> cacheExecute(ShardedJedis jedis) throws IOException { Set<byte[]> ranges; if (!rev) { ranges = jedis.zrangeByScore(SafeEncoder.encode(key), min, max); } else { ranges = jedis.zrevrangeByScore(SafeEncoder.encode(key), max, min); } for (byte[] range : ranges) { try { rt.add((T) SerializerUtil.read(range)); } catch (Exception e) { throw new JedisException(e); } } return rt; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRangeByScore, key: " + key, e); return rt; } } @Override public <T> Set<T> zRangeByScore(final String key, final double min, final double max, final boolean rev, final int offset, final int length) throws IOException { final Set<T> rt = new LinkedHashSet<T>(); try { return new CacheOperation<Set<T>>(CACHE_RETRY_COUNT, key) { @SuppressWarnings("unchecked") public Set<T> cacheExecute(ShardedJedis jedis) throws IOException { Set<byte[]> ranges; if (!rev) { ranges = jedis.zrangeByScore(SafeEncoder.encode(key), min, max, offset, length); } else { ranges = jedis.zrevrangeByScore(SafeEncoder.encode(key), max, min, offset, length); Set<Tuple> tuples = jedis.zrevrangeByScoreWithScores( SafeEncoder.encode(key), min, max, offset, length); for (Tuple tuple : tuples) { LOG.info("{} - {}", SerializerUtil.read(tuple.getBinaryElement()), tuple.getScore()); } } for (byte[] range : ranges) { try { rt.add((T) SerializerUtil.read(range)); } catch (Exception e) { throw new JedisException(e); } } return rt; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRangeByScore, key: " + key, e); return rt; } } @Override public Set<Tuple> zRangeByScoreWithScores(final String key, final double min, final double max, final boolean rev, final int offset, final int length) throws IOException { try { return new CacheOperation<Set<Tuple>>(CACHE_RETRY_COUNT, key) { public Set<Tuple> cacheExecute(ShardedJedis jedis) throws IOException { if (!rev) { return jedis.zrangeByScoreWithScores(SafeEncoder.encode(key), min, max, offset, length); } else { return jedis.zrevrangeByScoreWithScores(SafeEncoder.encode(key), max, min, offset, length); } } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRangeByScoreWithScores, key: " + key, e); return new LinkedHashSet<Tuple>(); } } @Override public List<Set<Tuple>> zRangeByScoreWithScores(final String[] keys, final double min, final double max, final boolean rev, final int offset, final int length) throws IOException { if (keys.length == 0) { return null; } try { return new CacheOperation<List<Set<Tuple>>>(CACHE_RETRY_COUNT) { @SuppressWarnings({ "rawtypes", "unchecked" }) public List<Set<Tuple>> cacheExecute(ShardedJedis jedis) throws IOException { List<Response<Set<Tuple>>> responses = new ArrayList<Response<Set<Tuple>>>(keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); if (!rev) { for (String key : keys) { responses.add(pipeline.zrangeByScoreWithScores(key, min, max, offset, length)); } } else { for (String key : keys) { responses.add(pipeline.zrevrangeByScoreWithScores(key, max, min, offset, length)); } } pipeline.sync(); List<Set<Tuple>> res = new ArrayList<Set<Tuple>>(keys.length); for (Response response : responses) { res.add((Set<Tuple>) response.get()); } return res; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when zRangeByScoreWithScores, keys: " + keys, e); return null; } } @Override public List<Tuple> zMergeRangeByScoreWithScores(final String[] keys, final double min, final double max, final boolean rev, final int offset, final int length) throws IOException { List<Set<Tuple>> sets = zRangeByScoreWithScores(keys, min, max, rev, offset, length); if (CollectionUtils.isEmpty(sets)) { LOG.info("empty result when zMergeRangeByScoreWithScores keys=" + keys); return null; } List<Tuple> tuples = new ArrayList<Tuple>(); for (Set<Tuple> set : sets) { if (CollectionUtils.isEmpty(set)) { continue; } for (Tuple tuple : set) { tuples.add(tuple); } } if (rev) { Collections.sort(tuples, Collections.reverseOrder()); } else { Collections.sort(tuples); } if (tuples.size() <= length) { return tuples; } return tuples.subList(0, length); } @Override public Void hmSet(final String[] keys, final Object[] values, final int expireTime) throws IOException { if (keys.length != values.length || keys.length == 0) { return null; } final List<Map<byte[], byte[]>> maps = new ArrayList<Map<byte[], byte[]>>(); for (Object o : values) { if (o != null) { maps.add(parseObject2Map(o)); } } return new CacheOperation<Void>(CACHE_RETRY_COUNT) { public Void cacheExecute(ShardedJedis jedis) throws JedisException, IOException { ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); int validCount = 0; for (int i = 0; i < keys.length; i++) { if (values[i] != null) { pipeline.hmsetByte(keys[i], maps.get(validCount++)); if (expireTime > 0) { pipeline.expire(keys[i], expireTime); } } } pipeline.sync(); return null; } }.execute(); } @Override public Void hmSet(final String[] keys, final Object[] os) throws IOException { return hmSet(keys, os, -1); } @Override public Void hmSet(final String key, final Object o, final int expireTime) throws IOException { final Map<byte[], byte[]> map = parseObject2Map(o); return new CacheOperation<Void>(CACHE_RETRY_COUNT, key) { public Void cacheExecute(ShardedJedis jedis) throws JedisException, IOException { ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); pipeline.hmsetByte(key, map); if (expireTime > 0) { pipeline.expire(key, expireTime); } pipeline.sync(); return null; } }.execute(); } @Override public String hmSet(final String key, final Object o) throws IOException { final Map<byte[], byte[]> map = parseObject2Map(o); return new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.hmset(SafeEncoder.encode(key), map); } }.execute(); } @Override public void hmSet(final String key, final Map<String, Object> map) throws IOException { if (hExists(key)) { new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws IOException { if (map == null || map.isEmpty()) { return null; } Map<byte[], byte[]> binaryMap = new HashMap<byte[], byte[]>(map.size()); for (Map.Entry<String, Object> entry : map.entrySet()) { binaryMap.put(SerializerUtil.write(entry.getKey()), SerializerUtil.write(entry.getValue())); } return jedis.hmset(SafeEncoder.encode(key), binaryMap); } }.execute(); } } @Override public void hmSetCreateKeyIfNotExists(final String key, final Map<String, Object> map) throws IOException { new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws IOException { if (map == null || map.isEmpty()) { return null; } Map<byte[], byte[]> binaryMap = new HashMap<byte[], byte[]>(map.size()); for (Map.Entry<String, Object> entry : map.entrySet()) { binaryMap.put(SerializerUtil.write(entry.getKey()), SerializerUtil.write(entry.getValue())); } return jedis.hmset(SafeEncoder.encode(key), binaryMap); } }.execute(); } @Override public void hmSetMap(final String key, final Map<String, String> map) throws IOException { new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws IOException { if (map == null || map.isEmpty()) { return null; } Map<byte[], byte[]> binaryMap = new HashMap<byte[], byte[]>(map.size()); for (Map.Entry<String, String> entry : map.entrySet()) { binaryMap.put(SerializerUtil.write(entry.getKey()), SerializerUtil.write(entry.getValue())); } return jedis.hmset(SafeEncoder.encode(key), binaryMap); } }.execute(); } @Override public Map<String, String> hmGetMap(final String key) throws IOException { try { return new CacheOperation<Map<String, String>>(CACHE_RETRY_COUNT, key) { public Map<String, String> cacheExecute(ShardedJedis jedis) throws IOException { Map<byte[], byte[]> all = jedis.hgetAll(SafeEncoder.encode(key)); Map<String, String> map = new HashMap<String, String>(); for (byte[] key : all.keySet()) { String field = (String) SerializerUtil.read(key); String value = String.valueOf(SerializerUtil.read(all.get(key))); map.put(field, value); } return map; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hmGetMap, key: " + key, e); return null; } } /** * 慎用: key不存在时不会创建key 导致操作无效 */ @Override public long hSet(final String key, final String field, final String value) throws IOException { if (hExists(key)) { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hset(SafeEncoder.encode(key), SerializerUtil.write(field), SerializerUtil.write(value)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hSet, key: " + key, e); return 0L; } } return 0L; } /** * 慎用: key不存在时不会创建key 导致操作无效 */ @Override public long hSet(final String key, final String field, final Object object) throws IOException { if (hExists(key)) { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hset(SafeEncoder.encode(key), SerializerUtil.write(field), SerializerUtil.write(object)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hSet, key: " + key, e); return 0L; } } return 0L; } /** * 慎用: key不存在时不会创建key 导致操作无效 */ @Override public long hSetCreateKeyIfNotExist(final String key, final String field, final Object object) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hset(SafeEncoder.encode(key), SerializerUtil.write(field), SerializerUtil.write(object)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hSet, key: " + key, e); return 0L; } } public long hDel(final String key, final String field) throws IOException { if (hExists(key)) { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hdel(SafeEncoder.encode(key), SerializerUtil.write(field)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hSet, key: " + key, e); return 0L; } } return 0L; } @Override public long hSetCreateKeyIfNotExists(final String key, final String field, final String value) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hset(SafeEncoder.encode(key), SerializerUtil.write(field), SerializerUtil.write(value)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when hExists a object, key: " + key, e); return 0L; } } @Override public String hGet(final String key, final String field) throws IOException { try { return new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws IOException { return (String) SerializerUtil.read(jedis.hget( SafeEncoder.encode(key), SerializerUtil.write(field))); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hGet, key: " + key, e); return null; } } public Object hGetObject(final String key, final String field) throws IOException { try { return new CacheOperation<Object>(CACHE_RETRY_COUNT, key) { public Object cacheExecute(ShardedJedis jedis) throws IOException { return SerializerUtil.read(jedis.hget( SafeEncoder.encode(key), SerializerUtil.write(field))); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hGet, key: " + key, e); return null; } } @Override public boolean hExists(final String key) throws IOException { try { return new CacheOperation<Boolean>(CACHE_RETRY_COUNT, key) { public Boolean cacheExecute(ShardedJedis jedis) throws IOException { long len = jedis.hlen(SafeEncoder.encode(key)); return len > 0 ? true : false; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hExists, key: " + key, e); return false; } } public long hLen(final String key) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hlen(SafeEncoder.encode(key)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hExists, key: " + key, e); return 0l; } } /** * remove a object in hash. remove in a transaction, if one field not delete success, then rollback. * @param key * @return * @throws java.io.IOException */ @Override public long hDel(final String key) throws JedisException, IOException { if (key == null || key.trim().length() == 0) { throw new JedisException("no key is null or length of o"); } return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { byte[] byteKey = SafeEncoder.encode(key); Set<byte[]> fields = jedis.hkeys(byteKey); if (fields == null || fields.size() == 0) { return 0L; } return jedis.hdel(byteKey, fields.toArray(new byte[][] {})); } }.execute(); } @Override public Long hIncrBy(final String key, final String field, final int increment) throws JedisException, IOException { return hIncrBy(key, field, increment, EmptyInstance.LONG); } @Override public Long hIncrBy(final String key, final String field, final int increment, final long defaultValue) throws JedisException, IOException { boolean hExists = hExists(key); if (hExists) { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { byte[] bkey = SafeEncoder.encode(key); byte[] bfield = SerializerUtil.write(field); Jedis shard = jedis.getShard(bkey); try { shard.watch(bkey); String wantedValue; Object filedValue = SerializerUtil.read(jedis.hget(bkey, bfield)); if (filedValue != null) { if (filedValue instanceof Integer) { wantedValue = String.valueOf(((Integer) filedValue) + increment); } else if (filedValue instanceof Long) { wantedValue = String.valueOf(((Long) filedValue) + increment); } else if (filedValue instanceof String) { String filedValueStr = (String) filedValue; if (org.apache.commons.lang.StringUtils.isNotEmpty(filedValueStr)) { wantedValue = String.valueOf(Long.parseLong(filedValueStr) + increment); } else { wantedValue = String.valueOf(defaultValue + increment); } } else { wantedValue = String.valueOf(defaultValue + increment); } } else { wantedValue = String.valueOf(defaultValue + increment); } Transaction t = shard.multi(); Response<Long> rt = t.hset(bkey, bfield, SerializerUtil.write(wantedValue)); List<Object> list = t.exec(); if (list == null) { shard.unwatch(); throw new JedisDataException("Transaction failed"); } for (Object obj : list) { if (obj instanceof JedisException) { throw (JedisException) obj; } } return rt.get(); } catch (Exception e) { shard.unwatch(); throw new JedisException(e); } } }.execute(); } else { return 0L; } } @Override public Object hmGet(final String key, final Class<?> clazz) throws IOException { try { Map<byte[], byte[]> map = new CacheOperation<Map<byte[], byte[]>>(CACHE_RETRY_COUNT, key) { public Map<byte[], byte[]> cacheExecute(ShardedJedis jedis) throws IOException { Map<byte[], byte[]> all = jedis.hgetAll(SafeEncoder.encode(key)); return all; } }.execute(); return parseObjFromMap(map, clazz); } catch (JedisException e) { LOG.error("exception occur when hmGet a object", e); return null; } } @Override public <T> List<T> hmGet(final String[] keys, final Class<?> clazz) throws IOException { try { return new CacheOperation<List<T>>(CACHE_RETRY_COUNT) { @SuppressWarnings({ "rawtypes", "unchecked" }) public List<T> cacheExecute(ShardedJedis jedis) throws IOException { List<T> objects = new ArrayList<T>(keys.length); List<Response<Map<byte[], byte[]>>> responses = new ArrayList<Response<Map<byte[], byte[]>>>( keys.length); ExtendedShardedJedisPipeline pipeline = new ExtendedShardedJedisPipeline(jedis); for (String key : keys) { responses.add(pipeline.hgetBytesAll(key)); } pipeline.sync(); Map<byte[], byte[]> all; for (Response response : responses) { all = (Map<byte[], byte[]>) response.get(); objects.add((T) parseObjFromMap(all, clazz)); } return objects; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hmGetMaps, keys: " + keys, e); return null; } } protected Map<byte[], byte[]> parseObject2Map(Object object) throws IOException { Map<byte[], byte[]> map = new HashMap<byte[], byte[]>(); Field[] fields = object.getClass().getDeclaredFields(); try { for (Field field : fields) { boolean isStatic = Modifier.isStatic(field.getModifiers());// 静态变量不存缓存 if (field != null && field.getName() != null && field.getAnnotation(IgnoreCache.class) == null && !isStatic) { field.setAccessible(true); Object obj = field.get(object); if (obj == null) { continue; } if (obj instanceof BigDecimal) { map.put(SerializerUtil.write(field.getName()), SerializerUtil.write(obj)); } else { String value = beanUtilsBean.getProperty(object, field.getName()); map.put(SerializerUtil.write(field.getName()), SerializerUtil.write(value)); } } } } catch (JedisException e) { LOG.error("Can't parse Object to Map", e); } catch (NoSuchMethodException e) { LOG.error("Can't parse Object to Map", e); } catch (InvocationTargetException e) { LOG.error("Can't parse Object to Map", e); } catch (IllegalAccessException e) { LOG.error("Can't parse Object to Map", e); } return map; } private static Map<String, Map<String, Class<?>>> classFields = new HashMap<String, Map<String, Class<?>>>(); public Object parseObjFromMap(Map<byte[], byte[]> map, Class<?> clazz) throws IOException { Object o = null; String field; if (map == null || map.size() <= 0) { return o; } Map<String, Class<?>> fieldMap = null; synchronized (classFields) { fieldMap = classFields.get(clazz.getName()); if (classFields.get(clazz.getName()) == null) { LOG.info(clazz.getName() + " is not exists in classFields, will generate it and put to map for cache"); Field[] fields = clazz.getDeclaredFields(); fieldMap = new HashMap<String, Class<?>>(); for (Field f : fields) { fieldMap.put(f.getName(), f.getType()); } classFields.put(clazz.getName(), fieldMap); } } Map<String, Object> valueMap = new HashMap<String, Object>(); try { o = clazz.newInstance(); for (Map.Entry<byte[], byte[]> entry : map.entrySet()) { field = (String) SerializerUtil.read(entry.getKey()); Object obj = SerializerUtil.read(entry.getValue()); if (obj == null || field == null) { continue; } valueMap.put(field, obj); } BeanMap beanMap = BeanMap.create(o); beanMap.setBean(o); beanMap.putAll(valueMap); } catch (Exception e) { LOG.error("Can't parse Object from List", e); return null; } return o; } public Long total(final String key) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { Long total = jedis.zcard(SafeEncoder.encode(key)); if (total == null) { return 0L; } return total; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling total, key: " + key, e); return 0L; } } public Long zRank(final String key, final Object target) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zrank(SafeEncoder.encode(key), SerializerUtil.write(target)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zRanking, key: " + key + ", value:" + target, e); return null; } } public Long zRevRank(final String key, final Object target) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { return jedis.zrevrank(SafeEncoder.encode(key), SerializerUtil.write(target)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zrevrank, key: " + key + ", value:" + target.toString(), e); return null; } } /** * 获取key的排名 如果列表不存在返回 -1 如果key不存在返回 null * @param key * @param target * @return * @throws java.io.IOException */ public Long zRevRankNoExpire(final String key, final Object target) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws JedisException, IOException { byte[] keys = SafeEncoder.encode(key); Transaction t = jedis.getShard(key).multi(); Response<Long> rankResponse = t.zrevrank(keys, SerializerUtil.write(target)); Response<Boolean> existResponse = t.exists(keys); t.exec(); if (!existResponse.get()) { return -1L; } else { return rankResponse.get(); } } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling zrevrank, key: " + key + ", value:" + target.toString(), e); return null; } } public boolean expire(final String key, final int seconds) throws IOException { try { return new CacheOperation<Boolean>(CACHE_RETRY_COUNT, key) { public Boolean cacheExecute(ShardedJedis jedis) throws IOException { Long expired = jedis.expire(key, seconds); return expired != null; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling expire, key: " + key, e); return false; } } /** * exists checking for the key with the expired command */ public boolean exists(final String key) throws IOException { try { return new CacheOperation<Boolean>(CACHE_RETRY_COUNT, key) { public Boolean cacheExecute(ShardedJedis jedis) throws IOException { Long ttl = jedis.ttl(key); if (ttl == -1) {// non-expire key or non-exists key Boolean exists = jedis.exists(key); return exists != null && exists.booleanValue(); } else if (ttl < 1) { try { delete(key); } catch (Exception e) { LOG.error("delete key error! " + key, e); } return false; } return true; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling exists, key: " + key, e); return false; } } @Override public void hmSetForPush(final String key, final Map<Long, Object> map) throws IOException { try { new CacheOperation<String>(CACHE_RETRY_COUNT, key) { public String cacheExecute(ShardedJedis jedis) throws IOException { if (map == null || map.isEmpty()) { return null; } Map<byte[], byte[]> binaryMap = new HashMap<byte[], byte[]>(map.size()); for (Map.Entry<Long, Object> entry : map.entrySet()) { binaryMap.put(SerializerUtil.write(entry.getKey()), SerializerUtil.write(entry.getValue())); } return jedis.hmset(SafeEncoder.encode(key), binaryMap); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hmSetForPush, key: " + key, e); } } @Override public Object hmGetForPush(final String key) throws IOException { try { return new CacheOperation<Object>(CACHE_RETRY_COUNT, key) { public Object cacheExecute(ShardedJedis jedis) throws IOException { Map<byte[], byte[]> binaryMap = jedis.hgetAll(SafeEncoder.encode(key)); Map<Long, Object> resultMap = new HashMap<Long, Object>(); for (Map.Entry<byte[], byte[]> entry : binaryMap.entrySet()) { resultMap.put((Long) ConvertUtils.convert( SerializerUtil.read(entry.getKey()), Long.class), SerializerUtil.read(entry.getValue())); } return resultMap; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling calling hmGetForPush, key:" + key, e); return null; } } public long hmDel(final String key, final long mapKey) throws IOException { if (key == null || key.trim().length() == 0) { throw new JedisException("no key is null or length of o"); } try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { return jedis.hdel(SafeEncoder.encode(key), SerializerUtil.write(mapKey)); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling hmDel, key: " + key, e); return -1L; } } public boolean setsIsMember(final String key, final String member) throws IOException { try { return new CacheOperation<Boolean>(CACHE_RETRY_COUNT, key) { public Boolean cacheExecute(ShardedJedis jedis) throws IOException { Boolean exists = jedis.sismember(key, member); return exists != null && exists.booleanValue(); } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling setsIsMember, key: " + key, e); return false; } } public Long setsAddMember(final String key, final String... member) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { Long added = jedis.sadd(key, member); return added; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling setsAddMember a object, key: " + key, e); return -1L; } } public Long setsDelMember(final String key, final String... member) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { Long removed = jedis.srem(key, member); return removed; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling setsDelMember, key: " + key, e); return -1L; } } public Set<String> setsAllMember(final String key) throws IOException { try { return new CacheOperation<Set<String>>(CACHE_RETRY_COUNT, key) { public Set<String> cacheExecute(ShardedJedis jedis) throws IOException { Set<String> members = jedis.smembers(key); return members; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling setsAllMember, key: " + key, e); return null; } } /** * if non-exsist return 0 ,like the empty set * @param key * @return * @throws java.io.IOException */ public long setsCountMember(final String key) throws IOException { try { return new CacheOperation<Long>(CACHE_RETRY_COUNT, key) { public Long cacheExecute(ShardedJedis jedis) throws IOException { Long count = jedis.scard(key); return count; } }.execute(); } catch (JedisException e) { LOG.error("exception occur when calling setsCountMember, key: " + key, e); return 0; } } /** * Cache lock. * @param key * @param seconds 任务间隔时间控制 * @return */ public boolean lock(String key, int seconds) { ShardedJedis shardedJedis = null; try { shardedJedis = getPool().getResource(); Jedis jedis = shardedJedis.getShard(key); if (jedis.exists(key)) { return false; } jedis.watch(key); Transaction transaction = jedis.multi(); Response<Long> response = transaction.setnx(key, "0"); transaction.expire(key, seconds); List<Object> list = transaction.exec(); return list != null && response.get() > 0; } catch (JedisException e) { LOG.error("lock : " + key, e); } finally { if (shardedJedis != null) { getPool().returnResource(shardedJedis); } } return false; } /** * release lock * 谨慎使用 如果任务时间比lock字段存在时间久 释放的可能是其他任务的lock * 一般情况下可不使用 * @param key * @return */ public boolean releaseLock(String key) { ShardedJedis jedis = null; try { jedis = this.getPool().getResource(); return jedis.del(key) > 0; } catch (JedisException e) { LOG.error("releaseLock key : " + key, e); } finally { if (jedis != null) { this.getPool().returnResource(jedis); } } return false; } /** * 批量操作zadd */ protected class BatchZAddOperator { private List<String> keys = null; private List<Double> scores = null; private List<Object> objects = null; public BatchZAddOperator() { this.keys = new ArrayList<String>(); this.scores = new ArrayList<Double>(); this.objects = new ArrayList<Object>(); } public void add(String key, double score, Object object) { this.keys.add(key); this.scores.add(score); this.objects.add(object); } public String[] getKeys() { return keys.toArray(new String[0]); } public Double[] getScores() { return scores.toArray(new Double[0]); } public Object[] getObjects() { return objects.toArray(new Object[0]); } } protected abstract class CacheOperationFactory { private Jedis jedis = null; public void setJedis(Jedis jedis) { this.jedis = jedis; } public Jedis getJedis() { return this.jedis; } public abstract void cache() throws JedisException, IOException; } protected abstract class CacheOperation<T> { private int retryCount; private String key = null; public CacheOperation(int retryCount) { this.retryCount = retryCount; } public CacheOperation(int retryCount, String key) { this.retryCount = retryCount; this.key = key; } public T execute() throws JedisException, IOException { if (retryCount <= 0) { throw new JedisException("cache operate count less than 1"); } while (retryCount > 0) { try { return cacheExecute(); } catch (JedisException e) { LOG.error("cache CountOperation exception, count: " + retryCount, e); retryCount--; } } throw new JedisException("cache CountOperation exception count=" + retryCount); } private T cacheExecute() throws JedisException, IOException { ShardedJedis jedis = null; boolean isFailed = false; try { jedis = pool.getResource(); return cacheExecute(jedis); } catch (JedisException e) { if (!(e.getCause() instanceof JedisDataException)) { isFailed = true; if(jedis != null && key != null) { JedisShardInfo shardInfo = jedis.getShardInfo(key); LOG.error("JedisException@{}:{}", shardInfo.getHost(), shardInfo.getPort()); } } throw e; } finally { if (jedis != null) { if (isFailed) { pool.returnBrokenResource(jedis); } else { pool.returnResource(jedis); } } } } public abstract T cacheExecute(ShardedJedis jedis) throws JedisException, IOException; } }
public class ExtendedShardedJedisPipeline extends Queable { private BinaryShardedJedis jedis = null; private List<FutureResult> results = new ArrayList<FutureResult>(); private Queue<Client> clients = new LinkedList<Client>(); public ExtendedShardedJedisPipeline() { } public ExtendedShardedJedisPipeline(BinaryShardedJedis jedis) { this.jedis = jedis; } public void setShardedJedis(BinaryShardedJedis jedis) { this.jedis = jedis; } public Response<String> set(String key, byte[] value) { Client c = getClient(key); c.set(SafeEncoder.encode(key), value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<String> set(String key, String value) { Client c = getClient(key); c.set(key, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<byte[]> getByte(String key) { Client c = getClient(key); c.get(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BYTE_ARRAY); } public Response<String> get(String key) { Client c = getClient(key); c.get(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Boolean> exists(String key) { Client c = getClient(key); c.exists(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<Boolean> type(String key) { Client c = getClient(key); c.type(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<Long> expire(String key, int seconds) { Client c = getClient(key); c.expire(key, seconds); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> expireAt(String key, long unixTime) { Client c = getClient(key); c.expireAt(key, unixTime); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> ttl(String key) { Client c = getClient(key); c.ttl(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> getSet(String key, String value) { Client c = getClient(key); c.getSet(key, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> setnx(String key, String value) { Client c = getClient(key); c.setnx(key, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> setex(String key, int seconds, String value) { Client c = getClient(key); c.setex(key, seconds, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> decrBy(String key, long integer) { Client c = getClient(key); c.decrBy(key, integer); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> decr(String key) { Client c = getClient(key); c.decr(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> incrBy(String key, int integer) { Client c = getClient(key); c.incrBy(key, integer); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> incr(String key) { Client c = getClient(key); c.incr(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> append(String key, String value) { Client c = getClient(key); c.append(key, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> substr(String key, int start, int end) { Client c = getClient(key); c.substr(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> hset(String key, String field, String value) { Client c = getClient(key); c.hset(key, field, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> hget(String key, String field) { Client c = getClient(key); c.hget(key, field); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> hsetnx(String key, String field, String value) { Client c = getClient(key); c.hsetnx(key, field, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> hmsetByte(String key, Map<byte[], byte[]> hash) { Client c = getClient(key); c.hmset(SafeEncoder.encode(key), hash); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<String> hmset(String key, Map<String, String> hash) { Client c = getClient(key); c.hmset(key, hash); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<List<String>> hmget(String key, String... fields) { Client c = getClient(key); c.hmget(key, fields); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_LIST); } public Response<Long> hincrBy(String key, String field, int value) { Client c = getClient(key); c.hincrBy(key, field, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Boolean> hexists(String key, String field) { Client c = getClient(key); c.hexists(key, field); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<Long> hdel(String key, String field) { Client c = getClient(key); c.hdel(key, field); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> hlen(String key) { Client c = getClient(key); c.hlen(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Set<String>> hkeys(String key) { Client c = getClient(key); c.hkeys(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_SET); } public Response<Set<String>> hvals(String key) { Client c = getClient(key); c.hvals(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_SET); } public Response<Map<byte[], byte[]>> hgetBytesAll(String key) { Client c = getClient(key); c.hgetAll(key); results.add(new FutureResult(c)); return getResponse(ExtendedBuilderFactory.BYTE_ARRAY_MAP); } public Response<Map<String, String>> hgetAll(String key) { Client c = getClient(key); c.hgetAll(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_MAP); } public Response<Long> rpush(String key, String string) { Client c = getClient(key); c.rpush(key, string); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> lpush(String key, String string) { Client c = getClient(key); c.lpush(key, string); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> llen(String key) { Client c = getClient(key); c.llen(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<List<String>> lrange(String key, int start, int end) { Client c = getClient(key); c.lrange(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_LIST); } public Response<String> ltrim(String key, int start, int end) { Client c = getClient(key); c.ltrim(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<String> lindex(String key, int index) { Client c = getClient(key); c.lindex(key, index); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<String> lset(String key, int index, String value) { Client c = getClient(key); c.lset(key, index, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> lrem(String key, int count, String value) { Client c = getClient(key); c.lrem(key, count, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> lpop(String key) { Client c = getClient(key); c.lpop(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<String> rpop(String key) { Client c = getClient(key); c.rpop(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> sadd(String key, String member) { Client c = getClient(key); c.sadd(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Set<String>> smembers(String key) { Client c = getClient(key); c.smembers(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_SET); } public Response<Long> srem(String key, String member) { Client c = getClient(key); c.srem(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<String> spop(String key) { Client c = getClient(key); c.spop(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> scard(String key) { Client c = getClient(key); c.scard(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Boolean> sismember(String key, String member) { Client c = getClient(key); c.sismember(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<String> srandmember(String key) { Client c = getClient(key); c.srandmember(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING); } public Response<Long> zadd(String key, double score, String member) { Client c = getClient(key); c.zadd(key, score, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> zadd(String key, double score, byte[] member) { Client c = getClient(key); c.zadd(SafeEncoder.encode(key), score, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Set<String>> zrange(String key, int start, int end) { Client c = getClient(key); c.zrange(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_ZSET); } public Response<Long> zrem(String key, String member) { Client c = getClient(key); c.zrem(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> zrem(String key, byte[] member) { Client c = getClient(key); c.zrem(SafeEncoder.encode(key), member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Double> zincrby(String key, double score, String member) { Client c = getClient(key); c.zincrby(key, score, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.DOUBLE); } public Response<Long> zrank(String key, String member) { Client c = getClient(key); c.zrank(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> zrevrank(String key, String member) { Client c = getClient(key); c.zrevrank(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Set<String>> zrevrange(String key, int start, int end) { Client c = getClient(key); c.zrevrange(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_ZSET); } public Response<Set<Tuple>> zrangeWithScores(String key, int start, int end) { Client c = getClient(key); c.zrangeWithScores(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET); } public Response<Set<Tuple>> zrevrangeWithScores(String key, int start, int end) { Client c = getClient(key); c.zrevrangeWithScores(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET); } public Response<Long> zcard(String key) { Client c = getClient(key); c.zcard(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Double> zscore(String key, String member) { Client c = getClient(key); c.zscore(key, member); results.add(new FutureResult(c)); return getResponse(BuilderFactory.DOUBLE); } public Response<Double> sort(String key) { Client c = getClient(key); c.sort(key); results.add(new FutureResult(c)); return getResponse(BuilderFactory.DOUBLE); } public Response<List<String>> sort(String key, SortingParams sortingParameters) { Client c = getClient(key); c.sort(key, sortingParameters); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_LIST); } public Response<Long> zcount(String key, double min, double max) { Client c = getClient(key); c.zcount(key, min, max); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Set<String>> zrangeByScore(String key, double min, double max) { Client c = getClient(key); c.zrangeByScore(key, min, max); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_ZSET); } public Response<Set<String>> zrangeByScore(String key, double min, double max, int offset, int count) { Client c = getClient(key); c.zrangeByScore(key, min, max, offset, count); results.add(new FutureResult(c)); return getResponse(BuilderFactory.STRING_ZSET); } public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max) { Client c = getClient(key); c.zrangeByScoreWithScores(key, min, max); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET_BINARY); } public Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { Client c = getClient(key); c.zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max), offset, count); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET_BINARY); } public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { Client c = getClient(key); c.zrangeByScoreWithScores(key, min, max, offset, count); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET_BINARY); } public Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double min, double max, int offset, int count) { Client c = getClient(key); c.zrevrangeByScoreWithScores(key, min, max, offset, count); results.add(new FutureResult(c)); return getResponse(BuilderFactory.TUPLE_ZSET_BINARY); } public Response<Long> zremrangeByRank(String key, int start, int end) { Client c = getClient(key); c.zremrangeByRank(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> zremrangeByScore(String key, double start, double end) { Client c = getClient(key); c.zremrangeByScore(key, start, end); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> linsert(String key, LIST_POSITION where, String pivot, String value) { Client c = getClient(key); c.linsert(key, where, pivot, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Boolean> getbit(String key, long offset) { Client c = getClient(key); c.getbit(key, offset); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<Boolean> setbit(String key, long offset, boolean value) { Client c = getClient(key); c.setbit(key, offset, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.BOOLEAN); } public Response<Long> setrange(String key, long offset, String value) { Client c = getClient(key); c.setrange(key, offset, value); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public Response<Long> getrange(String key, long startOffset, long endOffset) { Client c = getClient(key); c.getrange(key, startOffset, endOffset); results.add(new FutureResult(c)); return getResponse(BuilderFactory.LONG); } public List<Object> getResults() { List<Object> r = new ArrayList<Object>(); for (FutureResult fr : results) { r.add(fr.get()); } return r; } public void sync() { for (Client client : clients) { generateResponse(client.getOne()); } } public List<Object> syncAndReturnAll() { List<Object> formatted = new ArrayList<Object>(); for (Client client : clients) { formatted.add(generateResponse(client.getOne()).get()); } return formatted; } private Client getClient(byte[] key) { Client client = jedis.getShard(key).getClient(); clients.add(client); return client; } private Client getClient(String key) { Client client = jedis.getShard(key).getClient(); clients.add(client); return client; } private static class FutureResult { private Client client = null; public FutureResult(Client client) { this.client = client; } public Object get() { return client.getOne(); } } }