1. 程式人生 > >redis主從復制和sentinel配置高可用

redis主從復制和sentinel配置高可用

中一 pass fig 命令 開始 amp 接收 保存 int

一:redis主從配置
1、環境準備

master : 192.168.50.10 6179
slave1: 192.168.50.10 6279
slave2: 192.168.50.10 6379
2、redis.conf配置文件配置

master

port 6179
requirepass 123456 #密碼認證,可以不設置
dir "/var/redis/6179" #工作目錄,dump.rdb會保留在這個目錄
slave1

port 6279
slaveof 192.168.50.10 6179 #master的ip和端口,不能使用127.0.0.1 6179

masterauth 123456 #如果master設置了requirepass,則這裏需要配置
slave-read-only yes #默認就是yes
dir "/var/redis/6279"
slave2

port 6379
slaveof 192.168.50.10 6179 #master的ip和端口,不能使用127.0.0.1 6179
masterauth 123456 #如果master設置了requirepass,則這裏需要配置
slave-read-only yes #默認就是yes

dir "/var/redis/6379"
註意:如果slaveof 127.0.0.1 6179,則鏈接sentinel時提示是127.0.0.1,無法連接

3、啟動redis並測試 ==> 如果設置了daemonize yes則沒有日誌輸出,默認是no

啟動: nohup redis-server /redis/redis.conf $1>>/var/log/redis/redis.log 2>&1 &

master 127.0.0.1:6179>info replication

slave1 127.0.0.1:6279>info replication

slave2 127.0.0.1:6379>info replication

在master中執行如下語句,如果所有機器執行keys* 都能查出name這個key說明能夠復制

127.0.0.1:6179> set name nametest
4、日誌分析

slave1和slave2一啟動就會去鏈接master

master啟動後,接受slave1和slave2的信息同步請求,進行RDB持久化(在內存中持久化)

5、redis主從同步規則

Salve會發送sync命令到Master
Master啟動一個後臺進程,將Redis中的數據快照保存到文件中
啟動後臺進程的同時,Master會將保存數據快照期間接收到的寫命令緩存起來
Master完成寫文件操作後,將該文件發送給Salve
Salve將文件保存到磁盤上,然後加載文件到內存恢復數據快照到Salve的Redis上
當Salve完成數據快照的恢復後,Master將這期間收集的寫命令發送給Salve端
後續Master收集到的寫命令都會通過之前建立的連接,增量發送給salve端
總結一下,主從剛剛連接的時候,進行全量同步;全同步結束後,進行增量同步。當然,如果有需要,slave 在任何時候都可以發起全量同步

註意:在redis2.8開始,slave重新啟動,會發送psync到master進行部分同步,而不是sync全量同步

二:Sentinel 組件實現HA配置
1、介紹

Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,功能類似於zk,用於監控redis master狀態,進行切換。

sentinel是和redis獨立的組件,不需要每個redis節點都啟動sentinel,可以在任何機器上部署,只要能夠連接redis master即可。

其功能類似於zk,用於監聽和選舉,可以啟動多個sentinel作為集群,只要連接的master相同,則認為是統一集群,sentinel集群中各個sentinel也有互相通信,通過gossip協議

一個sentinel可以監聽多個redis集群,他們是通過連接到redis master,利用發布/訂閱功能來發現其他sentinel的存在。

2、配置參數介紹

集群1 mymaster

# 至少2個sentinel認為mymaster掛了,才真正認為是掛了,所以sentinel至少要有2個在運行
sentinel monitor mymaster 192.168.50.10 6179 2
# sentinel向master發送ping,如果在這時間內沒有響應,則這個sentinel認為master掛了
sentinel down-after-milliseconds mymaster 60000
#
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
集群2 resque

sentinel monitor resque 192.168.50.10 6179 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
3、工作原理

鏈接master,獲取slave和其他sentinel信息,記錄到自己的sentinel.conf中,如下圖

sentinel發現down-after-milliseconds 時間內master沒有回復,則認為failor,它會問集群其他sentinel是否也有人認為失敗,個數達到sentinel monitor mymaster xxx 2,才會觸發failover

sentinel集群選舉其中一個sentinel拿著一個唯一的版本號去進行master切換。此sentinel指定一個slave發送SLAVE OF NO ONE,將其轉化為master,同時將這些配置信息廣播給其他sentinel,進行更新master信息

4、啟動 ===> 如果設置了daemonize yes則沒有日誌輸出

nohup redis-server redis-slave1/sentinel.conf --sentinel $1>>/var/log/sentinel/sentinel.log 2>&1 &
5、失敗測試=> 6379變成了6179的redis

6、註意

當一個master配置為需要密碼才能連接時,客戶端和slave在連接時都需要提供密碼。

master通過requirepass設置自身的密碼,不提供密碼無法連接到這個master。
slave通過masterauth來設置訪問master時的密碼。

但是當使用了sentinel時,由於一個master可能會變成一個slave,一個slave也可能會變成master,所以需要同時設置上述兩個配置項。
三:動態切換master測試
1、pom依賴

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2、代碼

public class JedisSentinelTest {
public static void main(String[] args) {
/**
* 獲取master鏈接~方法一
*/
HashSet<String> sentinelSet = new HashSet<>();
sentinelSet.add("192.168.50.10:26179"); // 這個節點目前是掛掉的,也可以配置,後續啟動有效
sentinelSet.add("192.168.50.10:26279");
sentinelSet.add("192.168.50.10:26379");
JedisSentinelPool myMasterSentinel = new JedisSentinelPool(www.tiaotiaoylzc.com"mymaster", sentinelSet);

Jedis master = myMasterSentinel.getResource();
master.set(www.fengshen157.com"aaaa", "aaaTest");
master.close();

/**
* 獲取master鏈接~方法二
*/
Jedis sentinelNode = new Jedis("192.168.50.10", 26179);
List<Map<String, String>> masterList www.shengbangyule178.cn= sentinelNode.sentinelMasters();
Map<String, String> masterMap = null;
for (Map<String, String> temp : masterList){
if ("mymaster".equals(temp.get("name"))){
masterMap = temp;
break;
}
}
System.out.println("masterIp:www.meiwanyule.cn" + masterMap.get("ip"));
System.out.println("masterPort:" + masterMap.get("port"));

List<String> mymaster = sentinelNode.sentinelGetMasterAddrByName("mymaster");
System.out.println("masterIp:" + mymaster.get(0));
System.out.println("masterPort:" + mymaster.get(1));

/**
* 獲取slaves
*/
Jedis jedis = new Jedis("192.168.50.10", 26179);
List<Map<String, String>> slaves www.myptvip8.com= jedis.sentinelSlaves("mymaster");
for (Map<String, String> temp : slaves){
System.out.println("slaveIp:" + temp.get("ip"));
System.out.println("slaveIp:" + temp.get("port"));
}

/**
* 主從切換
*/
Map<String, String> first = slaves.get(0);
Jedis toBeMaster = new Jedis(first.get("ip"), Integer.parseInt(first.get(www.huanhuayule.cn"port")));
String flag = toBeMaster.slaveofNoOne(); // 將自己設置為主節點

for (int i = 1; i < slaves.size(); i++){
Map<String, String> temp = slaves.get(i);
Jedis ortherSlave = new Jedis(temp.get("ip"), Integer.parseInt(temp.get("port")));
ortherSlave.slaveof(first.get(www.078881.cn/ "ip"), Integer.parseInt(first.get("port")));
}

Jedis slave = new Jedis("192.168.50.10", 6279);
/**
* 重新加載配置信息,復原
*/
slave.configResetStat();

/**
* 手動觸發RDB(save、bgsave)以及aof rewrite
*/
slave.save();
slave.bgsave();
slave.bgrewriteaof();

/**
* 獲取信息,可以知道自己是什麽角色
*/
String info = slave.info();

redis主從復制和sentinel配置高可用