redis的一主二從三哨兵(Windows)
redis的一主二從三哨兵(Windows)
一、一主二從配置
- redis官網下載最新版,然後複製三份,slave redis與master redis是一樣的,只是配置不一樣而已。如下,為了更好區分,可以將資料夾的命名加上master和slave標識,以及埠號。
- 配置檔案
修改每個redis中的redis.conf配置檔案,一主二從的模式,就是配置一個master redis與兩個slave redis。
- master需要修改redis.conf配置檔案引數有:
. bind 10.112.11.186 127.0.0.1 (繫結redis訪問地址,10.112.11.186是內網地址,即你cmd中ipconfig命令出來的ipv4ip地址,可以是公網ip,也可以是私網ip);
. port 6380(redis訪問埠號)
. protected-mode no(如果不配置哨兵,並且沒有設定連線密碼,那麼這個屬性一定要設定no,這是redis的安全模式,預設是yes,即開啟狀態,如果你沒有設定密碼,那麼你用redis的客戶端(如jedis)是無法訪問redis的)。報錯資訊如下:Cannot get master address from sentinel running @ 10.112.11.186:26381
. 其他優化引數,自行配置
- slave-6381 需要修改redis.conf配置檔案引數有:
. bind 10.112.11.186 127.0.0.1 (繫結redis訪問地址,10.112.11.186是內網地址,即你cmd中ipconfig命令出來的ipv4ip地址,可以是公網ip,也可以是私網ip);
. port 6381(redis訪問埠號)
. protected-mode no(如果不配置哨兵,並且沒有設定連線密碼,那麼這個屬性一定要設定no,這是redis的安全模式,預設是yes,即開啟狀態,如果你沒有設定密碼,那麼你用redis的客戶端(如jedis)是無法訪問redis的,報錯資訊如下:Cannot get master address from sentinel running @ 10.112.11.186:26381)。
. slaveof 127.0.0.1 6380(設定master 的連線ip和port)
. 其他優化引數,自行配置
- slave-6382 需要修改redis.conf配置檔案引數有:
. bind 10.112.11.186 127.0.0.1 (繫結redis訪問地址,10.112.11.186是內網地址,即你cmd中ipconfig命令出來的ipv4ip地址,可以是公網ip,也可以是私網ip);
. port 6382(redis訪問埠號)
. protected-mode no(如果不配置哨兵,並且沒有設定連線密碼,那麼這個屬性一定要設定no,這是redis的安全模式,預設是yes,即開啟狀態,如果你沒有設定密碼,那麼你用redis的客戶端(如jedis)是無法訪問redis的,報錯資訊如下:Cannot get master address from sentinel running @ 10.112.11.186:26381)。
. slaveof 127.0.0.1 6380(設定master 的連線ip和port)
. 其他優化引數,自行配置
- 啟動配置,為了不用每次從cmd中輸入命令列啟動redis,可以為每一個redis建立啟動指令碼。
startRedisServer.bat指令碼如下:
@echo off
redis-server.exe redis.windows.conf
@pause
-
啟動後,先啟動master redis,然後啟動slave redis
-
檢視redis資訊
注:使用redis.exe -p 6380連線redis,如果使用的redis port不是預設的埠6379,則必須加上埠號。
二、redis哨兵的配置
- 在每個redis中建立一個哨兵的配置檔案,sentinel.conf
sentinel.conf
# 雖然你前面配置主從模式的時候,已經關閉了保護模式,但由於再配置了哨兵後,客戶端連線的是哨兵,而不是直接連線主節點(從而實現了客戶端與master redis的解耦,這也是為什麼哨兵模式能實現完全自動化進行故障轉移的原因),所以需要在哨兵中關閉保護模式。
protected-mode no
#當前Sentinel服務執行的埠(其他兩個sentinel.conf配置,只要這個地方埠改成26381,和26382就行)
port 26380
# 哨兵監聽的主伺服器
sentinel myid 41fff2d5fcefd3bd55ee99430ac53e07ec84a064
#
sentinel monitor master 127.0.0.1 6382 2
#如果10秒後,mysater仍沒啟動過來,則啟動failover
sentinel down-after-milliseconds master 3000
# 執行故障轉移時, 最多有1個從伺服器同時對新的主伺服器進行同步
sentinel failover-timeout master 10000
主要對第三行的配置引數解釋一下:
sentinel monitor [master-name] [ip] [port] [quorum]
master-name:master名稱,自定義。sentinel使用master name來標識哪個redis是master redis,為什麼是用 name而不是用ip來標識master redis,是因為,哨兵模式下,master redis如果出現故障了,可以動態配置另外一臺slave redis作為新的master redis,所以master ip是不固定的,也就沒法使用固定ip來確定哪個是master
ip port : IP地址和埠號
quorun:票數,Sentinel需要協商同意master是否可到達的數量。
- 啟動配置,為了不用每次從cmd中輸入命令列啟動sentinel,可以為每一個sentinel建立啟動指令碼startRedisSentinel.bat
配置檔案只需要配置master的資訊就好啦,不用配置slave的資訊,因為slave能夠被自動檢測到(master節點中有關於slave的訊息)。
@echo off
redis-server.exe sentinel.conf --sentinel
@pause
-
啟動三個哨兵,無先後關係
-
客戶端jedis連線哨兵,程式碼
package com.redis;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 請填寫類註釋
* @since 2018年12月27日 15:30
*/
public class RedisCluster {
//key的過期時間
private final static Integer EXPIRE_DATE = 1800;
//過期單位
private final static TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
public static void main(String[] args) {
//master name,我們在哨兵上配置過的別名maserName
String maserName = "master";
Set<String> sentinels = new HashSet<>();
//設定所有的哨兵ip和port,不需要
sentinels.add("127.0.0.1:26380");
sentinels.add("127.0.0.1:26381");
sentinels.add("127.0.0.1:26382");
GenericObjectPoolConfig gPoolConfig=new GenericObjectPoolConfig();
//idle:在池中,處於空閒狀態的最大連線數
gPoolConfig.setMaxIdle(3);
//Total:在池中,一共有多少連線數
gPoolConfig.setMaxTotal(3);
//MaxWaitMillis:從idle佇列裡面取物件時,若阻塞的話,則最大等待時長
gPoolConfig.setMaxWaitMillis(10);
//jmx是否開啟監控
gPoolConfig.setJmxEnabled(true);
JedisSentinelPool sentinelPool = new JedisSentinelPool(maserName,sentinels,gPoolConfig);
//一個while死迴圈,每隔一秒往master塞入一個值,並且日誌列印
Jedis jedis = null;
while (true){
try{
jedis = sentinelPool.getResource();
int index = new Random().nextInt(100000);
String key = "k-" + index;
String value = "v-" + index;
jedis.set(key,value);
jedis.expire(key,EXPIRE_DATE);
System.out.printf("%s value is %s\n",key,jedis.get(key));
TimeUnit.MILLISECONDS.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}finally {
if(jedis != null){
jedis.close();
}
}
}
//sentinelPool.close();
}
}