Jedis下的ShardedJedis(分散式)使用方法(一)
原來專案中有用到Redis用作快取服務,剛開始時只用一臺Redis就能夠滿足服務,隨著專案的慢慢進行,發現一臺滿足不了現有的專案需求,因為Redis操作都是原子性這樣的特性,造成有時同時讀寫快取造成查詢效率的下降。但是由於我們現在用的還是2.X版本,還是沒有叢集功能的(Redis作者在3.0版本中已經加入了叢集功能), 因此只能使用2.x版本中自帶的一個叫做
1.使用方法
的使用方法除了配置時有點區別,其他和Jedis基本類似,有一點要注意的是 不支援多命令操作,像mget、mset、brpop等可以在redis命令後一次性操作多個key的命令,具體包括哪些,大家可以看Jedis下的 MultiKeyCommands 這個類,這裡面就包含了所有的多命令操作。很貼心的是,Redis作者已經把這些命令從過濾掉了,使用時也調用不了這些方法,大家知道下就行了。
好了,現在來看基本的使用
//設定連線池的相關配置 JedisPoolConfig poolConfig = newJedisPoolConfig(); poolConfig.setMaxTotal(2); poolConfig.setMaxIdle(1); poolConfig.setMaxWaitMillis(2000); poolConfig.setTestOnBorrow(false); poolConfig.setTestOnReturn(false); //設定Redis資訊 String host = "127.0.0.1"; JedisShardInfo shardInfo1= new JedisShardInfo(host, 6379, 500); shardInfo1.setPassword("test123"); JedisShardInfo shardInfo2 = new JedisShardInfo(host, 6380, 500); shardInfo2.setPassword("test123"); JedisShardInfo shardInfo3 = new JedisShardInfo(host, 6381, 500); shardInfo3.setPassword("test123"); //初始化ShardedJedisPool List<JedisShardInfo> infoList = Arrays.asList(shardInfo1, shardInfo2, shardInfo3); ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, infoList); //進行查詢等其他操作 ShardedJedis jedis = null; try { jedis = jedisPool.getResource(); jedis.set("test", "test"); jedis.set("test1", "test1"); String test = jedis.get("test"); System.out.println(test); ...... } finally { //使用後一定關閉,還給連線池
if(jedis!=null) {
jedis.close();
} }
jedis獲取後一定要關閉,這和我們使用資料庫連線池是一樣的,放在finally塊中保證jedis的關閉.
ps:如果大家使用的jdk是1.7版本或者以上的話,可以使用1.7加入的try-with-resources語句
try(ShardedJedis jedis = jedisPool.getResource()) { jedis.set("test", "test"); jedis.set("test1", "test1"); String test = jedis.get("test"); System.out.println(test); }
try-with-resources的效果和我們上面寫法是一樣的,只是jedis.close()語法它會幫我們呼叫,它會預設呼叫我們在try-with-resources語句中宣告的,實現了Closeable 介面的物件的close方法(像上面的ShardedJedis),我們經常用到的資料庫連線Connection和一些輸入輸出流都可以使用這種方法。
從程式碼上看,除了初始化ShardedJedisPool時需要加入多個Redis伺服器資訊,其他的和Jedis使用差不多。
在初始化ShardedJedisPool 時,我們還可以傳入ShardedJedis採用的hash演算法,支援MURMUR_HASH 和MD5兩種演算法,預設是使用MURMUR_HASH(可以檢視redis.clients.util.Hashing 類檢視相關的資訊)
另外還可以傳入keyTagPattern來指定我們key的分佈策略,所有能夠匹配keyTagPattern的key(通過正則匹配)將放在同一個redis裡,預設的是直接使用key來進行判定。Redis自帶了一個Sharded.keyTagPattern,如下
Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile("\\{(.+?)\\}");
我們可以用下面的程式碼來實際測試下
ShardedJedis jedis = jedisPool.getResource();
jedis.set("cnblog", "cnblog"); jedis.set("redis", "redis"); jedis.set("test", "test"); jedis.set("123456", "1234567"); Client client1 = jedis.getShard("cnblog").getClient(); Client client2 = jedis.getShard("redis").getClient(); Client client3 = jedis.getShard("test").getClient(); Client client4 = jedis.getShard("123456").getClient(); ////列印key在哪個server中 System.out.println("cnblog in server:" + client1.getHost() + " and port is:" + client1.getPort()); System.out.println("redis in server:" + client2.getHost() + " and port is:" + client2.getPort()); System.out.println("test in server:" + client3.getHost() + " and port is:" + client3.getPort()); System.out.println("123456 in server:" + client4.getHost() + " and port is:" + client4.getPort());
看輸出內容:
可以看到我們儲存的4個key,cnblog和redis在同一個redis server中,另外兩個分別在另外的redis server中。
裡面採用了一致性雜湊的演算法,來決定每個key的儲存位置,具體是怎麼樣計算的,在下一篇中會研究下的原始碼來看看。