redis高可用:keepalived+redis主從部署

原文鏈接:https://blog.csdn.net/liuguanghui1988/article/details/77098143

參考文獻:

https://blog.csdn.net/liuguanghui1988/article/details/77098143

1 Redis高可用的可選方案
Redis的高可用方案目前主要5種方式。
1)  Redis Master-Slave + Keepalived + VIP。
這是很經典的db架構,也可以用與mysql的主從切換。基本原理是:Keepalive通過腳本檢測master的存活,然後通過漂移VIP(Virtual IP)完成主從切換。
2)  Redis Master-Slave + DNS Service + Sentinel。
基本原理是Sentinel集羣進行Redis的存活檢測和Redis M-S狀態切換。完成切換之後,sentinel調用notification-script參數制定的配置文件,通知DNS Server更改DNS配置,master dns解析執行新的master。
3)  Redis Master-Slave + Configure Center(Zookeeper) + Sentinel.
基本原理和第三種方案相似,只是notification-script通知的是配置中心完成redis連接配置的修改,比如Zookeeper實現的配置中心。
4)  Redis Master-Slave + Sentinel + Twemproxy + Lvs.
這種方案層次比較多,sentinel通知twemproxy進行redis m-s的配置更改。
5)Redis Cluster,redis3.0發佈了該功能,穩定性還待市場檢驗。

本文演示第一種方案:Redis Master-Slave + Keepalived + VIP.

1. 基本構建與原理

1)Keepalived + VIP : 在redis master-slave上部署keepalived、redis instance存活檢測腳本、以及告警通知腳本。

2)當redis master失效的時候,VIP從master上漂移到slave上,完成m-s角色和配置更改。3)客戶端連接redis的參數中host設置的是VIP,整個切換過程對客戶端透明。

2. 優缺點與適用場景。

優點:實現簡單,成本低,整個切換過程對客戶端透明。

缺點:整個集羣的最大吞吐量受限於redis單實例的處理能力,除非一個應用使用多套這種Keepalived+VIP方案。因而擴展能力較差,而且不適合目前單機部署多個redis實例的部署場景。

適合場景:併發請求不是很高的應用。

2 安裝keepalived
1. tar zxf  keepalived-1.3.5.tar.gz 2. cd keepalived-1.3.5 3. ./configure --prefix=/usr/local/keepalived/ 4. make 5. make install 拷貝需要的文件: $ cp /usr/local/src/keepalived-1.3.5/keepalived/etc/init.d/keepalived /etc/init.d/keepalived $ cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ $ cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ $ mkdir -p /etc/keepalived/ $ cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf是默認的配置文件

第一步,安裝基礎庫

yum -y install openssl-devel libnl3-devel ipset-devel iptables-devel libnfnetlink-devel net-snmp-devel

第二步,源碼安裝keepalived

3 keepalived + Redis主從部署
3.1 部署拓補圖
基於如下的拓撲圖:


3.2 Redis主從配置
3.2.1 Redis安裝
步驟1: 首先從官網(http://download.redis.io/releases/)下載redis正式版的壓縮包redis-2.8.19.tar.gz   步驟2:編譯源碼安裝: cd /usr/local/src/ tar zxvf redis-2.8.19.tar.gz cd redis-2.8.19 make make install

3.2.2 修改redis配置文件
cd redis-2.8.19 vim redis.conf 修改相關配置項,這裏僅做DOME演示,其他配置項默認。 修改redis master的redis.conf daemonize yes logfile /var/log/redis.log 修改redis backup的redis.conf daemonize yes logfile /var/log/redis.log slaveof 172.30.1.22 6379

3.2.3 啓動Redis
分別啓動主從redis-server:
cd redis-2.8.19
./src/redis-server ./redis.conf
3.2.3 測試主從功能
在主機器上執行set key value:
[root@localhost redis-2.8.19]# ./src/redis-cli -p 6379
127.0.0.1:6379> set nosql redis
OK
127.0.0.1:6379> 
在從機器上執行get key:
[root@localhost redis-2.8.19]# ./src/redis-cli -p 6379
127.0.0.1:6379> get nosql
"redis"
127.0.0.1:6379> 
OK,測試正常。

3.2 主從公共腳本
3.2.1 Redis監控腳本
該腳本檢測redis的運行狀態,並在nginx進程不存在時嘗試重新啓動ngnix,如果啓動失敗則停止keepalived,準備讓其它機器接管。

/etc/keepalived/scripts/check_redis.sh:

#!/bin/bash
CHECK=`/usr/local/bin/redis-cli PING`
if [ "$CHECK" == "PONG" ] ;then
      echo $CHECK
      exit 0
else 
      echo $CHECK
      service keepalived stop #可確保讓出MASTER
      exit 1
fi


keepalived根據監控腳本的返回碼調整優先級:

☉如果腳本返回碼爲0,並且weight配置的值大於0,則優先級相應的增加;

☉如果腳本返回碼爲非0,並且weight配置的值小於0,則優先級相應的減少;

☉其他情況,原本配置的優先級不變,即配置文件中priority對應的值。

提示:

優先級不會不斷的提高或者降低;

可以編寫多個檢測腳本併爲每個檢測腳本設置不同的weight(在配置中列出就行);

不管提高優先級還是降低優先級,最終優先級的範圍是在[1,254],不會出現優先級小於等於0或者優先級大於等於255的情況;

在MASTER節點的 vrrp_instance 中 配置 nopreempt ,當它異常恢復後,即使它 prio 更高也不會搶佔,這樣可以避免正常情況下做無謂的切換。

以上可以做到利用腳本檢測業務進程的狀態,並動態調整優先級從而實現主備切換。

3.2.2 redis_fault.sh
vim /etc/keepalived/scripts/redis_fault.sh 

# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[fault]" >> $LOGFILE 
date >> $LOGFILE
3.2.3 redis_stop.sh
# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[stop]" >> $LOGFILE 
date >> $LOGFILE
vim /etc/keepalived/scripts/redis_stop.sh  

# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[stop]" >> $LOGFILE 
date >> $LOGFILE

3.3 keepalived scripts for redis
  爲redis配置keepalived所需要的腳本。

3.3.1 Redis Master scripts
  在redis master配置:

   vim/etc/keepalived/scripts/redis_master.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.23 6379 >> $LOGFILE  2>&1
sleep 10 #延遲10秒以後待數據同步完成後再取消同步狀態
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
vim /etc/keepalived/scripts/redis_backup.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1
sleep 15 #延遲15秒待數據被對方同步完成之後再切換主從角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.23 6379 >> $LOGFILE  2>&1
3.3.2 Redis Backup scripts
  和3.3.1節的配置基本一樣,只是腳本中redis的IP爲原master主機的IP。

  在redis backup配置:

 vim/etc/keepalived/scripts/redis_master.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.22 6379 >> $LOGFILE  2>&1
sleep 10 #延遲10秒以後待數據同步完成後再取消同步狀態
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
vim /etc/keepalived/scripts/redis_backup.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1
sleep 15 #延遲15秒待數據被對方同步完成之後再切換主從角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.22 6379 >> $LOGFILE  2>&1
3.4 配置keepalived.conf
keepalived.conf樣例

global_defs {
    router_id redis
}
 
vrrp_script chk_redis {
    script "/etc/keepalived/scripts/check_redis.sh"
    interval 4
    weight -5
    fall 3  
    rise 2
}
 
vrrp_instance VI_REDIS {
    state MASTER
    interface eth1
    virtual_router_id 51
    priority 100
    advert_int 1
    nopreempt
 
    authentication {
        auth_type PASS
        auth_pass 1111
    }
 
    virtual_ipaddress {
        172.30.1.15
    }
 
    track_script {
        chk_redis
    }
 
    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/redsi_stop.sh
}
注意,在同一個網段內的,若爲不同的應用做高可用,不同應用使用不同的VIP,那麼vrrp_instance的名字(這裏是VI_REDIS)、virtual_router_id在不同的高可用實例必須設置不同的值區分開。否則keepalived會報如下錯誤:

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: (VI_1): received an invalid ip number count 1, expected2!

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: bogus VRRP packet received on eth1 !!!

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: VRRP_Instance(VI_1) Dropping received VRRP packet...

以上是keepalived MASTER節點配置文件/etc/keepalived/keepalived.conf的配置信息。在BACKUP節點,只需把vrrp_instance->state改爲BACKUP,vrrp_instance->priority改爲99即可。

在默認的keepalive.conf裏面還有 virtual_server,real_server 這樣的配置,我們這用不到,它是爲lvs準備的。 notify 可以定義在切換成MASTER或BACKUP時執行的腳本,如有需求請自行google。

  配置選項說明

global_defs

☉notification_email: keepalived在發生諸如切換操作時需要發送email通知地址,後面的 smtp_server 相比也都知道是郵件服務器地址。也可以通過其它方式報警,畢竟郵件不是實時通知的。

☉router_id: 機器標識,通常可設爲hostname。故障發生時,郵件通知會用到

vrrp_instance

☉state : 指定instance(Initial)的初始狀態,就是說在配置好後,這臺服務器的初始狀態就是這裏指定的,但這裏指定的不算,還是得要通過競選通過優先級來確定。如果這裏設置爲MASTER,但如若他的優先級不及另外一臺,那麼這臺在發送通告時,會發送自己的優先級,另外一臺發現優先級不如自己的高,那麼他會就回搶佔爲MASTER

☉interface: 實例綁定的網卡,因爲在配置虛擬IP的時候必須是在已有的網卡上添加的,可以用ifconfig命令查看網卡。

☉mcast_src_ip: 發送多播數據包時的源IP地址,這裏注意了,這裏實際上就是在那個地址上發送VRRP通告,這個非常重要,一定要選擇穩定的網卡端口來發送,這裏相當於heartbeat的心跳端口,如果沒有設置那麼就用默認的綁定的網卡的IP,也就是interface指定的IP地址

☉virtual_router_id: 這裏設置VRID,這裏非常重要,相同的VRID爲一個組,他將決定多播的MAC地址

☉priority: 設置本節點的優先級,優先級高的爲master

☉advert_int: 檢查間隔,默認爲1秒。這就是VRRP的定時器,MASTER每隔這樣一個時間間隔,就會發送一個advertisement報文以通知組內其他路由器自己工作正常

☉authentication: 定義認證方式和密碼,主從必須一樣,樣例用的是密碼方式。

☉virtual_ipaddress: 這裏設置的就是VIP,也就是虛擬IP地址,他隨着state的變化而增加刪除,當state爲master的時候就添加,當state爲backup的時候刪除,這裏主要是有優先級來決定的,和state設置的值沒有多大關係。這裏可以設置多個虛擬IP地址,類似於一個域名可以解析對應多個IP地址。

☉track_script: 引用VRRP腳本,即在 vrrp_script 部分指定的名字。每隔vrrp_script->interval時間運行腳本,如果監控服務有異常則改變優先級,並最終引發主備切換。

vrrp_script

告訴 keepalived 在什麼情況下切換,所以尤爲重要。可以有多個 vrrp_script

☉script : 自己寫的檢測腳本。也可以是一行命令如killall-0 nginx

☉interval4 : 每4s檢測一次,這裏要大於監控腳本執行的時間,監控腳本會執行超時,☉keepalived會發送SIGTERM信號結束監控腳本的執行。

☉weight-5 : 檢測失敗(腳本返回非0)則優先級 -5

☉fall 2: 檢測連續 2 次失敗纔算確定是真失敗。會用weight減少優先級(1-255之間)

☉rise 1: 檢測 1 次成功就算成功。但不修改優先級

4.1啓動keepalived 
在Redis Master和Redis Backup上將keepalived啓動

啓動keepalived:

service keepalived start

或者

/etc/init.d/keepalived start

或者

/usr/local/keepalived/sbin/keepalived -f/etc/keepalived/keepalived.conf -D

查看進程,正常會有三個進程

[root@localhost ~]# ps -ef | grepkeepalived

root     3870     1  0 14:46 ?        00:00:00 keepalived -D

root     3872  3870  0 14:46 ?        00:00:00 keepalived -D

root     3873  3870  0 14:46 ?       00:00:00 keepalived -D

root     3887 18774  0 14:46 pts/1    00:00:00 grep keepalived

[root@localhost ~]#

用ip命令查看VIP,ifconfig命令不能查看虛擬IP。

[root@localhost ~]#  ip a | grep eth1

2: eth1:<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen1000

   inet 172.30.1.22/24 brd 172.30.1.255scope global eth1

   inet 172.30.1.15/32 scope global eth1

[root@localhost ~]#

  可以看到現在是172.30.1.22接管着VIP。

  至此,Keppalived+Redis主從高可用環境已經搭建完成。客戶端訪問Redis使用VIP,或者將redis的域名解析指向VIP。

4 測試
  測試時可以用命令tail -f /var/log/messages查看keepalived的日誌,查看主從機器狀態的變化,VIP的漂移等。

4.1 客戶端用VIP訪問Redis
  在另一臺客戶端機器,比如172.30.1.20,用VIP登錄redis,並使用get命令獲取之前設置的[key,value].
[root@localhost redis-2.8.19]# redis-cli -h 172.30.1.15 -p 6379
172.30.1.15:6379> get nosql
"redis"
172.30.1.15:6379>
  再設置一個新的[key,value].
172.30.1.15:6379> set movie ZhanLang2
OK
172.30.1.15:6379> get movie
"ZhanLang2"
172.30.1.15:6379>
  測試結果正常。

4.2 測試VIP漂移
測試之前,先看下那臺機器接管這VIP

在172.30.1.22機器查看
[root@localhost ~]# ip a | grep eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost ~]#
在172.30.1.23查看
[root@localhost ~]#  ip a | grep eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.23/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]# 
可見,VIP被172.30.1.22機器接管着。
現在,把172.30.1.22機器上的redis-server幹掉,再查看VIP是否還接管着:
[root@localhost ~]# pkill redis-server
[root@localhost ~]# ps -ef | grep redis-server | grep -v grep
root      7372 30964  0 13:57 pts/0    00:00:00 grep redis-server
[root@localhost ~]# ip a | grep eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]#
可見,172.30.1.22已經沒有接管VIP了。
在172.30.1.23查看下是否接管了VIP:
[root@localhost ~]# ip a | grep eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.23/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost ~]#
可見172.30.1.23已經接管了VIP,進入MASTER狀態了。
繼續測試在VIP下的redis讀寫:
還是在客戶端172.30.1.20下執行
172.30.1.15:6379> get movie
"ZhanLang2"
172.30.1.15:6379> set director WuJing
OK
172.30.1.15:6379>
測試正常,注意,剛剛設置了一個新的[key,value],待會把172.30.1.22上的redis-server起來後,再查詢這個新的[key,value]——[director,WuJing].
現在把172.30.1.22上的redis-server啓動,keepalived也需要啓動,以爲檢測腳本check_redis.sh檢測到redis-server不在時,把keepalived也退出了,確保MASTER角色的讓出。
[root@localhost redis-2.8.19]# cd /usr/local/src/redis-2.8.19
[root@localhost redis-2.8.19]# ./src/redis-server redis.conf 
[root@localhost redis-2.8.19]#  ps -ef | grep redis-server | grep -v grep
root      7841     1  0 14:25 ?        00:00:00 ./src/redis-server *:6379    
[root@localhost redis-2.8.19]# service keepalived start
Starting keepalived:                                       [  OK  ]
[root@localhost redis-2.8.19]# ip a | grep eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost redis-2.8.19]#
 
可見,啓動redis-server和keepalived後,172.30.1.22又重新接管了VIP,因爲172.30.1.22設置的優先級是100比172.30.1.23的優先級99要高。
在客戶端172.30.1.20下繼續測試redis的讀寫
先查詢剛剛設置的[director,WuJing]
172.30.1.15:6379> get director
"WuJing"
172.30.1.15:6379>
可以查詢到,說明數據已經同步過來了
再測試下寫數據
172.30.1.15:6379> set piaofang 4billion
OK
172.30.1.15:6379>
可見,寫redis也是正常的。
 
OK,現在高可用的基本功能測試已經完成。

 

http://www.keepalived.org/

https://github.com/acassen/keepalived

 

http://redisdoc.com/topic/sentinel.html

http://blog.csdn.net/l1028386804/article/details/52578080

http://mdba.cn/2015/03/06/redis%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9E%B6%E6%9E%84-keepalivevip/
 

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