關於 Redis Cluster 模式下獲取 Java Client 的問題
阿新 • • 發佈:2018-12-25
Redis連線池對於單機模式來說,官網有提供個JedisPool工具類,用起來也比較方便
但是對於Redis叢集模式下,官網沒有提供連線池的工具類,於是就需要我們自己來實現類似的功能了,我這裡採用的是單例模式的方法來解決高併發的場景。
單機模式
如果對於 Redis 是單機模式下的話,那麼 Redis 有提供一個JedisPool
類 用來構建 Redis Client 的連線池,非常方便,簡單程式碼如下:
JedisPoolConfig config = new JedisPoolConfig();
//控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項。
config.setMaxIdle(5);
//控制一個pool可分配多少個jedis例項,通過pool.getResource()來獲取;如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;
config.setMaxTotal(1000 * 100);
//表示當borrow(引入)一個jedis例項時,最大的等待時間,如果超過等待時間,則直接丟擲JedisConnectionException;
config.setMaxWaitMillis(30 );
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
//如果你遇到 java.net.SocketTimeoutException: Read timed out exception的異常資訊,請嘗試在構造JedisPool的時候設定自己的超時值. JedisPool預設的超時時間是2秒(單位毫秒)
pool = new JedisPool(config, "127.0.0.1", 6379);
/*
* 獲得jedis連線
*/
Jedis jedis = pool.getResource();
叢集模式
單機模式Redis官方有提供JedisPool類,用起來非常方便。
但是,如果Redis部署的是叢集模式,你會發現,官方根本就沒有提供叢集模式下的連線池的類!!
官方有提供一個JedisClsuter
那麼問題來了,Redis叢集模式應該如何解決高併發的場景呢?
咦,這是我想到了一個自己感覺很不錯的方法,就是採用單例模式,簡單的程式碼如下:
public class JedisClsuterUtil {
private static JedisCluster jedis = null;
private JedisClsuterUtil(){}
public static JedisCluster getJedis(){
if(jedis==null){
synchronized(JedisClsuterUtil.class){
if(jedis==null){
Set<HostAndPort> hostAndPortSet = new HashSet();
hostAndPortSet.add(new HostAndPort("host1", 9001));
hostAndPortSet.add(new HostAndPort("host2", 9002));
// ....
jedis = new JedisCluster(hostAndPortSet);
}
}
}
return jedis;
}
}
用該方法測試過,是沒有問題的。
改進:
上面是依靠double-checked locking的,這是一種不正確的用法,並不能達到預期目標。
所以以下是單例模式的改進版:
public class JedisClsuterUtil {
private JedisClsuterUtil(){}
public static JedisCluster getJedis(){
return JedisClusterHolder.jedis;
}
private static class JedisClusterHolder{
private static Set<HostAndPort> hostAndPortSet;
static {
hostAndPortSet = new HashSet();
hostAndPortSet.add(new HostAndPort("host1", 9001));
hostAndPortSet.add(new HostAndPort("host2", 9002));
}
private static JedisCluster jedis = new JedisCluster(hostAndPortSet);
}
}
各位有什麼更好的想法或者問題可以提出來討論討論。。