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

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

本文來源 | 雲+社區專欄文章

作者 | 萬守兵,騰訊雲資深架構師。8年以上大型互聯網公司運維工作經驗,騰訊雲資深遷雲架構師,一直從事大型互聯網服務端架構設計和優化工作。個人專注於雲計算、k8s和 DevOps領域。

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

01環境說明

1.需求與目標

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

2.軟件版本

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

3.基本環境

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

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

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>就能得到當前主redis的ip和port。需要注意的是,Redis Sentinel 端口和 Redis 主節點均需要開放訪問權限。如果前端業務使用 Java,有 JedisSentinelPool 可以複用;如果前端業務使用 PHP,可以在 phpredis 的基礎上做二次封裝。/<master>

優點:

(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/document/product/215/18025

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

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/releases/

$ wget http://download.redis.io/releases/redis-3.2.8.tar.gz
$ 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>

^

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
基於騰訊雲CVM自建高可用Redis實踐

查看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的信息,發現報錯

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

查看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服務已經成功起來

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

查看sentinel服務已經啟動

(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
基於騰訊雲CVM自建高可用Redis實踐

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

● 發現172.16.2.2這臺redis-server提升為主:

 redis-cli -h 172.16.2.2 -p 6379 info replication
基於騰訊雲CVM自建高可用Redis實踐

在master上查看主從狀態

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

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

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

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

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

確認當前主可以執行寫操作

4.客戶端使用方式:

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

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

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

客戶端程序連接方式

方案二: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

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

正常情況下VIP指向172.16.2.4

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

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

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漂移操作。/<to-ip>/<to-port>/<to-ip>/<from-port>/<from-ip>/<state>/<role>/<master-name>

#修改三個服務器的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

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

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提升為主。

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

sentinel自動failover,將172.16.2.15提升為master

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

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

通過VIP成功查看sentinel狀態

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

通過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/software/keepalived-1.2.19.tar.gz 
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 { #執行的腳本
/> 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 {
/> 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 {
/> 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啟動後日志如下圖顯示則表示啟動成功

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

keepalived日誌輸出

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

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

查看vip地址已經綁定

5.測試驗證

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

04總結

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

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

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

(2)不同的大業務可以使用一套 Redis Sentinel 集群,代理該業務下的所有端口;

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

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

(5)自定義腳本傳入參數:<service> <role> <comment> <from> <from> ;/<from>/<from>/<comment>/<role>/<service>

(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/document/product/239。


分享到:


相關文章: