(七)使用jedis連接單機和集群(一步一個坑踩出來的辛酸淚)


環境准備:

  • redis-4.0.9,最新版了

  • ruby:redis-x.x.x.gem    這個gem什么版本都行,我redis4用3.0.0的gem正常跑

  • jedis-2.9.0.jar,最新版

 


偽集群搭建:這里省略了,需要的看我前面的文檔,這里只貼出來一些關鍵點

1、下載、解壓

1 # make
2 # make install PREFIX=/usr/local/bin/

2、創建集群工作目錄,把redis/bin復制進去,需要幾台集群自己看着辦

3、修改每個節點的配置文件

1 port  7001                                        //端口7001,7002,7003...       
2 bind 本機ip                                       //默認ip為127.0.0.1 需要改為其他節點機器可訪問的ip 否則創建集群時無法訪問對應的端口,無法創建集群,直接注釋掉
3 daemonize    yes                               //redis后台運行
4 cluster-enabled  yes                           //開啟集群  把注釋#去掉
protect_mode no                  //如果bind注釋掉了,那么就把保護模式關掉
5 #可選項 6 cluster-config-file nodes.conf //集群的配置 配置文件首次啟動自動生成,默認就行
cluster-node-timeout 15000 //請求超時 默認15秒,可自行設置
appendonly yes //aof日志開啟 有需要就開啟,它會每次寫操作都記錄一條日志

4、安裝ruby、rubygems、redis.x.x.x.gem

1 # yum install ruby
2 # yum install rubygems
3 # 去官網下redis-x.x.x.gem,3.0以上都行
4 # gem install redis-4.0.1.gem

5、構建以下目錄

解釋:

redis-cli:客戶端,方便調試用

reids-trib.rb:集群的ruby腳本,去源碼包復制過來

start-all-nodes.h:shell腳本,啟動所有節點(參考下圖)

stop-all-nodes.h:shell腳本,關閉集群(參考下圖)

redis-cluster-configure.sh:開始集群部署,需要node節點全部啟動(參考下圖)

6、依次執行shell即可(start-all-nodes.sh ---> redis-cluster-configure.sh ---> input "yes")


 

集群測試:

 1         @Test
 2     public void testCluster() throws IOException, InterruptedException {
 3         Set<HostAndPort> nodes = new HashSet<>();
 4         nodes.add(new HostAndPort("47.100.101.31", 7001));
 5         nodes.add(new HostAndPort("47.100.101.31", 7002));
 6         nodes.add(new HostAndPort("47.100.101.31", 7003));
 7         nodes.add(new HostAndPort("47.100.101.31", 7004));
 8         nodes.add(new HostAndPort("47.100.101.31", 7005));
 9         nodes.add(new HostAndPort("47.100.101.31", 7006));
10         JedisCluster cluster = new JedisCluster(nodes);
11         try {
12             String res = cluster.get("name");
13             System.out.println(res);    
14             cluster.close();
15         } catch (Exception e) {
16             e.printStackTrace();
17             cluster.close();
18         }
19     }    

遇到的坑:

1)連接報錯:Connection refused。

  錯誤原因:遠程拒絕鏈接,單機版和集群都報錯。

  解決方案:當時bind 127.0.0.1。於是乎注釋掉,不行,提示沒有bind於是啟動了保護模式,所以配置:protect_mode no,單機版ok,redis客戶端連集群ok。

2)通過jedis連接redis單機成功,使用JedisCluster連接redis集群一直報Could not get a resource from the pool,但是使用redis客戶端可以連接集群(我使用的redis desktop manager)在java中通過jedis連接redis單機也成功,但使用JedisCluster連接redis集群一直報Could not get a resource from the pool,

  錯誤原因:未知,以為jar包版本問題,換最新版2.9.0.jar,無效。糾結了好幾天,最后看一個博客說把127.0.0.1換成公網ip

  解決:127.0.0.1換成公網IP,於是直接跑通。

疑問:127.0.0.1表示的就是本地,啟動后對外網來說127就是公網ip了,不知道為啥會錯,因為用其他客戶端都沒問題,懷疑是jedis內部機制導致的。


附錄:Spring集成redis

 1     <!-- Jedis連接池配置, 可以寫在資源文件中 -->
 2     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
 3         <!-- 最大連接數 -->
 4         <property name="maxTotal" value="30" />
 5         <!-- 最大空閑連接數 -->
 6         <property name="maxIdle" value="10" />
 7         <!-- 每次釋放連接的最大數目 -->
 8         <property name="numTestsPerEvictionRun" value="1024" />
 9         <!-- 釋放連接的掃描間隔(毫秒) -->
10         <property name="timeBetweenEvictionRunsMillis" value="30000" />
11         <!-- 連接最小空閑時間 -->
12         <property name="minEvictableIdleTimeMillis" value="1800000" />
13         <!-- 連接空閑多久后釋放, 當空閑時間>該值 且 空閑連接>最大空閑連接數 時直接釋放 -->
14         <property name="softMinEvictableIdleTimeMillis" value="10000" />
15         <!-- 獲取連接時的最大等待毫秒數,小於零:阻塞不確定的時間,默認-1 -->
16         <property name="maxWaitMillis" value="1500" />
17         <!-- 在獲取連接的時候檢查有效性, 默認false -->
18         <property name="testOnBorrow" value="true" />
19         <!-- 在空閑時檢查有效性, 默認false -->
20         <property name="testWhileIdle" value="true" />
21         <!-- 連接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true -->
22         <property name="blockWhenExhausted" value="false" />
23     </bean>
24     <!-- jedis客戶端單機版 -->
25     <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
26         <constructor-arg name="host" value="47.100.101.31" />
27         <constructor-arg name="port" value="6379" />
28         <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
29     </bean>
30     <!-- Jedis集群版 -->
31     <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
32         <constructor-arg name="nodes">
33             <set>
34                 <bean class="redis.clients.jedis.HostAndPort">
35                     <constructor-arg name="host" value="47.100.101.31"/>
36                     <constructor-arg name="port" value="7001"/>
37                 </bean>
38                  <bean class="redis.clients.jedis.HostAndPort">
39                     <constructor-arg name="host" value="47.100.101.31"/>
40                     <constructor-arg name="port" value="7002"/>
41                 </bean>
42                  <bean class="redis.clients.jedis.HostAndPort">
43                     <constructor-arg name="host" value="47.100.101.31"/>
44                     <constructor-arg name="port" value="7003"/>
45                 </bean>
46                  <bean class="redis.clients.jedis.HostAndPort">
47                     <constructor-arg name="host" value="47.100.101.31"/>
48                     <constructor-arg name="port" value="7004"/>
49                 </bean>
50                  <bean class="redis.clients.jedis.HostAndPort">
51                     <constructor-arg name="host" value="47.100.101.31"/>
52                     <constructor-arg name="port" value="7005"/>
53                 </bean>
54                  <bean class="redis.clients.jedis.HostAndPort">
55                     <constructor-arg name="host" value="47.100.101.31"/>
56                     <constructor-arg name="port" value="7006"/>
57                 </bean>
58             </set>
59         </constructor-arg>
60         <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
61     </bean>

使用集群請注釋掉單機版的

 

最后還有點小bug,7001節點不能出現在jediscluster的構造函數中,不然訪問7001節點內容會超時,原因未知。我用3.2.9重裝一遍沒發現任何問題,待大佬們解決吧

 1 public interface JedisClient {
 2 
 3     String get(String key);
 4 
 5     String set(String key, String value);
 6 
 7     long ttl(String key);
 8 
 9     long expire(String key, int second);
10 
11     long incr(String key);
12 
13     long hset(String hkey, String key, String value);
14 
15     String hget(String hkey, String key);
16     
17     long del(String key);
18     
19     long hdel(String hkey, String key);
20 }
 1 public class JedisClientCluster implements JedisClient {
 2 
 3     @Resource
 4     private JedisCluster jedisCluster;
 5     
 6     @Override
 7     public String get(String key) {
 8         return jedisCluster.get(key);
 9     }
10 
11     @Override
12     public String set(String key, String value) {
13         return jedisCluster.set(key, value);
14     }
15 
16     @Override
17     public long ttl(String key) {
18         return jedisCluster.ttl(key);
19     }
20 
21     @Override
22     public long expire(String key, int second) {
23         return jedisCluster.expire(key, second);
24     }
25 
26     @Override
27     public long incr(String key) {
28         return jedisCluster.incr(key);
29     }
30 
31     @Override
32     public long hset(String hkey, String key, String value) {
33         return jedisCluster.hset(hkey, key, value);
34     }
35 
36     @Override
37     public String hget(String hkey, String key) {
38         return jedisCluster.hget(hkey, key);
39     }
40 
41     @Override
42     public long del(String key) {
43         return jedisCluster.del(key);
44     }
45     
46     @Override
47     public long hdel(String hkey, String key) {
48         return jedisCluster.del(hkey, key);
49     }
50 }
 1 public class JedisClientSingle implements JedisClient {
 2 
 3     @Resource
 4     private JedisPool jedisPool;
 5     
 6     @Override
 7     public String get(String key) {
 8         Jedis jedis = jedisPool.getResource();
 9         String string = jedis.get(key);
10         jedis.close();
11         return string;
12     }
13 
14     @Override
15     public String set(String key, String value) {
16         Jedis jedis = jedisPool.getResource();
17         String string = jedis.set(key, value);
18         jedis.close();
19         return string;
20     }
21 
22     @Override
23     public String hget(String hkey, String key) {
24         Jedis jedis = jedisPool.getResource();
25         String string = jedis.hget(hkey, key);
26         jedis.close();
27         return string;
28     }
29 
30     @Override
31     public long hset(String hkey, String key, String value) {
32         Jedis jedis = jedisPool.getResource();
33         Long result = jedis.hset(hkey, key, value);
34         jedis.close();
35         return result;
36     }
37 
38     @Override
39     public long incr(String key) {
40         Jedis jedis = jedisPool.getResource();
41         Long result = jedis.incr(key);
42         jedis.close();
43         return result;
44     }
45 
46     @Override
47     public long expire(String key, int second) {
48         Jedis jedis = jedisPool.getResource();
49         Long result = jedis.expire(key, second);
50         jedis.close();
51         return result;
52     }
53 
54     @Override
55     public long ttl(String key) {
56         Jedis jedis = jedisPool.getResource();
57         Long result = jedis.ttl(key);
58         jedis.close();
59         return result;
60     }
61 
62     @Override
63     public long del(String key) {
64         Jedis jedis = jedisPool.getResource();
65         Long result = jedis.del(key);
66         jedis.close();
67         return result;
68     }
69 
70     @Override
71     public long hdel(String hkey, String key) {
72         Jedis jedis = jedisPool.getResource();
73         Long result = jedis.hdel(hkey, key);
74         jedis.close();
75         return result;
76     }
77 }

如果集群版和主從復制版想要共存,那么就在spring配置文件中手動注入


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM