1. 程式人生 > >【精】搭建redis cluster叢集,JedisCluster帶密碼訪問【解決當中各種坑】!

【精】搭建redis cluster叢集,JedisCluster帶密碼訪問【解決當中各種坑】!

一.搭建redis單機 本文搭建redis3.0版本,3.0主要增加了redis cluster叢集功能。 1.下載地址:http://download.redis.io/releases/redis-3.0.0.tar.gz,將下載檔案拷貝到/usr/local 2.解壓原始碼:tar -zxvf redis-3.0.0.tar.gz 3.編譯原始碼:cd /usr/local/redis-3.0.0
make
4.安裝到指定目錄: cd /usr/local/redis-3.0.0 
make PREFIX=/usr/local/redis install
5.進入原始碼目錄,將redis.conf拷貝到安裝路徑:cd /usr/local/redis
mkdir conf cp /usr/local/redis-3.0.0/redis.conf  /usr/local/redis/bin
6.修改redis.conf配置檔案,以後端模式啟動:daemonize yes 7.啟動redis:cd /usr/local/redis ./bin/redis-server ./redis.conf  //在何處啟動的server,一些配置檔案就預設在該處生成(如果配置的相對路徑) 8.redis.conf配置檔案主要配置:
port 7001  //監聽的埠 # bind 127.0.0.1  //繫結ip,只允許該ip訪問,不填預設為*,表示允許所有ip訪問 requirepass "你的密碼"  //開啟密碼
loglevel debug   //日誌級別,開發模式儘量選用debug logfile "redis.log"   //日誌檔案路徑,此處使用相對路徑,將生成到/usr/local/redis下 maxmemory 100000000  //允許最大記憶體佔用100m appendonly yes  //啟用aof auto-aof-rewrite-percentage 80  //部署在同一機器的多個redis例項,建議把auto-aof-rewrite錯開(可分別寫80-100不等),防止瞬間fork,所有redis程序做rewrite,佔用大量記憶體
9.jedis連線redis單機:
<dependency> 
<groupId>redis.clients</groupId> 
<artifactId>jedis</artifactId> 
<version>2.7.0</version>
</dependency>
連線池整合spring:        
<!-- redis連線池(單例) -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="close">
<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>		
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port}"/>
<constructor-arg name="timeout" value="${redis.timeout}"/>
<constructor-arg name="password" value="${redis.pass}"/>
</bean>        
<!-- 連線池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大連線數 -->
<property name="maxTotal" value="150" />
<!-- 最大空閒連線數 -->
<property name="maxIdle" value="30" />
<!-- 最小空閒連線數 -->
<property name="minIdle" value="10" />
<!-- 獲取連線時的最大等待毫秒數,小於零:阻塞不確定的時間,預設-1 -->
<property name="maxWaitMillis" value="3000" />
<!-- 每次釋放連線的最大數目 -->
<property name="numTestsPerEvictionRun" value="100" />
<!-- 釋放連線的掃描間隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="3000" />
<!-- 連線最小空閒時間 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 連線空閒多久後釋放, 當空閒時間>該值 且 空閒連線>最大空閒連線數 時直接釋放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 在獲取連線的時候檢查有效性, 預設false -->
<property name="testOnBorrow" value="true" />
<!-- 在空閒時檢查有效性, 預設false -->
<property name="testWhileIdle" value="true" />
<!-- 在歸還給pool時,是否提前進行validate操作 -->
<property name="testOnReturn" value="true" />
<!-- 連線耗盡時是否阻塞, false報異常,ture阻塞直到超時, 預設true -->
<property name="blockWhenExhausted" value="false" />
</bean>
@RunWith(SpringJUnit4ClassRunner.class) // 指定測試用例的執行器 這裡是指定了Junit4
@ContextConfiguration("classpath:spring/application*.xml")
public class RedisTest {
@Autowired
private JedisPool pool;
@Test
public void testJedisPool() {
Jedis jedis = null;
String name = null;
try {
jedis = pool.getResource();
jedis.set("testName", "RCL");
name = jedis.get("testName");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (jedis != null) {
// 返回給池
jedis.close();
}
Assert.assertEquals("RCL", name);
}
}
10.如果連線不上,可檢視是否防火牆沒有將redis埠開放:/etc/sysconfig/iptables新增:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 7001 -j ACCEPT //7001即redis埠
重啟防火牆
二、搭建redis叢集 1.安裝ruby環境 叢集管理工具redis-trib.rb依賴ruby環境 (1)安裝ruby:
yum install ruby yum install rubygems
(2)安裝ruby和redis的介面程式:
拷貝redis-3.0.0.gem至/usr/local。執行:gem install /usr/local/redis-3.0.0.gem
2.建立redis例項 (1)建立存放redis群的資料夾及子資料夾(用於存放每個redis例項):
cd /usr/local     mkdir redis-cluster  mkdir redis-cluster/7001 mkdir redis-cluster/7002
……
(2)將剛剛安裝的單機redis的/usr/local/redis資料夾拷貝到每個700X資料夾下,(這裡我們建立六個例項,三主三從) (3)修改每個700X目錄下的redis.conf配置檔案:
port 700X   //各自監聽的埠 #bind 127.0.0.1  //這裡不繫結,預設允許所有ip訪問,或者bind 0.0.0.0 cluster-enabled yes   //開啟叢集 cluster-node-timeout 15000   //15時間內沒有收到對方的回覆,則單方面認為端節點掛掉 另外,由於下面我們需要配置叢集密碼,故之前配置的 requirepass 先刪掉,叢集成功後再進行配置。
3.啟動各個redis:分別進入7001、7002、...7006目錄,執行./redis-server ./redis.conf 4.建立叢集:/usr/local/redis-cluster/redis-trib.rb create --replicas 1 123.123.123.123:7001 123.123.123.123:7002 123.123.123.123:7003 123.123.123.123:7004 123.123.123.123:7005 123.123.123.123:7006 注意: (1)為保證遠端可訪問,這裡的ip儘量使用公網ip,且建立叢集時可先關閉防火牆,否則可以出現一直join……的現象。 (2)redis叢集至少需要3個主節點,每個主節點有一個從節點總共6個節點 (3)replicas指定為1表示每個主節點有一個從節點 (4)如果出現[ERR] Sorry, can't connect to node錯誤:
1.ruby 和rubygem 版本太低,安裝新版本。檢視gem版本和redis版本(redis-cli -v可檢視redis版本) 2.檢視reids配置檔案,bind繫結的允許連線的ip是否正確。 3.是否redis配置檔案還是使用了密碼,使用了密碼也可能導致這個錯誤。
(5)如果出現[ERR] Node 127.0.0.1:7005 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0:
表示叢集時,之前的redis已有資料,那麼登入到7005的redis中,執行FLUSHALL即可
(6)如果出現ERR Slot 0 is already busy (Redis::CommandError):
用redis-cli登入到每個節點執行flushall和cluster reset即可2.6進入叢集:./redis-cli -c  -p 7001 -h 123.123.123.123(-c即-cluster 表示進入叢集模式,不加表示進入單機redis)
5.檢查叢集是否成功:進入集群后,鍵入cluster info,顯示cluster_state:ok,表示成功 6.設定密碼:
(1)登入到每個節點,執行 config set masterauth 你的密碼 config set requirepass 你的密碼 (2)隨後登入 7001/bin/redis-cli -c -h 112.74.55.239 -p 7004 -a 你的密碼,執行: config rewrite (3)防火牆開放7001到7006埠,以及redis匯流排:17001到17006:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 7001:7006 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 17001:17006 -j ACCEPT
7.JedisCluster連線redis叢集
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>  //2.9.0才支援cluster密碼認證,之前版本的jedisCluster.auth("密碼")方法裡面什麼都沒有實現,僅僅拋一個JedisClusterException("No way to dispatch this command to Redis Cluster.")
</dependency>
整合spring:        
<!-- redis叢集 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg index="0">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port1}"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port2}"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port3}"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port4}"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port5}"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="${redis.host}"></constructor-arg>
<constructor-arg index="1" value="${redis.port6}"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" value="${redis.timeout}"></constructor-arg>
<constructor-arg index="2" value="${redis.sockettimeout}"></constructor-arg>
<constructor-arg index="3" value="${redis.maxAttempts}"></constructor-arg>
<constructor-arg index="4" value="${redis.pass}"></constructor-arg>
<constructor-arg index="5" ref="jedisPoolConfig"></constructor-arg>
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/application*.xml")
public class RedisTest {
@Autowired
private JedisCluster jCluster;
@Test
public void testJCluster() {
jCluster.set("name", "RCL");
String name = jCluster.get("testName");
Assert.assertEquals("RCL", name);
}