Redis学习笔记-Jedis操作Redis

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();
		}
	}
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值