Redis + Keepalived主從叢集的搭建及容錯移轉
設計思路: 當 Master 與 Slave 均運作正常時, Master負責服務,Slave負責Standby; 當 Master 掛掉,Slave 正常時, Slave接管服務,同時關閉主從複製功能; 當 Master 恢複正常,則從Slave同步資料,同步資料之後關閉主從複製功能,恢複Master身份,於此同時Slave等待Master同步資料完成之後,恢複Slave身份。 然後依次迴圈。
注意事項:
需要在Master與Slave上都開啟本地化策略,否則在互相自動切換的過程中,未開啟本地化的一方會將另一方的資料清空,造成資料完全丟失。 環境準備
叢集可以是單台機器的不同連接埠,也可以是多台機器,通常實際應用是,多台機器。假設目前已經安裝好了2台機器,IP和連接埠分別是
主Redis伺服器IP:192.168.1.148主Redis伺服器連接埠號碼:6379從Redis伺服器IP:192.168.1.158從Redis伺服器連接埠號碼:6379
設定一個虛擬IP
192.168.1.200
進入root使用者
xiaoyao@xiaoyao-virtual-machine:~$ su密碼: root@xiaoyao-virtual-machine:/home/xiaoyao#
主從兩個機器上分別安裝Keepalived
root@xiaoyao-virtual-machine:/home/xiaoyao# apt-get install keepalived
主從伺服器分別修改hosts檔案
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/hosts在檔案末尾添加192.168.1.148 redis148192.168.1.158 redis158
主伺服器建立設定檔
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/keepalived.conf
配置內容:
! Configuration File for keepalivedglobal_defs { router_id redis148}vrrp_script chk_redis { script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379" interval 2 timeout 2 fall 3}vrrp_instance redis { state MASTER # master set to SLAVE also interface eth0 virtual_router_id 50 priority 150 nopreempt # no seize,must add advert_int 1 authentication { #all node must same auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.200/24 } track_script { chk_redis } notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 192.168.1.158 6379" notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 192.168.1.158 6379" notify_fault /etc/keepalived/scripts/redis_fault.sh notify_stop /etc/keepalived/scripts/redis_stop.sh }
這裡可能會出錯,一般虛擬機器設定成:interface eth0,但是有的機器可能是em1,這個要根據情況來配置,否則建立虛擬IP會失敗。
舉個例子:
查看IP後是下面的樣子
root@ubuntu:/etc/init.d# cat /etc/network/interfaces# This file describes the network interfaces available on your system# and how to activate them. For more information, see interfaces(5).# The loopback network interfaceauto em1iface em1 inet staticaddress 192.168.0.33netmask 255.255.255.0gateway 192.168.0.1
那麼就應該配置成
interface em1
從伺服器建立設定檔
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/keepalived.conf
配置內容:
! Configuration File for keepalivedglobal_defs { router_id redis158}vrrp_script chk_redis { script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379" interval 2 timeout 2 fall 3}vrrp_instance redis { state BACKUP interface eth0 virtual_router_id 50 priority 100 advert_int 1 authentication { #all node must same auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.200/24 } track_script { chk_redis } notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 192.168.1.148 6379" notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 192.168.1.148 6379" notify_fault /etc/keepalived/scripts/redis_fault.sh notify_stop /etc/keepalived/scripts/redis_stop.sh }
在主伺服器和從伺服器上分別建立監控Redis的指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# mkdir /etc/keepalived/scriptsroot@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_check.sh
指令碼內容:
#!/bin/bash ALIVE=`/usr/local/bin/redis-cli -h $1 -p $2 PING` LOGFILE="/var/log/keepalived-redis-check.log" echo "[CHECK]" >> $LOGFILEdate >> $LOGFILEif [ $ALIVE == "PONG" ]; then : echo "Success: redis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1 exit 0 else echo "Failed:redis-cli -h $1 -p $2 PING $ALIVE " >> $LOGFILE 2>&1 exit 1 fi
Keepalived在轉換狀態時會根據狀態來呼叫: 當進入Master狀態時會呼叫redis_master 當進入Backup狀態時會呼叫redis_backup 當發現異常情況時進入Fault狀態呼叫redis_fault 當Keepalived程式終止時則呼叫redis_stop
下面在主從伺服器分別建立下列指令碼 在主伺服器上建立redis_master指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_master.sh
指令碼內容
#!/bin/bash REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3" LOGFILE="/var/log/keepalived-redis-state.log" echo "[master]" >> $LOGFILE date >> $LOGFILE echo "Being master...." >> $LOGFILE 2>&1 echo "Run MASTER cmd ..." >> $LOGFILE 2>&1$REDISCLI SLAVEOF $2 $3 >> $LOGFILE sleep 10 #delay 10 s wait data async cancel syncecho "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
在主伺服器上建立redis_backup指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_backup.sh
指令碼內容
#!/bin/bash REDISCLI="/usr/local/bin/redis-cli" LOGFILE="/var/log/keepalived-redis-state.log" echo "[backup]" >> $LOGFILE date >> $LOGFILE echo "Run SLAVEOF cmd ..." >> $LOGFILE $REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1 # echo "Being slave...." >> $LOGFILE 2>&1 sleep 15 #delay 15 s wait data sync exchange role
在主伺服器上建立redis_fault指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_fault.sh
指令碼內容
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[fault]" >> $LOGFILEdate >> $LOGFILE
在主伺服器上建立redis_stop指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_stop.sh
指令碼內容
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[stop]" >> $LOGFILE date >> $LOGFILE
在從伺服器上建立redis_master指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_master.sh
指令碼內容
#!/bin/bash REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3" LOGFILE="/var/log/keepalived-redis-state.log" echo "[master]" >> $LOGFILE date >> $LOGFILE echo "Being master...." >> $LOGFILE 2>&1 echo "Run SLAVEOF cmd ... " >> $LOGFILE $REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1#echo "SLAVEOF $2 cmd can't excute ... " >> $LOGFILE sleep 10 ##delay 15 s wait data sync exchange roleecho "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
在從伺服器上建立redis_backup指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_backup.sh
指令碼內容
#!/bin/bash REDISCLI="/usr/local/bin/redis-cli" LOGFILE="/var/log/keepalived-redis-state.log" echo "[BACKUP]" >> $LOGFILE date >> $LOGFILE echo "Being slave...." >> $LOGFILE 2>&1 echo "Run SLAVEOF cmd ..." >> $LOGFILE 2>&1$REDISCLI SLAVEOF $2 $3 >> $LOGFILE sleep 100 #delay 10 s wait data async cancel sync exit(0)
在從伺服器上建立redis_fault指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_fault.sh
指令碼內容
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[fault]" >> $LOGFILEdate >> $LOGFILE
在從伺服器上建立redis_stop指令碼
root@xiaoyao-virtual-machine:/home/xiaoyao# vim /etc/keepalived/scripts/redis_stop.sh
指令碼內容
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[stop]" >> $LOGFILE date >> $LOGFILE
主伺服器和從伺服器分別給指令碼添加可執行許可權
root@xiaoyao-virtual-machine:/home/xiaoyao# chmod +x /etc/keepalived/scripts/*.sh
啟動服務測試
啟動主伺服器上的Redis
root@xiaoyao-virtual-machine:/home/xiaoyao# service redis start
啟動從伺服器上的Redis
root@xiaoyao-virtual-machine:/home/xiaoyao# service redis start
啟動主伺服器上的Keepalived
root@xiaoyao-virtual-machine:/home/xiaoyao# /etc/init.d/keepalived start
啟動從伺服器上的Keepalived
root@xiaoyao-virtual-machine:/home/xiaoyao# /etc/init.d/keepalived start
通過虛擬ip串連Redis
root@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.200 INFO # Replicationrole:masterconnected_slaves:1slave0:ip=192.168.1.158,port=6379,state=online,offset=15,lag=1master_repl_offset:15repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:14
通過虛擬ip插入一條資料
root@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.200 SET Hello Redis
主從伺服器均能讀到此條資料
root@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.200 GET Helloroot@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.148 GET Helloroot@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.158 GET Hello
在主伺服器上殺死redis進程
root@xiaoyao-virtual-machine:/home/xiaoyao# killall -9 redis-server
查看主伺服器上的Keepalived日誌
root@xiaoyao-virtual-machine:/home/xiaoyao# tailf /var/log/keepalived-redis-state.log
查看從伺服器上的Keepalived日誌
root@xiaoyao-virtual-machine:/home/xiaoyao# tailf /var/log/keepalived-redis-state.log
查看從伺服器上的資訊
root@xiaoyao-virtual-machine:/home/xiaoyao# redis-cli -h 192.168.1.158 INFO# Replicationrole:masterconnected_slaves:0master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:0