基於騰訊雲CVM自建高可用Redis實踐

本文來源 | 雲+社區專欄文章
做者 | 萬守兵,騰訊雲資深架構師。8年以上大型互聯網公司運維工做經驗,騰訊雲資深遷雲架構師,一直從事大型互聯網服務端架構設計和優化工做。我的專一於雲計算、k8s和 DevOps領域。php

導讀:在企業實際生產環境中爲了可以給業務上層應用提供高可靠、低延遲、低數據損失的Redis緩存服務,本文經過對目前主流的幾種redis高可用方案進行對比分析,並基於騰訊雲CVM和HAVIP等基礎產品進行搭建、配置、測試、總結,供你們參考。前端

01環境說明redis

1.需求與目標docker

本文將經過對目前主流的幾種redis高可用方案進行對比分析,並基於騰訊雲CVM和HAVIP等基礎產品進行搭建、配置、測試、總結。vim

2.軟件版本緩存

redis用3.2.8版本,keepalived用1.2.19版本。bash

3.基本環境服務器

採用同一網絡內的三臺主機(能夠是物理主機、虛擬機或docker容器),要求三臺主機之間都能相互訪問。我這裏使用騰訊雲上3臺CVM,每臺CVM上開啓一個redis-server、redis-sentinel和keepalived服務,redis-server端口爲6379,redis-sentinel的端口爲26379(我這裏用默認端口,生產環境中能夠修改默認端口),3臺CVM上都安裝keepalived服務。微信

clipboard.png

02幾種redis高可用方案說明網絡

1.通常的主從複製方案

因爲redis目前只支持主從複製備份(不支持主主複製),當主redis掛了,從redis只能提供讀服務,沒法提供寫服務。因此,還得想辦法,當主redis掛了,讓從redis升級成爲主redis。

優勢:
(1)實現了對master數據的備份,一旦master出現故障,slave節點能夠提高爲新的master,頂替舊的master繼續提供服務

(2)實現讀擴展。使用主從複製架構, 通常都是爲了實現讀擴展。Master主要實現寫功能, Slave實現讀的功能

缺點:
(1)一旦主節點宕機,從節點晉升成主節點,同時須要修改應用方的主節點地址,還須要命令全部從節點去複製新的主節點,整個過程須要人工干預,此時須要通過以下操做(假設提高Slave1爲Master):

在Slave1上執slaveof no one命令提高Slave1爲新的Master節點
在Slave1上配置爲可寫,這是由於大多數狀況下,都將slave配置只讀
告訴Client端(也就是鏈接Redis的程序)新的Master節點的鏈接地址
配置Slave2重新的Master進行數據複製

(2)主節點的寫能力受到單機的限制

(3)主節點的存儲能力受到單機的限制

2.sentinel高可用方案

客戶端程序(如PHP程序)鏈接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 主節點均須要開放訪問權限。若是前端業務使用 Java,有 JedisSentinelPool 能夠複用;若是前端業務使用 PHP,能夠在 phpredis 的基礎上作二次封裝。

優勢:
(1)redis sentinel帶有自動故障轉移功能(failover),當一個主redis不能提供服務時,redis sentinel能夠將一個從redis升級爲主redis,並對其餘從redis進行配置,讓它們使用新的主redis進行復製備份;

(2)服務探測故障及時;

(3)DBA 維護成本低。

缺點:
(1)對應用有入侵性:客戶端每次鏈接redis前,先向sentinel發送請求,得到主redis的ip和port,而後用返回的ip和port鏈接redis。每次操做redis至少須要發送兩次鏈接請求,第一次請求sentinel,第二次請求redis;

(2)Sentinel服務器和Redis節點須要開放訪問權限。

3.redis-sentinel+VIP方案+自定義腳本方案

底層是Redis Sentinel 集羣,代理着 Redis 主從,Web端經過VIP提供服務。在部署Redis主從的時候,須要將虛擬IP綁定到當前的Redis 節點。當主節點發生故障,好比機器故障、Redis節點故障或者網絡不可達,Sentinel 集羣會調用 client-reconfig-script 配置的腳本,將VIP漂移到新的主節點上。

好比:當前redis系統中主redis的ip地址是172.16.2.4,那麼VIP(172.16.2.250)指向172.16.2.4,客戶端程序用VIP(172.16.2.250)地址鏈接redis,實際上鍊接的就是當前主redis,這樣就避免了向sentinel發送請求。

優勢:
(1)腳本自定義,架構可控;

(2)對應用透明,當主redis宕機,進行故障轉移時,192.168.56.102這臺服務器上的redis提高爲主,這時VIP(172.16.2.4)指向192.168.56.102,這樣客戶端程序不須要修改任何代碼,鏈接的是192.168.56.102這臺主redis;

(3)秒級切換,在 5s 內完成整個切換操做.

缺點:
(1)使用VIP增長維護成本,存在IP混亂風險;

(2)須要自行編寫VIP切換腳本,須要經過ip addr手動先在主redis上配置vip,配置相對複雜;

(3)Sentinel模式存在短期的服務不可用;

(4)應用場景侷限於內網,例如部分業務只能經過外網訪問Redis時,該方案不可用

注意:
VIP方案對配置的環境有必定的要求,在騰訊雲上搭建redis,須要用到騰訊雲HAVIP,文檔見:https://cloud.tencent.com/doc...

clipboard.png

4.redis-sentinel+keepalived方案

keepalived經過vrrp_script檢測當前主機上的redis-server是否以master狀態運行,若是當前主機上的redis-server正在以master狀態運行,則將vrrp_instance標記爲存活狀態,並分配VIP;若是當前主機上的redis-server正在以slave狀態運行,則將vrrp_instance標記爲錯誤狀態。當某臺主機宕機後,其餘兩臺主機上的keepalived會將VIP切換到新的master(當前主機上的redis-server正在以master狀態運行)上。

優勢:
(1)相對redis-sentinel+VIP方案,不需編寫VIP切換腳本,配置更簡潔、清晰;

(2)對應用透明;

(3)秒級切換。

缺點:
(1)對網絡環境有要求:keepalived的核心協議VRRP使用IP多播數據包進行封裝,組地址爲224.0.0.18,發佈範圍只限於同一局域網內,並且在網絡不受本身控制時基本不能用,可是騰訊雲是支持組播協議,可使用keepalived;

(2)存在腦裂;

(3)Sentinel模式存在短期的服務不可用

注意:
keepalived方案也須要一個VIP,且網絡要能支持組播協議。

03安裝部署
方案一:sentinel高可用方案

1.首先下載安裝redis:(http://download.redis.io/rele...
$ wget http://download.redis.io/rele...

$ tar -zxvf redis-3.2.8.tar.gz

$ cd redis-3.2.8

$ make (若是沒有安裝gcc會報錯,因此強烈建議在make以前先yum install gcc先安裝gcc)
make報錯以下:(make是用來編譯的,從Makefile中讀取指令,安裝到指定的位置)

make3: gcc: Command not found
make3: * net.o Error 127
make3: Leaving directory `/opt/redis-3.2.8/deps/hiredis'
make2: * hiredis Error 2
make2: Leaving directory `/opt/redis-3.2.8/deps'
make1: persist-settings Error 2 (ignored)
CC adlist.o
/bin/sh: cc: command not found
make1: * adlist.o Error 127
make1: Leaving directory `/opt/redis-3.2.8/src'
make: * all Error 2
安裝gcc:

yum install gcc
繼續編譯:

make
Make報錯以下:

make1: Entering directory `/opt/redis-3.2.8/src'
CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory

include <jemalloc/jemalloc.h>

^
compilation terminated.
make1: * adlist.o Error 1
make1: Leaving directory `/opt/redis-3.2.8/src'
make: * all Error 2
從新編譯:

make MALLOC=libc
編譯成功!!!

2.基本配置:

(1)make完後 redis-3.2.8目錄下會出現編譯後的redis服務程序redis-server,還有用於測試的客戶端程序redis-cli,兩個程序位於安裝目錄 src 目錄下:

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

$ cd src

$ cp redis-cli redis-server redis-sentinel /usr/sbin/
(2)在redis目錄下有redis.conf和sentinel.conf配置文件示例,將兩個配置文件複製到/etc目錄下(固然也能夠在/etc/目錄新建配置文件),而後修改配置文件

$ cp redis.conf sentinel.conf /etc/
(3)redis.conf 是一個默認的配置文件。咱們能夠根據須要修改配置文件

●修改主redis-server(172.16.2.4)配置文件內容以下:

不修改,使用默認端口

port 6379

修改成0.0.0.0,能夠從外部鏈接redis服務端

bind 0.0.0.0

默認狀況下redis運行在保護模式(這種模式下,訪問不須要密碼),可是這種模式只容許本地迴路訪問,這裏改成no

protected-mode no

默認狀況下,redis不是在後臺模式運行的,若是須要在後臺進程運行,把該項的值更改成yes,默認爲no

daemonize yes

redis服務之後臺進程運行的時候,Redis默認會把pid寫入/var/run/redis.pid文件組

pidfile /var/run/redis.pid

開啓AOF持久化,默認是關閉的,RDB默認是開啓的,可是AOF的優先級更高,啓動時Redis 會優先載入 AOF 文件來恢復數據,與 RDB 相比,AOF 的實時性更好,所以已成爲主流的持久化方案

若是不但願丟掉任何一條數據的話就該用純累加模式:一旦開啓這個模式,Redis會把每次寫入的數據在接收後都寫入 appendonly.aof 文件。

appendonly yes

● 修改從redis-server(172.16.2.2和172.16.2.15)配置文件內容以下:

不修改,使用默認端口

port 6379

修改成0.0.0.0,能夠從外部鏈接redis服務端

bind 0.0.0.0

默認狀況下redis運行在保護模式(這種模式下,訪問不須要密碼),可是這種模式只容許本地迴路訪問,這裏改成no

protected-mode no

默認狀況下,redis不是在後臺模式運行的,若是須要在後臺進程運行,把該項的值更改成yes,默認爲no

daemonize yes

redis服務之後臺進程運行的時候,Redis默認會把pid寫入/var/run/redis.pid文件組,改成yes

pidfile /var/run/redis.pid

開啓AOF持久化,默認是關閉的,RDB默認是開啓的,可是AOF的優先級更高,啓動時Redis 會優先載入 AOF 文件來恢復數據,與 RDB 相比,AOF 的實時性更好,所以已成爲主流的持久化方案

若是不但願丟掉任何一條數據的話就該用純累加模式:一旦開啓這個模式,Redis會把每次寫入的數據在接收後都寫入 appendonly.aof 文件。

appendonly yes

從redis比主redis多這一行,使用slaveof實現主從複製

slaveof 172.16.2.4 6379
● 啓動redis服務以前,建議先修改kernel參數,重啓生效

vim /etc/sysctl.conf

表示內核容許分配全部的物理內存,而無論當前的內存狀態如何

vm.overcommit_memory = 1

定義了TCP全鏈接隊列長度,默認128過小,啓動redis服務會報錯

net.core.somaxconn = 511

使配置文件永久生效

sysctl -p
(4)啓動redis-server服務:

$ redis-server & #加上‘&’號使redis之後臺程序方式運行

$ redis-server /etc/redis.conf #經過指定配置文件啓動,在生產環境中強烈建議使用這種方式啓動服務
(5)中止:

使用客戶端:

$ redis-cli shutdown
由於Redis能夠妥善處理SIGTERM信號,因此直接kill -9也是能夠的

$ kill -9 PID
(6)啓動redis服務進程後,就可使用測試客戶端程序redis-cli和redis服務交互了,鏈接redis-server:

$ redis-cli #本地鏈接redis-server,若是要鏈接遠程redis,redis-cli -h host -p port -a password

redis> set key1 value1

OK

redis> get key1

"value1"
(7)查看主從狀態:

經過redis-cli 進入主redis命令行,執行info replication查看當前主從配置,能夠發現兩個從節點信息,代表redis-server主從已經配置完畢。

redis> INFO replication
clipboard.png

查看redis主從關係已經創建

● 可能遇到的問題:redis主從創建失敗,有多是啓動服務時沒有指定正確的配置文件

● 解決思路:

(1)經過ps -ef查看服務進程ID

(2)經過lsof -p pid查看進程打開的文件,若是打開文件有誤,經過redis-server /etc/redis.conf指定正確的配置文件從新啓動服務

(8)搭建redis-sentinel系統:

redis-sentinel程序上面已經安裝過了,這裏只須要修改配置文件就能夠了。修改/etc/sentinel.conf以下:

● 三臺sentinel服務器配置都一致

當前Sentinel服務運行的端口

port 26379

監控的master的名字叫作mymaster(自定義),地址爲172.16.2.4:6379,行尾最後的一個2表明在sentinel集羣中,多少個sentinel認爲masters死了,才能真正認爲該master不可用了

sentinel monitor mymaster 172.16.2.4 6379 2

每一個Sentinel節點都要按期PING命令來判斷Redis數據節點和其他Sentinel節點是否可達,若是超過30秒且沒有回覆,則斷定不可達

sentinel down-after-milliseconds mymaster 30000

當Sentinel節點集合對主節點故障斷定達成一致時,Sentinel領導者節點會作故障轉移操做,選出新的主節點,原來的從節點會向新的主節點發起復制操做,限制每次向新的主節點發起復制操做的從節點個數爲1,在從Redis實例較多的狀況下這個數字越小,同步的時間越長,完成故障轉移所需的時間就越長

sentinel parallel-syncs mymaster 1

failover過時時間,當failover開始後,在此時間內仍然沒有觸發任何failover操做,當前sentinel將會認爲這次failover失敗。默認180秒,即3分鐘。

sentinel failover-timeout mymaster 18000

若是Sentinel監控的主節點配置了密碼,能夠經過sentinel auth-pass配置經過添加主節點的密碼,防止Sentinel節點沒法對主節點進行監控。

例如:sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

sentinel auth-pass

在故障轉移期間,當一些警告級別的Sentinel事件發生(指重要事件,如主觀下線,客觀下線等)時,會觸發對應路徑的腳本,想腳本發送相應的事件參數。

例如:sentinel notification-script mymaster /var/redis/notify.sh

sentinel notification-script

在故障轉移結束後,觸發應對路徑的腳本,並向腳本發送故障轉移結果的參數。

例如:sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

sentinel client-reconfig-script
● 常見問題:在172.16.2.4(主redis)上查看sentinel的信息,發現報錯

clipboard.png

查看sentinel服務報錯

● 解決方案:修改/etc/sentinel.conf文件

緣由是sentinel沒有指定bind和密碼訪問,因此被開啓了protected-mode保護模式,拒絕其餘sentinel的鏈接。致使進入了ODWON。在sentinel.conf里加入關閉保護,protected-mode no

protected-mode no

指定文件啓動sentinel服務

redis-sentinel sentinel.conf &
3.測試驗證:

(1)基本鏈接測試:

redis-cli -h host -p port info sentinel
三個redis-sentinel服務啓動完畢後,鏈接任意sentinel服務能夠獲知當前主redis服務信息,說明sentinel服務已經成功起來

查看sentinel服務已經啓動

clipboard.png

(2)測試sentinel的failover故障切換功能:

● 把主redis(172.16.2.4)停掉

redis-cli -h 172.16.2.4 -p 6379 shutdown
● 查看redis-sentinel的監控狀態:

redis-cli -h 172.16.2.4 -p 26379 info sentinel

clipboard.png

查看sentinel信息發現master已經切換爲172.16.2.2

● 發現172.16.2.2這臺redis-server提高爲主:

redis-cli -h 172.16.2.2 -p 6379 info replication

在master上查看主從狀態

● 控制檯也輸出相關信息,表示主從切換成功。

clipboard.png

控制檯log,redis主從切換成功

● 172.16.2.2切換成主以後,也能夠執行寫操做了。至此,redis的sentinel方案已經搭建完成。

clipboard.png

確認當前主能夠執行寫操做

4.客戶端使用方式:

客戶端程序(如PHP程序)鏈接redis時須要ip和port,但redis-server進行故障轉移時,主redis是變化的,因此ip地址也是變化的。客戶端程序如何感知當前主redis的ip地址和端口呢?redis-sentinel提供了接口,請求任何一個sentinel,發送SENTINEL get-master-addr-by-name<master name>就能獲得當前主redis的ip和port。

● 鏈接到sentinel獲取當前主redis的ip和端口(由於又執行了一次切換,這裏的主已經切換到172.16.2.15,這裏只是說明客戶端的使用方式)

clipboard.png

客戶端程序鏈接方式
方案二:redis-sentinel+vip方案

1.方案說明

VIP方案是redis系統對外始終是同一ip地址,當redis主從進行故障轉移時,須要作的是將VIP從以前的redis服務器漂移到如今新的主redis服務器上。
好比:當前redis系統中主redis的ip地址是172.16.2.4,那麼VIP(172.16.2.250)指向172.16.2.4,客戶端程序用VIP(172.16.2.250)地址鏈接redis,實際上鍊接的就是當前主redis,這樣就避免了向sentinel發送請求。

● 正常狀況下VIP指向172.16.2.4

clipboard.png

正常狀況下VIP指向172.16.2.4

● 故障狀況下,VIP漂移指向172.16.2.2

clipboard.png

clipboard.png

master故障狀況下,VIP自動漂移指向172.16.2.2

2.基本配置:

那麼如今的問題是,如何在進行redis故障轉移時,將VIP漂移到新的主redis服務器上。在方案一的配置基礎之上增長對sentinel.conf的配置,具體配置以下:
(1)在sentinel.conf配置文件設置要執行的vip漂移的腳本

使用sentinel.conf配置文件的有一個參數client-reconfig-script,這個參數配置執行腳本,sentinel在作failover的時候會執行這個腳本,而且傳遞6個參數<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>,其中<to-ip>是新主redis的IP地址,能夠在這個腳本里作VIP漂移操做。

修改三個服務器的redis-sentinel配置文件/etc/sentinel.conf,增長下面一行。

vi /etc/sentinel.conf

sentinel client-reconfig-script mymaster /opt/notify_mymaster.sh
(2)建立VIP漂移腳本(VIP用以前在騰訊雲控制檯上申請的VIP)

而後在/opt/目錄下建立notify_mymaster.sh腳本文件,這個腳本作VIP漂移操做。
chmod 777 notify_mymaster.sh #賦予腳本執行權限
腳本內容以下:

notify_mymaster.sh腳本內容

!/bin/bash

MASTER_IP=$6 #第六個參數是新主redis的ip地址

LOCAL_IP='172.16.2.2' #其餘兩個服務器上爲172.16.2.4,172.16.2.15

VIP='172.16.2.250'

NETMASK='24'

INTERFACE='eth0'

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會一直執行這個腳本
(3)第一次需在主redis上手工設置VIP

只須要第一次手工在主redis上設置vip,如今當前主redis是172.16.2.2,須要手動綁定VIP到該服務器上。(注意強烈建議加sudo執行)
sudo /sbin/ip addr add 172.16.2.250/24 dev eth0
sudo /sbin/arping -q -c 3 -A 172.16.2.250 -I eth0
3.測試驗證

(1)配置完成以後,去另外一個服務器上(172.16.2.15)經過VIP地址鏈接redis-server和redis-sentinel。從上面能夠看到主redis是172.16.2.2

clipboard.png

VIP成功綁定在master 172.16.2.2上

(2)驗證:下面關閉這臺主redis服務(172.16.2.2),看看VIP是否漂移到另外一臺服務器上

redis-cli -h 172.16.2.2 -p 6379 shutdown
經過查詢sentinel發現172.16.2.15提高爲主。

clipboard.png

sentinel自動failover,將172.16.2.15提高爲master

(3)經過訪問VIP鏈接查看redis sentinel信息和redis-server主從關係,發現VIP確實指向了172.16.2.15

clipboard.png

經過VIP成功查看sentinel狀態

clipboard.png

經過VIP成功查看redis的狀態
方案三:redis-sentinel+keepalived方案

1.方案說明

VIP方案是經過sentinel服務在作redis主從切換的時候,經過配置文件sentinel.conf中的一個參數client-reconfig-script來執行相應的腳本,這種方式須要本身編寫腳本。而keepalived方案經過vrrp_script檢測當前主機上的redis-server是否以master狀態運行,若是當前主機上的redis-server正在以master狀態運行,則將vrrp_instance標記爲存活狀態,並分配VIP;若是當前主機上的redis-server正在以slave狀態運行,則將vrrp_instance標記爲錯誤狀態。當某臺主機宕機後,其餘兩臺主機上的keepalived會將VIP切換到新的master(當前主機上的redis-server正在以master狀態運行)上。三臺CVM都須要安裝keepalived組件。

2.在VIP方案基礎之上安裝keepalived組件(3臺CVM都須要安裝)

wget -c http://www.keepalived.org/sof...

tar zxf keepalived-1.2.19.tar.gz

cd keepalived-1.2.19

./configure --prefix=/usr/local/keepalived

make

make install
3.基本配置

(1)編譯安裝keepalived以後,作初始化

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

cd /etc/init.d/

chkconfig --add keepalived

chkconfig keepalived on

mkdir -p /etc/keepalived
(2)關於keepalived的配置文件

keepalived的配置文件默認是沒有的,固然sample&example文件仍是有的,一般在PREFIX/etc/sample目錄下。
keepalived master和backup(backups)之間不一樣的是:

1.優先級的不一樣,master的優先級priority的數字要高一些,我這裏主redis上設置爲100,從redis上設置爲99;

2.global_defs段的router_id都不同,實際中能夠用任意名字區分也能夠用主機名區分;

3.backup的配置文件中還有一個nopreempt字段,意思是設置爲非搶佔模式,做用是讓master優先獲取到VIP,並保證VIP是在原先的master上。
● 主redis172.16.2.4上的配置:

vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {

notification_email { #指定keepalived在發生切換時須要發送email到的對象,一行一個

root@localhost

}

notification_email_from keepalived@localhost #指定發件人

smtp_server 127.0.0.1 #指定smtp服務器地址

smtp_connect_timeout 10 #指定smtp鏈接超時時間

router_id keepalivedha_1 #運行keepalived機器的一個標識

}

vrrp_script chk_http_port { #執行的腳本

script "redis-cli info | grep role:master >/dev/null 2>&1"

interval 1

timeout 2

fall 2

rise 1

}

vrrp_sync_group VG_1 { #監控多個網段的實例

group {

    VI_1        #實例名

}

}

vrrp_instance VI_1 {

state BACKUP

interface eth0      #設置實例綁定的網卡

#use_vmac keepalived

#vmac_xmit_base

mcast_src_ip 172.16.2.4

smtp_alert

virtual_router_id 20        #路由器標識,MASTER和BACKUP必須是一致的

priority 100        #優先級,高優先級競選爲master

advert_int 1

authentication {        #設置認證

    auth_type PASS      #認證方式

    auth_pass password      #認證密碼

}

virtual_ipaddress {     #設置vip

    172.16.2.250

}

track_script {      #監測的對象

    chk_http_port

}

}
● 從redis172.16.2.2上的配置:

! Configuration File for keepalived

global_defs {

notification_email {

root@localhost

}

notification_email_from keepalived@localhost

smtp_server 127.0.0.1

smtp_connect_timeout 10

router_id keepalivedha_2

}

vrrp_script chk_http_port {

script "redis-cli info | grep role:master >/dev/null 2>&1"

interval 1

timeout 2

fall 2

rise 1

}

vrrp_sync_group VG_1 {

group {

    VI_1

}

}

vrrp_instance VI_1 {

state BACKUP

interface eth0

#use_vmac keepalived

#vmac_xmit_base

mcast_src_ip 172.16.2.2

smtp_alert

virtual_router_id 20

priority 99

advert_int 1

authentication {

    auth_type PASS

    auth_pass password

}

virtual_ipaddress {

    172.16.2.250

}

track_script {

    chk_http_port

}

    nopreempt

}
● 從redis172.16.2.15上的配置:

! Configuration File for keepalived

global_defs {

notification_email {

root@localhost

}

notification_email_from keepalived@localhost

smtp_server 127.0.0.1

smtp_connect_timeout 10

router_id keepalivedha_3

}

vrrp_script chk_http_port {

script "redis-cli info | grep role:master >/dev/null 2>&1"

interval 1

timeout 2

fall 2

rise 1

}

vrrp_sync_group VG_1 {

group {

    VI_1

}

}

vrrp_instance VI_1 {

state BACKUP

interface eth0

#use_vmac keepalived

#vmac_xmit_base

mcast_src_ip 172.16.2.15

smtp_alert

virtual_router_id 20

priority 99

advert_int 1

authentication {

    auth_type PASS

    auth_pass password

}

virtual_ipaddress {

    172.16.2.250

}

track_script {

    chk_http_port

}

    nopreempt

}
4.啓動keepalived

service keepalived start

tail /var/log/messages
(1)若是在主redis上keepalived啓動後日志以下圖顯示則表示啓動成功

clipboard.png

keepalived日誌輸出

(2)用ip add查看VIP已經綁定到主redis上

clipboard.png

查看vip地址已經綁定

5.測試驗證

模擬主redis故障時,redis的set、get和複製狀況

(1)停掉主Redis(172.16.2.4)上的redis-server服務

clipboard.png

停掉主Redis(172.16.2.4)上的redis-server服務

(2)主Redis(172.16.2.4)上的VIP已經被移除

clipboard.png

主Redis(172.16.2.4)上的VIP已經被移除

(3)查看Redis(172.16.2.15)上的Redis狀態已經切換成master

clipboard.png

查看Redis(172.16.2.15)上的Redis狀態已經切換成master

(4)能夠看出,VIP已經漂移到新的redis master(172.16.2.15)上

clipboard.png

能夠看出,VIP已經漂移到新的redis-server master了

(5)從sentinel進行redis主從切換,到VIP的漂移過程是須要時間的,用ping VIP來作測試,中斷時間大概須要幾秒左右,以下圖所示:

clipboard.png

04總結

以上經過搭建、配置、驗證、測試,瞭解到幾種redis高可用方案各有優缺點,若是網絡環境可以支持組播協議,建議採用redis-sentinel+keepalived方案,這種方案配置更簡單;若是網絡環境不支持組播協議,可使用redis-sentinel+VIP方案;若是業務代碼上可以接受在每次操做redis以前都先額外進行一次sentinel查詢操做,就能夠採用sentinel方案。

如下是實戰過程當中總結出的最佳實踐:

(1)Redis Sentinel 集羣建議使用 >= 5 臺機器;

(2)不一樣的大業務可使用一套 Redis Sentinel 集羣,代理該業務下的全部端口;

(3)根據不一樣的業務劃分好 Redis 端口範圍;

(4)自定義腳本建議採用 Python 實現,擴展便利;

(5)自定義腳本傳入參數:<service_name> <role> <comment> <from_ip> <from_port> <to_ip> <to_port>;

(6)自定義腳本須要遠程 ssh 操做機器,建議使用 paramiko 庫,避免重複創建 SSH 鏈接,消耗時間;

(7)加速 SSH 鏈接,建議關閉如下兩個參數:
UseDNS no
GSSAPIAuthentication no

(8)微信或者郵件告警,建議 fork 一個進程,避免主進程阻塞;

(9)自動切換和故障切換,全部操做建議在 15s 之內完成。

以上幾種方案都是針對單個redis實例的高可用,比較適合中小型業務的應用。若是業務數據量比較大,併發量比較高的狀況下,建議搭建redis集羣,好比官方redis cluster和開源的codis方案,或者使用騰訊雲PAAS層redis集羣方案,文檔說明見:
https://cloud.tencent.com/doc...

相關文章
相關標籤/搜索