本人一直從事java研發,java版本的redis客戶端一般使用的是jedis。在以前生產開發過程當中,redis主要以單機形式或者主備讀寫分離形式使用,並未涉及到分片等高級功能。最近,因爲業務量激增,單機redis的性能出現了瓶頸,主要是redis消耗cpu太高。因而,想採用數據分片的方式,將請求路由到其餘redis實例上去,下降單機redis的壓力,該方案具體的實現方式是使用客戶端的ShardedJedis對象來實現數據分片。java
因爲系統以前的緩存設計使用了redis多個db分區存儲數據,在使用ShardedJedis分片存取的過程當中發現,ShardedJedis不支持動態選擇DB,該對象沒有select功能。爲何呢?ShardedJedis其實是一個虛擬鏈接,一個ShardJedis對應了多個物理鏈接,經過一致性哈希算法計算key的哈希值,而後得到相應的物理鏈接,再發送存儲命令,實現存儲操做。ShardJedis中對應的物理鏈接必須保持一致,才能保證分片存儲數據的一致性,所以,ShardJedis不支持select操做。redis
若是必定要實現選擇DB,怎麼辦呢?也不是沒有辦法的,只要把ShardJedis對應的全部物理鏈接客戶端都設置爲同一個db便可,下面是代碼示例:算法
public class RedisShardPoolTest { private static ShardedJedisPool shardedJedisPool; static { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(100); poolConfig.setMaxIdle(50); poolConfig.setMinIdle(10); poolConfig.setMaxWaitMillis(1000 * 60); poolConfig.setTestOnBorrow(true); String host = "127.0.0.1"; int portA = 6379; int portB = 6378; List<JedisShardInfo> jdsInfoList = new ArrayList<JedisShardInfo>(2); JedisShardInfo infoA = new JedisShardInfo(host, portA); JedisShardInfo infoB = new JedisShardInfo(host, portB); jdsInfoList.add(infoA); jdsInfoList.add(infoB); shardedJedisPool = new ShardedJedisPool(poolConfig, jdsInfoList); } public static void main(String[] args) { ShardedJedis jds = shardedJedisPool.getResource(); Collection<Jedis> collection=jds.getAllShards(); Iterator<Jedis> jedis = collection.iterator(); while(jedis.hasNext()){ jedis.next().select(1); } ShardedJedisPipeline pipeline = jds.pipelined(); for(int i=0; i<100; i++) { String key = generateKey(); System.out.println(key + ":" + jds.getShard(key).getClient().getPort()); System.out.println(pipeline.set(key,Math.random() + "")); } pipeline.sync(); } private static int index = 1; public static String generateKey(){ return String.valueOf(Thread.currentThread().getId())+"_"+(index++); } }