1. 程式人生 > 程式設計 >Redis高可用架構

Redis高可用架構

前言

Redis是一個高效能的key-value資料庫,現時越來越多企業與應用使用Redis作為快取伺服器。樓主是一枚JAVA後端程式設計師,也算是半個運維工程師了。在Linux伺服器上搭建Redis,怎麼可以不會呢?下面樓主就帶著大家從0開始,依次搭建:Redis單機伺服器 -> Redis主從複製 ->Redis-Sentinel高可用。逐步搭建出高可用的Redis快取伺服器。

搭建Redis

1. 下載並解壓

首先從Redis官網下載Redis並解壓,樓主使用的版本是4.0.2。依次執行如下命令:

cd /opt
wget http://download.redis.io/releases/redis-4.0.2.tar.gz
tar -zcvf redis-4.0.2.tar.gz複製程式碼


    
如果沒有安裝`gcc`依賴包,則安裝對應依賴包複製程式碼
yum install -y gcc-c++ tcl複製程式碼

2. 編譯並安裝

下載並解壓完畢後,則對原始碼包進行編譯安裝,樓主的Redis安裝路徑為/usr/local/redis,同學們可以自行修改語句:make install PREFIX=你想要安裝的路徑

cd /opt/redis-4.0.2
make install PREFIX=/usr/local複製程式碼

複製Redis相關命令到/usr/sbin目錄下,這樣就可以直接執行這些命令,不用寫全路徑

cd /usr/local/redis/bin
sudo cp redis-* /usr/sbin複製程式碼

3. 建立Redis配置檔案

安裝完成之後將 Redis 配置檔案拷貝到系統配置目錄/etc/下,redis.confRedis 的配置檔案,redis.confRedis 原始碼目錄,port預設 6379。

cp /usr/local/redis-4.0.2/redis.conf  /etc/複製程式碼

Redis配置檔案主要引數解析參考

    daemonize  no               #redis程式是否以守護程式的方式執行,yes為是,no為否(不以守護程式的方式執行會佔用一個終端)
    pidfile /var/run/redis.pid  #指定redis程式的PID檔案存放位置
    port 6379                   #redis程式的埠號
    bind 127.0.0.1              #繫結的主機地址
    timeout  300                #客戶端閒置多長時間後關閉連線,預設此引數為0即關閉此功能
    loglevel verbose            #redis日誌級別,可用的級別有debug.verbose.notice.warning
    logfile stdout              #log檔案輸出位置,如果程式以守護程式的方式執行,此處又將輸出檔案設定為stdout的話,就會將日誌資訊輸出到/dev/null裡面去了
    databases 16                #設定資料庫的數量,預設為0可以使用select <dbid>命令在連線上指定資料庫id
    save <seconds><changes>   #指定在多少時間內重新整理次數達到多少的時候會將資料同步到資料檔案;
    rdbcompression yes          #指定儲存至本地資料庫時是否壓縮檔案,預設為yes即啟用儲存;
    dbfilename dump.db          #指定本地資料庫檔名
    dir ./                      #指定本地資料問就按存放位置;
    slaveof <masterip><masterport>    #指定當本機為slave服務時,設定master服務的IP地址及埠,在redis啟動的時候他會自動跟master進行資料同步
    masterauth <master-password>       #當master設定了密碼保護時,slave服務連線master的密碼;
    requirepass footbared       #設定redis連線密碼,如果配置了連線密碼,客戶端在連線redis是需要通過AUTH<password>命令提供密碼,預設關閉
    maxclients 128              #設定同一時間最大客戶連線數,預設無限制;redis可以同時連線的客戶端數為redis程式可以開啟的最大檔案描述符,如果設定 maxclients 0,表示不作限制。當客戶端連線數到達限制時,Redis會關閉新的連線並向客戶端返回max number of clients reached錯誤資訊
    maxmemory<bytes>           #指定Redis最大記憶體限制,Redis在啟動時會把資料載入到記憶體中,達到最大記憶體後,Redis會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大記憶體設定,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis新的vm機制,會把Key存放記憶體,Value會存放在swap區
    appendonly no               #指定是否在每次更新操作後進行日誌記錄,Redis在預設情況下是非同步的把資料寫入磁碟,如果不開啟,可能會在斷電時導致一段時間內的資料丟失。因為 redis本身同步資料檔案是按上面save條件來同步的,所以有的資料會在一段時間內只存在於記憶體中。預設為no
    appendfilename appendonly.aof       #指定跟新日誌檔名預設為appendonly.aof
    appendfsync everysec         #指定更新日誌的條件,有三個可選引數no:表示等作業系統進行資料快取同步到磁碟(快),always:表示每次更新操作後手動呼叫fsync()將資料寫到磁碟(慢,安全),everysec:表示每秒同步一次(折衷,預設值);
複製程式碼
3.1 設定後端啟動:

由於Redis預設是前端啟動,必須保持在當前的視窗中,如果使用ctrl + c退出,那麼Redis也就退出,不建議使用。

    vi /etc/redis.conf複製程式碼

修改Redis配置檔案把舊值daemonize no 改為 新值daemonize yes

3.2 設定訪問:

Redis預設只允許本機訪問,可是有時候我們也需要 Redis 被遠端訪問。

vi /etc/redis.conf複製程式碼

找到 bind 那行配置,預設是: # bind 127.0.0.1

去掉#註釋並改為: bind 0.0.0.0 此設定會變成允許所有遠端訪問。如果想指定限制訪問,可設定對應的IP。

3.3 配置Redis日誌記錄:

找到logfile那行配置,預設是:logfile "",改為logfile /var/log/redis_6379.log

3.4 設定 Redis 請求密碼:

vi /etc/redis.conf複製程式碼

找到預設是被註釋的這一行:# requirepass foobared

去掉註釋,把 foobared 改為你想要設定的密碼,比如我打算設定為:123456,所以我改為:requirepass "123456"

修改之後重啟下服務

有了密碼之後,進入客戶端,就得這樣訪問:redis-cli -h 127.0.0.1 -p 6379 -a 123456

4. Redis常用操作

4.1 啟動

/usr/local/redis/bin/redis-server /etc/redis.conf複製程式碼

4.2 關閉

    
```
/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown
```複製程式碼
4.3 檢視是否啟動

    ps -ef | grep redis複製程式碼

4.4 進入客戶端

    redis-cli
   複製程式碼

4.5 關閉客戶端

redis-cli shutdown複製程式碼

4.6 設定開機自動啟動配置

echo "/usr/local/redis/bin/redis-server /etc/redis.conf" >/etc/rc.local複製程式碼

4.7 開放防火牆埠

新增規則:iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT
儲存規則:service iptables save
重啟 iptables:service iptables restart複製程式碼

5. 將Redis註冊為系統服務

在/etc/init.d目錄下新增Redis服務的啟動,暫停和重啟指令碼:

    vi /etc/init.d/redis複製程式碼

    指令碼內容如下:複製程式碼
    #  
    # redis - this script starts and stops the redis-server daemon  
    #  
    # chkconfig:   - 85 15  
    # description:  Redis is a persistent key-value database  
    # processname: redis-server  
    # config:      /usr/local/redis/bin/redis-server
    # config:      /etc/redis.conf  
    # Source function library.  
    . /etc/rc.d/init.d/functions  
    # Source networking configuration.  
    . /etc/sysconfig/network  
    # Check that networking is up.  
    [ "$NETWORKING" = "no" ] && exit 0  
    redis="/usr/local/redis/bin/redis-server" 
    prog=$(basename $redis)  
    REDIS_CONF_FILE="/etc/redis.conf" 
    [ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis  
    lockfile=/var/lock/subsys/redis  
    <span class="hljs-function"><span class="hljs-title">start() {  
        [ -x $redis ] || exit 5  
        [ -f $REDIS_CONF_FILE ] || exit 6  
        echo -n $"Starting $prog: "  
        daemon $redis $REDIS_CONF_FILE  
        retval=$?  
        echo  
        [ $retval -eq 0 ] && touch $lockfile  
        return $retval  
    }  
    <span class="hljs-function"><span class="hljs-title">stop() {  
        echo -n $"Stopping $prog: "  
        killproc $prog -QUIT  
        retval=$?  
        echo  
        [ $retval -eq 0 ] && rm -f $lockfile  
        return $retval  
    }  
    <span class="hljs-function"><span class="hljs-title">restart() {  
        stop  
        start  
    }  
    <span class="hljs-function"><span class="hljs-title">reload() {  
        echo -n $"Reloading $prog: "  
        killproc $redis -HUP  
        RETVAL=$?  
        echo  
    }  
    <span class="hljs-function"><span class="hljs-title">force_reload() {  
        restart  
    }  
    <span class="hljs-function"><span class="hljs-title">rh_status() {  
        status $prog  
    }  
    <span class="hljs-function"><span class="hljs-title">rh_status_q() {  
        rh_status >/dev/null 2>&1  
    }  
    case "$1" in  
        start)  
            rh_status_q && exit 0  
            $1  
            ;;  
        stop)  
            rh_status_q || exit 0  
            $1  
            ;;  
        restart|configtest)  
            $1  
            ;;  
        reload)  
            rh_status_q || exit 7  
            $1  
            ;;  
        force-reload)  
            force_reload  
            ;;  
        status)  
            rh_status  
            ;;  
        condrestart|try-restart)  
            rh_status_q || exit 0  
        ;;  
        *)  
            echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart| reload|orce-reload}"  
            exit 2  
    esac複製程式碼

    賦予指令碼許可權複製程式碼
複製程式碼

    啟動、停止和重啟:複製程式碼
    service redis stop
    service redis restart複製程式碼

    至此,`Redis`單機伺服器已搭建完畢,下面我們看看主從架構如何搭建。複製程式碼
    # 搭建Redis主從架構複製程式碼
    ### 1. redis-server說明複製程式碼

    172.16.2.181:6379 從複製程式碼

2. Redis主從架構配置

  • 編輯從機的 Redis 配置檔案,找到 210 行(大概),預設這一行應該是註釋的: # slaveof
  • 我們需要去掉該註釋,並且填寫我們自己的主機的 IP 和 埠,比如:slaveof 172.16.2.185 6379,如果主機設定了密碼,還需要找到masterauth 這一行,去掉註釋,改為masterauth 主機密碼
  • 配置完成後重啟從機Redis 服務
  • 重啟完之後,進入主機的 redis-cli 狀態下redis-cli -h 127.0.0.1 -p 6379 -a 123456,輸入:INFO replication
    可以查詢到當前主機的 Redis處於什麼角色,有哪些從機已經連上主機。
    主機資訊`172.16.2.185`複製程式碼
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=172.16.2.181,port=6379,state=online,offset=28,lag=1
    master_replid:625ae9f362643da5337835beaeabfdca426198c7
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:28
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:28複製程式碼

    從機資訊`172.16.2.181`複製程式碼
    # Replication
    role:slave
    master_host:172.16.2.185
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:3
    master_sync_in_progress:0
    slave_repl_offset:210
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:625ae9f362643da5337835beaeabfdca426198c7
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:210
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:210複製程式碼

  • 此時已經完成了主從配置,我們可以測試下:
    我們進入主機的 redis-cli 狀態,然後 set 某個值,比如:set myblog YouMeek.com
  • 我們切換進入從機的 redis-cli 的狀態下,獲取剛剛設定的值看是否存在:get myblog,此時,我們可以發現是可以獲取到值的。
    ### 3. Redis主從架構總結複製程式碼
  • 需要注意的是:從庫不具備寫入資料能力,不然會報錯。 從庫只有只讀能力。
  • 主從架構的優點:除了減少主庫連線的壓力,還有可以關掉主庫的持久化功能,把持久化的功能交給從庫進行處理。
  • 第一個從庫配置的資訊是連上主庫,後面的第二個從庫配置的連線資訊是連上第一個從庫, 假如還有第三個從庫的話,我們可以把第三個從庫的配置資訊連上第二個從庫上,以此類推。
    # Redis Sentinel高可用架構搭建複製程式碼
    ### 1. 自動故障轉移複製程式碼
  • 雖然使用主從架構配置Redis做了備份,看上去很完美。但由於Redis目前只支援主從複製備份(不支援主主複製),當主Redis掛了,從Redis只能提供讀服務,無法提供寫服務。所以,還得想辦法,當主Redis掛了,讓從Redis升級成為主Redis
  • 這就需要自動故障轉移,Redis Sentinel帶有這個功能,當一個主Redis不能提供服務時,Redis Sentinel可以將一個從Redis升級為主Redis,並對其他從Redis進行配置,讓它們使用新的主Redis進行復製備份。
    Redis Sentinel架構圖- 圖片來自於CSDN 在Redis Sentinel環境下,jedis該如何配置" class="inited">
    注意:搭建`Redis Sentinel`推薦至少3臺伺服器,但由於樓主偷懶,下面用例只用了2臺伺服器。複製程式碼
    `Redis Sentinel`的主要功能如下:複製程式碼
  1. 監控:哨兵不斷的檢查masterslave是否正常的執行。
  2. 通知:當監控的某臺Redis例項發生問題時,可以通過API通知系統管理員和其他的應用程式。
  3. 自動故障轉移:如果一個master不正常運行了,哨兵可以啟動一個故障轉移程式,將一個slave升級成為master,其他的slave被重新配置使用新的master,並且應用程式使用Redis服務端通知的新地址。
  4. 配置提供者:哨兵作為Redis客戶端發現的權威來源:客戶端連線到哨兵請求當前可靠的master的地址。如果發生故障,哨兵將報告新地址。
    預設情況下,每個`Sentinel`節點會以每秒一次的頻率對`Redis`節點和其它的`Sentinel`節點傳送`PING`命令,並通過節點的回覆來判斷節點是否線上。複製程式碼
    如果在`down-after-millisecondes`毫秒內,沒有收到有效的回覆,則會判定該節點為主觀下線。複製程式碼
    如果該節點為`master`,則該`Sentinel`節點會通過`sentinel is-master-down-by-addr`命令向其它`sentinel`節點詢問對該節點的判斷,如果超過`<quorum>`個數的節點判定`master`不可達,則該`sentinel`節點會將`master`判斷為客觀下線。複製程式碼
    這個時候,各個`Sentinel`會進行協商,選舉出一個領頭`Sentinel`,由該領頭`Sentinel`對`master`節點進行故障轉移操作。複製程式碼
    故障轉移包含如下三個操作:複製程式碼
  1. 在所有的slave伺服器中,挑選出一個slave,並將其轉換為master
  2. 讓其它slave伺服器,改為複製新的master
  3. 將舊master設定為新masterslave,這樣,當舊的master重新上線時,它會成為新masterslave
    ### 2. 搭建Redis Sentinel高可用架構複製程式碼
    這裡使用兩臺伺服器,每臺伺服器上開啟一個`redis-server`和`redis-sentinel`服務。複製程式碼
    redis-server說明複製程式碼
    172.16.2.185:6379 主

    172.16.2.181:6379 從複製程式碼

    redis-sentinel說明複製程式碼
    172.16.2.185:26379

    172.16.2.181:26379複製程式碼

    ###### 2.1 建立Redis配置檔案複製程式碼
    如果要做自動故障轉移,則建議所有的`redis.conf`都設定`masterauth`,因為自動故障只會重寫主從關係,即`slaveof`,不會自動寫入`masterauth`。如果`Redis`原本沒有設定密碼,則可以忽略。複製程式碼
    `Redis`程式上面已經安裝過了,我們只需增加`redis-sentinel`的相關配置即可,將 `redis-sentinel`的配置檔案拷貝到系統配置目錄`/etc/`下,`sentinel.conf` 是 `redis-sentinel`的配置檔案,`sentinel.conf` 在 `Redis` 原始碼目錄。複製程式碼
    cp /usr/local/redis-4.0.2/sentinel.conf  /etc/複製程式碼

    修改`sentinel.conf`配置檔案內容如下:複製程式碼
    vi /etc/sentinel.conf複製程式碼
    protected-mode no
    sentinel monitor mymaster 172.16.2.185 6379 2
    # redis在搭建時設定了密碼,所以要進行密碼配置
    sentinel auth-pass mymaster “123456“
    #5秒內mymaster沒有響應,就認為SDOWN
    sentinel down-after-milliseconds mymaster 5000  
    sentinel failover-timeout  mymaster 15000複製程式碼

    在配置最後加上複製程式碼
    logfile /var/log/sentinel.log
    pidfile  /var/run/sentinel.pid
    daemonize yes複製程式碼

    配置檔案說明:複製程式碼
    1.port :當前Sentinel服務執行的埠複製程式碼
    2.dir : Sentinel服務執行時使用的臨時資料夾複製程式碼
    3.sentinel monitor master001 192.168.110.10163792:Sentinel去監視一個名為master001的主redis例項,這個主例項的IP地址為本機地址192.168.110.101,埠號為6379,而將這個主例項判斷為失效至少需要2個 Sentinel程式的同意,只要同意Sentinel的數量不達標,自動failover就不會執行複製程式碼
    4.sentinel down-after-milliseconds master001 30000:指定了Sentinel認為Redis例項已經失效所需的毫秒數。當例項超過該時間沒有返回PING,或者直接返回錯誤,那麼Sentinel將這個例項標記為主觀下線。只有一個 Sentinel程式將例項標記為主觀下線並不一定會引起例項的自動故障遷移:只有在足夠數量的Sentinel都將一個例項標記為主觀下線之後,例項才會被標記為客觀下線,這時自動故障遷移才會執行複製程式碼
    5.sentinel parallel-syncs master001 1:指定了在執行故障轉移時,最多可以有多少個從Redis例項在同步新的主例項,在從Redis例項較多的情況下這個數字越小,同步的時間越長,完成故障轉移所需的時間就越長複製程式碼
    6.sentinel failover-timeout master001 180000:如果在該時間(ms)內未能完成failover操作,則認為該failover失敗複製程式碼
    7.sentinel notification-script  :指定sentinel檢測到該監控的redis例項指向的例項異常時,呼叫的報警指令碼。該配置項可選,但是很常用複製程式碼
    ###### 2.2 開放防火牆埠複製程式碼
    新增規則:iptables -I INPUT -p tcp -m tcp --dport 26379 -j ACCEPT
    儲存規則:service iptables save
    重啟iptables:service iptables restart複製程式碼

    ###### 2.3 啟動redis-sentinel複製程式碼
    redis-sentinel  /etc/sentinel.conf複製程式碼

    在任意一臺機子均可檢視到相關服務資訊複製程式碼
    redis-cli -h 127.0.0.1 -p 26379

    INFO sentinel複製程式碼
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,status=ok,address=172.16.2.185:6379,slaves=1,sentinels=2複製程式碼

    ### 3. 自動故障轉移測試複製程式碼
    ###### 3.1 停止主Redis複製程式碼
    redis-cli -h 172.16.2.185 -p 6379 -a 123456 shutdown複製程式碼

    ###### 3.2 檢視redis-sentinel的監控狀態複製程式碼
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,address=172.16.2.181:6379,sentinels=2複製程式碼

    發現從庫提升為主庫。複製程式碼
    ###### 3.3 注意事項複製程式碼
  • 如果停掉master後,Sentinel顯示足夠數量的sdown後,沒有出現odowntry-failover,則檢查密碼等配置是否正確
  • 如果停掉master後,試圖切換的時候,發現日誌出現 failover-abort-not-elected,則分2種情況分別解決:
  1. 如果Redis例項沒有配置
    protected-mode yes
    bind 172.16.2.185複製程式碼

    則在`Sentinel` 配置檔案加上`protected-mode no`即可複製程式碼
  1. 如果Redis例項有配置
    protected-mode yes
    bind 172.16.2.185複製程式碼

    則在`Sentinel`配置檔案加上複製程式碼
    protected-mode yes
    bind 172.16.2.185複製程式碼

    至此,redis的高可用方案已經搭建完成。複製程式碼
    # VIP對外提供虛擬IP實現高可用複製程式碼
    ### 1. 現有情況概述複製程式碼
    客戶端程式(如JAVA程式)連線`Redis`時需要`ip`和`port`,但`redis-server`進行故障轉移時,主`Redis`是變化的,所以`ip`地址也是變化的。客戶端程式如何感知當前主`Redis`的`ip`地址和埠呢?`redis-sentinel`提供了介面,請求任何一個`Sentinel`,傳送`SENTINEL get-master-addr-by-name <master name>`就能得到當前主`Redis`的`ip`和`port`。複製程式碼
    客戶端每次連線`Redis`前,先向`sentinel`傳送請求,獲得主`Redis`的`ip`和`port`,然後用返回的`ip`和`port`連線`Redis`。複製程式碼
    這種方法的缺點是顯而易見的,每次操作`Redis`至少需要傳送兩次連線請求,第一次請求`Sentinel`,第二次請求`Redis`。複製程式碼
    更好的辦法是使用`VIP`,當然這對配置的環境有一定的要求,比如`Redis`搭建在阿里雲伺服器上,可能不支援`VIP`。複製程式碼
    `VIP`方案是,`Redis`系統對外始終是同一ip地址,當`Redis`進行故障轉移時,需要做的是將`VIP`從之前的`Redis`伺服器漂移到現在新的主`Redis`伺服器上。複製程式碼
    比如:當前`Redis`系統中主`Redis`的`ip`地址是`172.16.2.185`,那麼`VIP(172.16.2.250)`指向`172.16.2.185`,客戶端程式用`VIP(172.16.2.250)`地址連線`Redis`,實際上連線的就是當前主`Redis`,這樣就避免了向`Sentinel`傳送請求。複製程式碼
    當主`Redis`宕機,進行故障轉移時,`172.16.2.181`這臺伺服器上的`Redis`提升為主,這時`VIP(172.16.2.250)`指向`172.16.2.181`,這樣客戶端程式不需要修改任何程式碼,連線的是`172.16.2.181`這臺主`Redis`。複製程式碼
    ### 2.漂移VIP實現Redis故障轉移複製程式碼
    那麼現在的問題是,如何在進行`Redis`故障轉移時,將`VIP`漂移到新的主`Redis`伺服器上。複製程式碼
    這裡可以使用`Redis Sentinel`的一個引數`client-reconfig-script`,這個引數配置執行指令碼,`Sentinel`在做`failover`的時候會執行這個指令碼,並且傳遞6個引數`<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip>、<to-port>`,其中`<to-ip>`是新主`Redis`的`IP`地址,可以在這個腳本里做`VIP`漂移操作。複製程式碼
    sentinel client-reconfig-script mymaster /opt/notify_mymaster.sh複製程式碼

    修改兩個伺服器的`redis-sentinel`配置檔案`/etc/sentinel.conf`,增加上面一行。然後在`/opt/`目錄下建立`notify_mymaster.sh`指令碼檔案,這個指令碼做`VIP`漂移操作,內容如下:複製程式碼
    vi /opt/notify_mymaster.sh複製程式碼
    #!/bin/bash
    echo "File Name: $0"
    echo "Quoted Values: $@"
    echo "Quoted Values: $*"
    echo "Total Number of Parameters : $#"

    MASTER_IP=${6}  #第六個引數是新主redis的ip地址
    LOCAL_IP='172.16.2.185'  #當前伺服器IP,主機172.16.2.185,從機172.16.2.181
    VIP='172.16.2.250'
    NETMASK='24'
    INTERFACE='eth1'
    if [ ${MASTER_IP} = ${LOCAL_IP} ]; then
         sudo /sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE}  #將VIP繫結到該伺服器上
         sudo /sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE}
        exit 0
    else
         sudo /sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE}   #將VIP從該伺服器上刪除
       exit 0
    fi
    exit 1  #如果返回1,sentinel會一直執行這個指令碼複製程式碼

    賦予指令碼許可權複製程式碼
    chmod 755 /opt/notify_mymaster.sh複製程式碼

    現在當前主`Redis`是`172.16.2.185`,需要手動繫結`VIP`到該伺服器上。複製程式碼
    /sbin/ip  addr add 172.16.2.250/24 dev eth1
    /sbin/arping -q   -c 3 -A 172.16.2.250 -I eth1複製程式碼

    由於VIP只能繫結只有一臺機子,所以建議將改為`bind 0.0.0.0`新增至`redis.conf` 中複製程式碼
    vi /etc/redis.conf複製程式碼

    設定`bind 0.0.0.0`複製程式碼
    由於VIP只能繫結只有一臺機子,所以建議將改為`bind 0.0.0.0`新增至`sentinel.conf`中複製程式碼
    vi /etc/sentinel.conf複製程式碼

    設定`bind 0.0.0.0`複製程式碼
    重啟`Redis`複製程式碼
    service redis restart`複製程式碼

    重啟`Sentinel`複製程式碼
    redis-sentinel /etc/sentinel.conf複製程式碼

    隨後我們在另一臺機器`172.16.2.181`上,通過`VIP`訪問主機複製程式碼
    redis-cli -h 172.16.2.250 -p 6379 -a 123456 INFO replication複製程式碼

    可正常通訊,資訊如下:複製程式碼
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=172.16.2.181,offset=0,lag=0
    master_replid:325b0bccab611d329d9c2cd2c35a1fe3c01ae196
    master_replid2:c1f7a7d17d2c35575a34b00eb10c8abf32df2243
    master_repl_offset:22246293
    second_repl_offset:22241024
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:22237293
    repl_backlog_histlen:9001複製程式碼

    訪問主機的`Sentinel`複製程式碼
    redis-cli -h 172.16.2.250 -p 26379 INFO sentinel複製程式碼

    可正常通訊,資訊如下:複製程式碼
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,sentinels=3複製程式碼

    下面關閉主機的`Redis`服務,看看VIP是否漂移到另一臺伺服器上。複製程式碼
    redis-cli -h 172.16.2.185 -p 6379 -a 123456 shutdown複製程式碼

    檢視是否已進行切換複製程式碼
    redis-cli -h 172.16.2.250 -p 26379 INFO sentinel複製程式碼
    # Sentinel
    sentinel_masters:1
    sentinel_tilt:0
    sentinel_running_scripts:0
    sentinel_scripts_queue_length:0
    sentinel_simulate_failure_flags:0
    master0:name=mymaster,sentinels=3複製程式碼

    通過查詢`Sentinel`發現從機`172.16.2.181`提升為主。複製程式碼
    通過訪問`VIP`的方式連線`Redis`複製程式碼
    redis-cli -h 172.16.2.250 -p 6379 -a 123456 INFO replication複製程式碼

`

Replication

role:masterconnected_slaves:0master_replid:cab30a4083f35652053ffcd099d70b9aaf7a80f3master_replid2:3da856dd33cce4bedd54926df6797b410f1ab9e8masterreploffset:74657secondreploffset:36065replbacklogactive:1replbacklogsize:1048576replbacklogfirstbyteoffset:1replbackloghistlen:74657

從上面資訊可知,VIP已經飄移成功。可喜可賀,大吉大利,晚上吃雞。

總結

至此,高可用Redis快取服務已搭建完畢,遲點會再出一篇文章教大家如何通過JAVA連線Redis進行相關操作。至於Redis Cluster叢集方案,等有空再搭建然後再和大家一同分享。

參考文章

搭建一個redis高可用系統

Redis 安裝和配置

Redis 複製、Sentinel的搭建和原理說明

Redis 快速入門(官網翻譯)

Redis Sentinel機制與用法(一)

Redis哨兵-實現Redis高可用

讀懂Redis並配置主從叢集及高可用部署

在Redis Sentinel環境下,jedis該如何配置

redis sentinel 主從切換(failover)解決方案,詳細配置

Redis-3.2.1主從故障測試例項