《Redis Sentinel集群部署》要點:
本文介紹了Redis Sentinel集群部署,希望對您有用。如果有疑問,可以聯系我們。
什么是Redis Sentinel
Redis Sentinel是用來實現Redis高可用的一套解決方案.Redis Sentinel由兩個部分組成:由一個或者多個Sentinel實例組成Sentinel系統;由一個主Redis服務器(Master Redis)和多個從Redis服務器(Slave Redis)組成主從備份的Redis系統.
Sentinel系統本身是一個分布式的系統,它的作用是監視Redis服務器,在Master Redis下線時,自動將某個Slave Redis提升為新的主服務器.Redis系統由Master Redis處理客戶端的命令請求,Slave Redis作為主服務器的備份而存在.
Redis Sentinel主要作用
Redis Sentinel系統架構圖
Sentinel的原理并不復雜:
Redis Sentinel環境準備
?
一個一主多從的Redis系統中,可以使用多個Sentinel進行監控任務以保證系統足夠穩健.此時,不僅Sentinel會同時監控主數據庫和從數據庫,Sentinel之間也會相互監控.在這里,建議大家Sentinel至少部署三個,并且使用奇數個Sentinel.
在三臺服務器上分別安裝Redis和Sentinel.需要注意的是,如果要給Redis設置密碼,需要在三個Redis的配置文件中設置相同的密碼.
安裝的Redis版本必須在2.8版本以上.
$ apt-get install redis-server redis-sentinel
配置Redis
三臺Redis主機配置類似,只是初次配置時角色不同.這里以主機dev-master-01
為例,其它兩臺按實際情況修改就行了.
Redis默認會綁定到127.0.0.1
,這里要在多臺機器間通信,我們將它綁定到主機IP上.
$ vim /etc/redis/redis.conf bind 192.168.2.210
如果要給Redis設置密碼,需要在三個Redis的配置文件中設置相同的密碼.
$ vim /etc/redis/redis.conf requirepass "000000"
設置主從復制
在兩個Slave Redis的配置文件中聲明所從屬的主數據庫.
$ vim /etc/redis/redis.conf slaveof 192.168.2.210 6379
這里需要注意一點:當一個Master配置需要密碼才能連接時,客戶端和Slave在連接時都需要提供密碼.Master通過requirepass
設置自身的密碼,不提供密碼無法連接到這個Master.Slave通過masterauth
來設置訪問Master時的密碼.
Sentinel可以切換主從數據庫,主數據庫可能會變成從數據庫,所以三臺機器上都需要同時設置requirepass
和masterauth
配置項.
$ vim /etc/redis/redis.conf requirepass "000000" masterauth "000000"
配置Sentinel
redis-sentinel軟件包中默認包含了一個名為sentinel.conf
的文件,默認在/etc/redis/sentinel.conf
.這里以主機dev-master-01
為例,其它兩臺配置類似,按實際情況修改就行了.
運行一個Sentinel所需的最少配置如下所示:
$ vim /etc/redis/sentinel.conf daemonize yes port 26379 bind 192.168.2.210 sentinel monitor redis-master 192.168.2.210 6379 2 sentinel down-after-milliseconds redis-master 5000 sentinel failover-timeout redis-master 180000 sentinel parallel-syncs redis-master 2 sentinel auth-pass redis-master 000000 sentinel notification-script redis-master /etc/redis/notify.sh sentinel client-reconfig-script redis-master /etc/redis/failover.sh logfile /var/log/redis/redis-sentinel.log
以上配置項說明:
daemonize yes
以后臺進程模式運行.
port 26379
Sentinel實例之間的通訊端口,該端口號默認為26379.
bind 192.168.2.210
Sentinel默認會綁定到127.0.0.1
,這里要在多臺機器間通信,我們將它綁定到主機IP上.
sentinel monitor redis-master 192.168.2.210 6379 2
Sentinel去監視一個名為redis-master的主服務器,這個主服務器的IP地址為192.168.2.210 ,端口號為6379.將這個主服務器判斷為失效至少需要2個Sentinel同意,一般設置為N/2+1(N為Sentinel總數).只要同意Sentinel的數量不達標,自動故障遷移就不會執行.
不過要注意,無論你設置要多少個Sentinel同意才能判斷一個服務器失效, 一個Sentinel都需要獲得系統中多數Sentinel的支持,才能發起一次自動故障遷移,并預留一個給定的配置紀元.(configuration Epoch ,一個配置紀元就是一個新主服務器配置的版本號).
sentinel down-after-milliseconds redis-master 5000
down-after-milliseconds
選項指定了Sentinel認為服務器已經斷線所需的毫秒數.如果服務器在給定的毫秒數之內,沒有返回Sentinel發送的PING命令的回復,或者返回一個錯誤,那么Sentinel將這個服務器標記為主觀下線(subjectively down,簡稱SDOWN).
不過只有一個Sentinel將服務器標記為主觀下線并不一定會引起服務器的自動故障遷移,只有在足夠數量的Sentinel都將一個服務器標記為主觀下線之后,服務器才會被標記為客觀下線(objectively down,簡稱ODOWN), 這時自動故障遷移才會執行.將服務器標記為客觀下線所需的Sentinel數量由對主服務器的配置(sentinel monitor參數)決定.
sentinel failover-timeout redis-master 180000
如果在多少毫秒內沒有把宕掉的那臺Master恢復,那Sentinel認為這是一次真正的宕機.在下一次選取時排除該宕掉的Master作為可用的節點,然后等待一定的設定值的毫秒數后再來探測該節點是否恢復,如果恢復就把它作為一臺Slave加入Sentinel監測節點群,并在下一次切換時為他分配一個”選取號”.
sentinel parallel-syncs redis-master 2
parallel-syncs
選項指定了在執行故障轉移時,最多可以有多少個從服務器同時對新的主服務器進行同步.這個數字越小,完成故障轉移所需的時間就越長.
如果從服務器被設置為允許使用過期數據集(slave-serve-stale-data
選項), 那么你可能不希望所有從服務器都在同一時間向新的主服務器發送同步請求.因為盡管復制過程的絕大部分步驟都不會阻塞從服務器,但從服務器在載入主服務器發來的RDB文件時,仍然會造成從服務器在一段時間內不能處理命令請求.
如果全部從服務器一起對新的主服務器進行同步,那么就可能會造成所有從服務器在短時間內全部不可用的情況出現.你可以通過將這個值設為1來保證每次只有一個從服務器處于不能處理命令請求的狀態.
sentinel auth-pass redis-master 000000
當Master設置了密碼時,Sentinel連接Master和Slave時需要通過設置參數auth-pass
配置相應密碼.
sentinel notification-script redis-master /etc/redis/notify.sh
指定Sentinel檢測到該監控的Redis實例failover時調用的報警腳本.腳本被允許執行的最大時間為60秒,超過這個時間腳本會被kill.該配置項可選,但線上系統建議配置.這里的通知腳本簡單的記錄一下failover事件.
# 創建通知腳本 $ vim /etc/redis/notify.sh #! /bin/bash echo "master failovered at `date`" > /var/log/redis/redis_issues.log
# 給腳本增加執行權限 $ chmod +x /etc/redis/notify.sh
sentinel client-reconfig-script redis-master /etc/redis/failover.sh
指定Sentinel failover之后重配置客戶端時執行的腳本,該配置項可選,但線上系統建議配置.
logfile /var/log/redis/redis-sentinel.log
日志文件所在位置,默認在/var/log/redis/redis-sentinel.log.
配置完Redis和Sentinel之后,按順序啟動各個角色.啟動順序如下:Master->Slave->Sentinel
,要確保按照這個順序依次啟動.
$ systemctl start redis
運行Sentinel有兩種方式:
雖然Redis Sentinel有單獨的軟件安裝包,但實際上它只是一個運行在特殊模式下的Redis實例.當前Redis Stable版已經自帶了redis-sentinel這個工具.你可以在啟動一個普通Redis實例時通過給定--sentinel
選項來啟動Redis Sentinel.
第一種:用單獨的可執行文件redis-sentinel
$ redis-sentinel /etc/redis/sentinel.conf
第二種:使用redis-server的—sentinel選項
$ redis-server /etc/redis/sentinel.conf --sentinel
以上兩種方式,都必須指定一個Sentinel的配置文件sentinel.conf.需要確保配置文件是可寫的,因為Sentinel會往配置文件里添加很多信息作為狀態持久化,這是為了重啟等情況下可以正確地恢復 Sentinel的狀態.
當配置文件無法寫入時,Sentinel會啟動失敗.Sentinel默認監聽26379端口,所以運行前必須確定該端口沒有被別的進程占用.
我們這里用redis-sentinel
方式來啟動:
$ systemctl start redis-sentinel
啟動成功后可以通過redis客戶端工具查看當前Sentinel的信息,終端輸入:
$ redis-cli -p 26379 -h 192.168.2.210 INFO Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:2 sentinel_scripts_queue_length:1 master0:name=redis-master,status=ok,address=192.168.2.210:6379,slaves=2,sentinels=1
Sentinel啟動后會輸出類似的日志:
$ tail -f /var/log/redis/redis-sentinel.log 6207:X 06 Jun 10:40:05.904 # Sentinel runid is 2b2446b24a2bd01b9f54a6b2ca4f945a3480dd7e 6207:X 06 Jun 10:40:05.904 # +monitor master redis-master 192.168.2.210 6379 quorum 2 6207:X 06 Jun 10:40:05.910 * +slave slave 192.168.2.211:6379 192.168.2.211 6379 @ redis-master 192.168.2.210 6379 6207:X 06 Jun 10:40:05.915 * +slave slave 192.168.2.212:6379 192.168.2.212 6379 @ redis-master 192.168.2.210 6379 6207:X 06 Jun 12:01:33.098 * +sentinel sentinel 192.168.2.211:26379 192.168.2.211 26379 @ redis-master 192.168.2.210 6379 6207:X 06 Jun 12:02:07.922 * +sentinel sentinel 192.168.2.212:26379 192.168.2.212 26379 @ redis-master 192.168.2.210 637968.2.212:6379 192.168.2.212 6379 @ redis-master 192.168.2.210 6379
輸出的結果表示開始監控redis-master集群,并輸出集群的基本信息.+slave
和+sentinel
分別代表成功發現了從數據庫和其他Sentinel.
重新打開sentinel.conf文件,發現Sentinel自動生成了一些信息,記錄了監控過程中的狀態變化.
$ cat /etc/redis/sentinel.conf # Generated by CONFIG REWRITE maxclients 4064 sentinel leader-epoch redis-master 0 sentinel known-slave redis-master 192.168.2.212 6379 sentinel known-slave redis-master 192.168.2.211 6379 sentinel current-epoch 0
列出所有被監視的主服務器,以及這些主服務器的當前狀態.
$ redis-cli ?-p 26379 -h 192.168.2.210 192.168.2.210:26379> sentinel master redis-master 1) "name" 2) "redis-master" 3) "ip" 4) "192.168.2.210" 5) "port" 6) "6379" 7) "runid" 8) "02d88a6105ce3277745c1fc65b695887f165f302" 9) "flags" 10) "master" 11) "pending-commands" 12) "0" 13) "last-ping-sent" 14) "0" 15) "last-ok-ping-reply" 16) "1096" 17) "last-ping-reply" 18) "1096" 19) "down-after-milliseconds" 20) "5000" 21) "info-refresh" 22) "4732" 23) "role-reported" 24) "master" 25) "role-reported-time" 26) "667578" 27) "config-epoch" 28) "0" 29) "num-slaves" 30) "2" 31) "num-other-sentinels" 32) "0" 33) "quorum" 34) "2" 35) "failover-timeout" 36) "180000" 37) "parallel-syncs" 38) "2" 39) "notification-script" 40) "/etc/redis/notify.sh"
測試Failover
我們讓dev-master-01主機上的redis-master主動休眠30秒來觀察failover過程:
$ redis-cli -p 6379 -h 192.168.2.210 -a 000000 DEBUG sleep 30
我們可以看到每個Sentinel進程都監控到Master掛掉,從sdown狀態進入odown,然后選舉了一個leader來進行failover,最終192.168.2.212
成為新的Master, Sentinel的日志輸出:
日志的幾個主要事件
在Redis Master角色上主要有以下幾個事件:
+sdown master redis-master 192.168.2.210 6379
,發現Master檢測失敗,主觀認為該節點掛掉,進入sdown狀態.+odown master redis-master 192.168.2.210 6379 #quorum 2/2
,有兩個Sentinel節點認為Master 6379掛掉,達到配置的quorum
值2,因此認為Master已經客觀掛掉,進入odown狀態.+try-failover master redis-master 192.168.2.210 6379
,表示Sentine開始進行故障恢復.+vote-for-leader 2b2446b24a2bd01b9f54a6b2ca4f945a3480dd7e 1
,準備選舉一個 Sentinel Leader來開始failover.+failover-end master redis-master 192.168.2.210 6379
,表示Sentinel完成故障修復,其中包括了Sentinel Leader的選舉、備選從數據庫的選擇等較為復雜的過程.+switch-master redis-master 192.168.2.210 6379 192.168.2.212 6379
, 切換Master節點,failover完成.-sdown slave 192.168.2.210:6379 192.168.2.210 6379 @ redis-master 192.168.2.212 6379
,192.168.2.210休眠完成后,作為Slave掛載到192.168.2.212后面,可見Sentinel確實同時在監控Slave狀態,并且掛掉的節點不會自動移除,而是繼續監控.在Redis Slave角色上主要有以下幾個事件:
?
Redis Slave上大多數都和Redis Master上的事件類似,不同的是Redis Slave還多了一步配置更新.
+config-update-from sentinel 192.168.2.210:26379 192.168.2.210 26379 @ redis-master 192.168.2.210 6379
查看Sentinel配置文件變更
經過一次failover后,會發現Sentinel配置文件變更了以下一些內容.可以看到Sentinel將最新的集群狀態寫入了配置文件.
$ cat /etc/redis/sentinel.conf # Generated by CONFIG REWRITE maxclients 4064 sentinel leader-epoch redis-master 1 sentinel known-slave redis-master 192.168.2.211 6379 sentinel known-slave redis-master 192.168.2.210 6379 sentinel known-sentinel redis-master 192.168.2.212 26379 bbf85fae74692d9527e77c5b0bb83a2b5db40dd2 sentinel known-sentinel redis-master 192.168.2.210 26379 2b2446b24a2bd01b9f54a6b2ca4f945a3480dd7e sentinel current-epoch 1
驗證下三臺主機上的角色
以下輸出信息,表明192.168.2.212上的Redis是Master角色.
$ redis-cli -p 6379 -h 192.168.2.212 -a 000000 info Replication # Replication role:master connected_slaves:2 slave0:ip=192.168.2.211,port=6379,state=online,offset=2312008,lag=0 slave1:ip=192.168.2.210,port=6379,state=online,offset=2312008,lag=0 master_repl_offset:2312008 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1639828 repl_backlog_histlen:672181
以下輸出信息,表明192.168.2.210上的Redis是Slave角色.
$ redis-cli -p 6379 -h 192.168.2.210 -a 000000 info Replication # Replication role:slave master_host:192.168.2.212 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_repl_offset:2222825 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:593455 repl_backlog_histlen:1048576
以下輸出信息,表明192.168.2.211上的Redis是Slave角色.
$ redis-cli -p 6379 -h 192.168.2.211 -a 000000 info Replication # Replication role:slave master_host:192.168.2.212 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_repl_offset:2283392 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
以下列出的是Sentinel接受的命令:
PING
:返回PONG.SENTINEL masters
:列出所有被監視的主服務器,以及這些主服務器的當前狀態.SENTINEL master <master name>
:用于查看監控的某個Redis Master信息,包括配置和狀態等.SENTINEL slaves <master name>
:列出給定主服務器的所有從服務器,以及這些從服務器的當前狀態.SENTINEL sentinels <master name>
:查看給定主服務器的Sentinel實例列表及其狀態.SENTINEL get-master-addr-by-name <master name>
:返回給定名字的主服務器的IP地址和端口號. 如果這個主服務器正在執行故障轉移操作,或者針對這個主服務器的故障轉移操作已經完成,那么這個命令返回新的主服務器的IP地址和端口號.SENTINEL reset <pattern>
:重置所有名字和給定模式pattern相匹配的主服務器.pattern 參數是一個Glob風格的模式.重置操作清除主服務器目前的所有狀態,包括正在執行中的故障轉移,并移除目前已經發現和關聯的,主服務器的所有從服務器和Sentinel.SENTINEL failover <master name>
:當主服務器失效時, 在不詢問其他Sentinel意見的情況下, 強制開始一次自動故障遷移(不過發起故障轉移的Sentinel會向其他Sentinel發送一個新的配置,其他Sentinel會根據這個配置進行相應的更新).SENTINEL reset <pattern>
:強制重設所有監控的Master狀態,清除已知的Slave和Sentinel實例信息,重新獲取并生成配置文件.SENTINEL failover <master name>
:強制發起一次某個Master的failover,如果該Master不可訪問的話.SENTINEL ckquorum <master name>
:檢測Sentinel配置是否合理,failover的條件是否可能滿足,主要用來檢測你的Sentinel配置是否正常.SENTINEL flushconfig
:強制Sentinel重寫所有配置信息到配置文件.SENTINEL is-master-down-by-addr <ip> <port>
:一個Sentinel可以通過向另一個Sentinel發送SENTINEL is-master-down-by-addr
命令來詢問對方是否認為給定的服務器已下線.SENTINEL MONITOR <name> <ip> <port> <quorum> SENTINEL REMOVE <name> SENTINEL SET <name> <option> <value>
增加和移除Sentinel
增加新的Sentinel實例非常簡單,修改好配置文件,啟動即可,其他Sentinel會自動發現該實例并加入集群.如果要批量啟動一批Sentinel節點,最好以30秒的間隔一個一個啟動為好,這樣能確保整個 Sentinel集群的大多數能夠及時感知到新節點,滿足當時可能發生的選舉條件.
移除一個Sentinel實例會相對麻煩一些,因為Sentinel不會忘記已經感知到的Sentinel實例,所以最好按照下列步驟來處理:
SENTINEL RESET *
命令來重置狀態,忘記將要移除的sentinel,每個進程之間間隔30秒.SENTINEL MASTER <mastername>
命令來觀察,或者查看配置文件.對于一個最小集群,Redis應該是一個Master帶上兩個Slave,并且開啟下列選項:
min-slaves-to-write 1 min-slaves-max-lag 10
這樣能保證寫入Master的同時至少寫入一個Slave,如果出現網絡分區阻隔并發生failover的時候,可以保證寫入的數據最終一致而不是丟失,寫入老的Master會直接失敗.
Slave可以適當設置優先級,除了0之外(0表示永遠不提升為Master),越小的優先級,越有可能被提示為Master.如果Slave分布在多個機房,可以考慮將和Master同一個機房的Slave的優先級設置的更低以提升他被選為新的Master的可能性.
考慮到可用性和選舉的需要,Sentinel進程至少為3個,推薦為5個.如果有網絡分區,應當適當分布(比如2個在A機房, 2個在B機房,一個在C機房)等.
客戶端從過去直接連接Redis ,變成:
SENTINEL get-master-addr-by-name master-name
獲取Redis地址信息.ROLE
命令查詢是否是Master.如果是,連接進入正常的服務環節.否則應該斷開重新查詢.SENTINEL sentinels <master-name>
來更新自己的Sentinel實例列表.當Sentinel發起failover后,切換了新的Master,Sentinel會發送 CLIENT KILL TYPE normal
命令給客戶端,客戶端需要主動斷開對老的Master的鏈接,然后重新查詢新的Master地址,再重復走上面的流程.這樣的方式仍然相對不夠實時,可以通過Sentinel
提供的Pub/Sub
來更快地監聽到failover事件,加快重連.
如果需要實現讀寫分離,讀走Slave,那可以走SENTINEL slaves <master name>
來查詢Slave列表并連接.
由于Redis是異步復制,所以Sentinel其實無法達到強一致性,它承諾的是最終一致性:最后一次failover的Redis Master贏者通吃,其他Slave的數據將被丟棄,重新從新的Master復制數據.此外還有前面提到的分區帶來的一致性問題.
其次,Sentinel的選舉算法依賴時間,因此要確保所有機器的時間同步,如果發現時間不一致,Sentinel實現了一個TITL模式來保護系統的可用性.
文章來自微信公眾號:運維之美
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/2399.html