redis+sentinel+keepalived 高可用,可實現多臺並單點訪問

       之前有寫過redis+sentinel的哨兵機制主從的切換,這一次多了一個keepalived,是爲了能夠方便項目只支持一臺訪問,可是又要高可用的情況下,就可以執行此方案。


本次主要講的就是keepalived的配置,如何才能做到單臺訪問而實現高可用,從而實現主從無縫切換。


1.有個問題需要注意

       當master down了,backup接管了,master再次起來,不能再成爲master。否則master恢復了再接管的話,會造成業務來回切換,這時候就需要nopreempt參數了。
 nopreempt:設置不搶佔,這裏只能設置在state爲backup的節點上,而且這個節點的優先級必須別另外的高。


先來看看方案的整體思路:

        通過keepalived的自定義腳本功能監控本機的redis服務狀態,當監控腳本檢測到redis服務出現異常時,則改變本機keepalived的優先級,同時這會導致master/backup角色的變化,而keepalived在角色變化時也會觸發一些機制執行相關腳本,這就爲我們改變redis的master/slave狀態提供了機會,這樣做的目的是爲了是redis的master/slave直接的數據保持一致。


    在keepalived+redis的使用過程中有三種情況:


    1 一種是keepalived掛了,同時redis也掛了,這樣的話直接VIP飄走之後,通過哨兵對redis數據同步,並切換主從,哨兵集羣會自動去切換,保證數據的一致性。


    2 另一種是keepalived掛了,redis沒掛,這時候VIP飄走後,redis的master/slave還是老的對應關係,如果不變化的話會把數據寫入redis slave中,從而不會同步到master上去,這就要藉助監控腳本反轉redis的master/slave關係。這時候就要預留一點時間進行數據同步,然後反轉master/slave。


    3 還有一種是keepalived沒掛,redis掛了,這時候根據監控腳本會檢測到redis掛了,並且降低keepalived master的優先級,同樣會導致VIP飄走,情況和第二種一樣,也是需要進行數據同步,然後反轉當前redis的master/slave關係的。

進入正題,安裝keepalived的過程就略了,安裝redis的也跳過,直接將keepalived的配置文件。


一.配置主keepalived

! Configuration File for keepalived

global_defs {
    lvs_id LVS_redis
}
vrrp_script chk_redis {
        script "/etc/keepalived/scripts/redis_check.sh"     #執行指定腳本
        weight -20                                          #腳本結果導致的優先級變更:20表示優先級+20;-20則表示優先級-20
        interval 2                                          #指定腳本的執行時間間隔
}

vrrp_instance VI_1 {
        state backup
        interface eth0                                     #把vip掛再哪個網卡上
        virtual_router_id 51
        nopreempt                                          #不搶佔資源,只有在主的keepalived設置
        priority 200                                       #權重值
        advert_int 5                                        
        track_script {
            chk_redis
        }
        virtual_ipaddress {
             192.168.18.230                                 #設置VIP
        }
        notify_master /etc/keepalived/scripts/redis_master.sh        
        notify_backup /etc/keepalived/scripts/redis_backup.sh
        notify_fault  /etc/keepalived/scripts/redis_fault.sh
        notify_stop   /etc/keepalived/scripts/redis_stop.sh
}

二.建立主redis切換狀態腳本

在/etc/keepalived目錄下建立log和scripts目錄。

在script下有五個腳本,一個是檢測redis狀態的redis_check.sh腳本,其餘四個是keepalived狀態變化時執行的腳本。keepalived有master/backup/stop/fault四種狀態,因爲我們主要是關注系統上的業務,所以在在keepalived進入fault/stop狀態後,也認爲是進入了backup狀態,需要對redis的master/slave關係進行反轉,否則即使VIP漂移過去,但是redis的主從關係還沒有改變,會導致數據不一致,所以最終四個腳本只有兩種內容。

(1)檢測腳本redis_check.sh (主從這裏配置都一樣)

#!/bin/bash
###/etc/keepalived/scripts/redis_check.sh
ALIVE=`/opt/redis/src/redis-cli PING`          #參考使用只修改redis-cli的路徑即可
if [ "$ALIVE" == "PONG" ]; then
  echo $ALIVE
  exit 0
else
  echo $ALIVE
  exit 1
fi

(2)keepalived進入master狀態時的檢測腳本redis_master.sh

#!/bin/bash
###/etc/keepalived/scripts/redis_master.sh
REDISCLI="/opt/redis/src/redis-cli"              #修改redis-cli的位置,如有做變量,則直接輸入爲"redis-cli"即可
LOGFILE="/etc/keepalived/log/redis-state.log"    #生成日誌路徑
pid=$$

echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.18.137 6379'" >> $LOGFILE            #修改下從redis的IP即可
$REDISCLI SLAVEOF 192.168.18.137 6379 >> $LOGFILE  2>&1                                                         #修改下從redis的IP即可
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] wait 10 sec for data sync from old master" >> $LOGFILE    
sleep 10
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] data rsync from old mater ok..." >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Run slaveof no one,close master/slave" >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait other slave connect...." >> $LOGFILE

(3)keepalived進入backup時的檢測腳本(stop和fault的腳本跟backup腳本一致,所以CP修改下名稱即可)

#!/bin/bash
###/etc/keepalived/scripts/redis_backup.sh
REDISCLI="/opt/redis/src/redis-cli"               
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$

echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait 10 sec for data sync from old master" >> $LOGFILE
sleep 10
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] data rsync from old mater ok..." >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.18.137 6379'" >> $LOGFILE          #修改從redis的IP即可
$REDISCLI SLAVEOF 192.168.18.137 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.18.137 ok..." >> $LOGFILE      #修改從redis的IP即可

三.從keepalived配置文件配置

! Configuration File for keepalived

global_defs {
    lvs_id LVS_redis
}

vrrp_script chk_redis {
        script "/etc/keepalived/scripts/redis_check.sh"
        weight  -20
        interval 2
}
vrrp_instance VI_1 {
        state backup
        interface eth0
        virtual_router_id 51
        priority 190                            #權重值要比主的低
        advert_int  5
        track_script {
             chk_redis
        }
        virtual_ipaddress {
             192.168.18.230
        }
        notify_master /etc/keepalived/scripts/redis_master.sh
        notify_backup /etc/keepalived/scripts/redis_backup.sh
        notify_fault  /etc/keepalived/scripts/redis_fault.sh
        notify_stop   /etc/keepalived/scripts/redis_stop.sh
}

四.從redis狀態切換腳本

在/etc/keepalived目錄下建立log和scripts目錄

(1)從redis服務狀態檢測腳本redis_check.sh(136上面內容和它一樣)

#!/bin/bash
###/etc/keepalived/scripts/redis_check.sh
ALIVE=`/opt/redis-3.2.3/src/redis-cli PING`     #修改redis-cli的路徑即可,如設置好變量,直接寫"redis-cli"即可
if [ "$ALIVE" == "PONG" ]; then
  echo $ALIVE
  exit 0
else
  echo $ALIVE
  exit 1
fi

(2)從 keepalived進入master狀態時的檢測腳本redis_master.sh

#!/bin/bash
###/etc/keepalived/scripts/redis_master.sh
REDISCLI="/opt/redis-3.2.3/src/redis-cli"                #修改redis-cli的路徑即可
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$

echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[backup]" >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[backup] Run 'SLAVEOF 192.168.18.136 6379'" >> $LOGFILE          #從redis要寫主redis的IP
$REDISCLI SLAVEOF 192.168.18.136 6379 >> $LOGFILE  2>&1                                                       #從redis要寫主redis的IP
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[backup] wait 10 sec for data sync from old master" >> $LOGFILE
sleep 10
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] data rsync from old mater ok..." >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Run slaveof no one,close master/slave" >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait other slave connect...." >> $LOGFILE

(3)從keepalived進入backup/stop/fault時的檢測腳本,由於內容都一致,所以只寫出redis_backup.sh

#!/bin/bash
###/etc/keepalived/scripts/redis_backup.sh
REDISCLI="/opt/redis-3.2.3/src/redis-cli"
LOGFILE="/etc/keepalived/log/redis-state.log"
pid=$$

echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] Being slave state..." >> $LOGFILE 2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] wait 15 sec for data sync from old master" >> $LOGFILE
sleep 15
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[master] data rsync from old mater ok..." >> $LOGFILE
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] Run 'SLAVEOF 192.168.18.136 6379'" >> $LOGFILE
$REDISCLI SLAVEOF 192.168.18.136 6379 >> $LOGFILE  2>&1
echo "`date +'%Y-%m-%d:%H:%M:%S'`|$pid|state:[slaver] slave connect to 192.168.18.136 ok..." >> $LOGFILE

五.開始實驗

     既然我們設置了nopreempt,那麼在啓動keepalived的時候就有啓動的順序問題了,我們把redis的master和keepalived的master(雖然配置文件中都是backup,但是我們是想讓136這臺做master的,由於在keepalived的master上面設置了nopreempt參數,所以在啓動keepalived服務的時候,一定要先啓動redis master的那臺,因爲在設置了nopreempt了,keepalived在啓動後都是先進入backup狀態,而腳本又設置了進入backup狀態後,會連接新的對方進行數據同步,所以,在啓動keepalived之前還有一個條件就是redis的master和slave中的數據必須一致。這樣先啓動redis的master那臺的keepalived,雖然redis master會連接到redis slave同步數據,但是兩邊數據在剛開始的時候是一致的,並不會產生什麼問題。


1.模擬一,首先我們把redis按順序啓動,然後查看哨兵以及redis.log是否數據同步。

查看redis日誌,我們發現以及跟137的達成同步了。


再查看哨兵日誌,發現136已經變成137的主了。


我們再把主redis關掉,會看到原來的主已經變成從了,而VIP也已經飄逸過去137身上了。



2.模擬二,把keepalived關掉,redis正常的情況下會發現它也自動切換VIP並把主變成了從。



         總結:從以上可以見得,不管是keepalived宕了,還是redis宕了,都會自動去執行腳本並切換他,使得無縫切換,更多的切換時間參數已經超時時間,後續你們自己配一下就好,我就不多說了,其他的現象,你們也可以模擬一下,在實驗的過程中發現有問題的,可以在下方評論,我會回饋你們的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章