1. 程式人生 > >Redis進階實踐之十 Redis哨兵叢集模式

Redis進階實踐之十 Redis哨兵叢集模式

一、引言

             上一篇文章我們詳細的講解了Redis的主從叢集模式,其實這個叢集模式配置很簡單,只需要在Slave的節點上進行配置,Master主節點的配置不需要做任何更改,但是有一點,Master和Slave兩個節點的持久化配置儘量保持一致,否則會有奇怪的問題出現。從今天開始我們開始講Redis叢集模式的第二模式,也就是“哨兵”模式,該模式是從Redis的2.6版本開始提供的,但是當時這個版本的模式是不穩定的,直到Redis的2.8版本以後,這個哨兵模式才穩定下來,在生產環境中,如果想要使用Redis的哨兵模式,也會盡量使用Redis的2.8版本之後的版本。無論是主從模式,還是哨兵模式,這兩個模式都有一個問題,不能水平擴容,並且這兩個模式的高可用特性都會受到Master主節點記憶體的限制。還有一點,實現哨兵模式的配置也不簡單,甚至可以說有些繁瑣,所以在工業場景裡這兩個模式都不建議使用,如果要使用必須有相關的問題的解決方案,以免後續帶來的問題。

二、Redis Sentinel簡介



             Sentinel(哨兵)程序是用於監控redis叢集中Master主伺服器工作的狀態,在Master主伺服器發生故障的時候,可以實現Master和Slave伺服器的切換,保證系統的高可用,其已經被整合在redis2.6+的版本中,Redis的哨兵模式到了2.8版本之後就穩定了下來。一般在生產環境也建議使用Redis的2.8版本的以後版本。哨兵(Sentinel) 是一個分散式系統,你可以在一個架構中執行多個哨兵(sentinel) 程序,這些程序使用流言協議(gossipprotocols)來接收關於Master主伺服器是否下線的資訊,並使用投票協議(Agreement Protocols)來決定是否執行自動故障遷移,以及選擇哪個Slave作為新的Master。每個哨兵(Sentinel)程序會向其它哨兵(Sentinel)、Master、Slave定時傳送訊息,以確認對方是否”活”著,如果發現對方在指定配置時間(可配置的)內未得到迴應,則暫時認為對方已掉線,也就是所謂的”主觀認為宕機” ,英文名稱:Subjective Down,簡稱SDOWN。有主觀宕機,肯定就有客觀宕機。當“哨兵群”中的多數Sentinel程序在對Master主伺服器做出 SDOWN 的判斷,並且通過 SENTINEL is-master-down-by-addr 命令互相交流之後,得出的Master Server下線判斷,這種方式就是“客觀宕機”,英文名稱是:Objectively Down, 簡稱 ODOWN。通過一定的vote演算法,從剩下的slave從伺服器節點中,選一臺提升為Master伺服器節點,然後自動修改相關配置,並開啟故障轉移(failover)。

            哨兵(sentinel) 雖然有一個單獨的可執行檔案 redis-sentinel ,但實際上它只是一個執行在特殊模式下的 Redis 伺服器,你可以在啟動一個普通 Redis 伺服器時通過給定 --sentinel 選項來啟動哨兵(sentinel),哨兵(sentinel) 的一些設計思路和zookeeper非常類似。

           Sentinel叢集之間會互相通訊,溝通交流redis節點的狀態,做出相應的判斷並進行處理,這裡的主觀下線狀態和客觀下線狀態是比較重要的狀態,它們決定了是否進行故障轉移,可以 通過訂閱指定的頻道資訊,當伺服器出現故障得時候通知管理員,客戶端可以將 Sentinel 看作是一個只提供了訂閱功能的 Redis 伺服器,你不可以使用 PUBLISH 命令向這個伺服器傳送資訊,但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通過訂閱給定的頻道來獲取相應的事件提醒。一個頻道能夠接收和這個頻道的名字相同的事件。 比如說, 名為 +sdown 的頻道就可以接收所有例項進入主觀下線(SDOWN)狀態的事件。 

      1、Sentinel(哨兵)程序的作用:


              1】、監控(Monitoring): 哨兵(sentinel) 會不斷地檢查你的Master和Slave是否運作正常。

              2】、提醒(Notification):當被監控的某個Redis節點出現問題時, 哨兵(sentinel) 可以通過 API 向管理員或者其他應用程式傳送通知。

              3】、自動故障遷移(Automatic failover):當一個Master不能正常工作時,哨兵(sentinel) 會開始一次自動故障遷移操作,它會將失效Master的其中一個Slave升級為新的Master, 並讓失效Master的其他Slave改為複製新的Master;當客戶端試圖連線失效的Master時,叢集也會向客戶端返回新Master的地址,使得叢集可以使用現在的Master替換失效Master。Master和Slave伺服器切換後,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置檔案的內容都會發生相應的改變,即,Master主伺服器的redis.conf配置檔案中會多一行slaveof的配置,sentinel.conf的監控目標會隨之調換。

      
       2、Sentinel(哨兵)程序的工作方式:


             1】、每個Sentinel(哨兵)程序以每秒鐘一次的頻率向整個叢集中的Master主伺服器,Slave從伺服器以及其他Sentinel(哨兵)程序傳送一個 PING 命令。

             2】、如果一個例項(instance)距離最後一次有效回覆 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個例項會被 Sentinel(哨兵)程序標記為主觀下線(SDOWN)。

             3】、如果一個Master主伺服器被標記為主觀下線(SDOWN),則正在監視這個Master主伺服器的所有 Sentinel(哨兵)程序要以每秒一次的頻率確認Master主伺服器的確進入了主觀下線狀態。

             4】、當有足夠數量的 Sentinel(哨兵)程序(大於等於配置檔案指定的值)在指定的時間範圍內確認Master主伺服器進入了主觀下線狀態(SDOWN), 則Master主伺服器會被標記為客觀下線(ODOWN)。

             5】、在一般情況下, 每個 Sentinel(哨兵)程序會以每 10 秒一次的頻率向叢集中的所有Master主伺服器、Slave從伺服器傳送 INFO 命令。

             6】、當Master主伺服器被 Sentinel(哨兵)程序標記為客觀下線(ODOWN)時,Sentinel(哨兵)程序向下線的 Master主伺服器的所有 Slave從伺服器傳送 INFO 命令的頻率會從 10 秒一次改為每秒一次。

             7】、若沒有足夠數量的 Sentinel(哨兵)程序同意 Master主伺服器下線, Master主伺服器的客觀下線狀態就會被移除。若 Master主伺服器重新向 Sentinel(哨兵)程序傳送 PING 命令返回有效回覆,Master主伺服器的主觀下線狀態就會被移除。


       3、哨兵模式的環境:

             1】、Master主伺服器配置資訊:IP:192.168.127.128, Port:6379,OS:Linux

             2】、Slave從伺服器的配置資訊:IP:192.168.127.129 Port:6379,OS:Linux

             3】、在Slave從伺服器上安裝了一個哨兵程序(Sentinel),在Master伺服器也安裝了一個哨兵程序(Sentinel)。

             由於兩個Redis伺服器都是安裝在Linux作業系統上,而且這兩個Redis伺服器會在Master主伺服器發生故障的時候會進行切換,必須保證兩個Redis伺服器的埠號已經增加進了防火牆,或者把兩個Linux作業系統的防火牆關閉,否則會提示Master-link-Status:down,沒有連線上Master主伺服器。解決辦法有兩個:第一個辦法是關閉兩個Linux作業系統的防火牆;第二個辦法是把各個Redis服務的埠號增加到防火牆裡面,允許通過該埠號進行通訊。可以先使用命令 【firewall-cmd --query-port=6379/tcp】,如果結果是 No,那就繼續執行以下命令【firewall-cmd --add-port=6379/tcp】,命令執行後,返回Success,表示增加成功。這樣兩個Linux系統上的Redis伺服器就可以順利切換,執行哨兵模式的操作。


三、哨兵模式的配置

      下面是我使用的配置,需要修改的配置項我寫了出來,沒有更改的配置項就是用預設值,就不會寫出來:

      1、###### Master config(redis.conf)

複製程式碼
         1.1、### NETWORK 設定:

                  bind 192.168.127.128  //繫結IP地址,可以通過ifconfig 獲取Ip地址(在Linux系統下)

                  port 6379  //保持預設值,也可以修改

                  timeout 30  //Client 端空閒斷開連線的時間


         1.2、### GENERAL 設定:

                  daemonize yes   //預設值是no,把值修改為yes,以後臺模式執行

                  logfile /root/application/program/redis-tool/logs/redis.log  //日誌檔案的位置


         1.3、### SNAPSHOTTING 設定:

                  dir /root/application/program/redis-tool/datas   //SNAPSHOTTING檔案的路徑


         1.4、### APPEND ONLY MODE 設定:

                  appendonly yes  //預設值是No,意思是不使用AOF增量持久化的方式,使用RDB全量持久化的方式。把No值改成Yes,使用AOF增量持久化的方式

                  appendfsync always
複製程式碼


      2、###### Slave Config(redis.conf)

複製程式碼
          2.1、### NETWORK 設定:

                   bind 192.168.127.129   //繫結IP地址,可以通過ifconfig 獲取Ip地址(在Linux系統下)

                   port 6379   //保持預設值,也可以修改

                   timeout 30  //Client 端空閒斷開連線的時間


          2.2、### GENERAL 設定:

                   daemonize yes    //預設值是no,把值修改為yes,以後臺模式執行

                   logfile /root/application/program/redis/logs/redis.log  //日誌檔案的位置


          2.3、### SNAPSHOTTING 設定:

                   dir /root/application/program/redis/datas  //SNAPSHOTTING檔案的路徑


          2.4、### REPLICATION 設定:

                   slaveof 192.168.127.128 6379  //主伺服器的Ip地址和Port埠號

                   slave-serve-stale-data no  //如果slave 無法與master 同步,設定成slave不可讀,方便監控指令碼發現問題。


          2.5、### APPEND ONLY MODE 設定:

                   appendonly yes  //預設值是No,意思是不使用AOF增量持久化的方式,使用RDB全量持久化的方式。把No值改成Yes,使用AOF增量持久化的方式

                   appendfsync always
複製程式碼


      3、###### Sentinel Config(sentinel.conf,192.168.127.129 Slave從伺服器)

複製程式碼
          
          3.1、 ### Port 設定:

                port 26379  //哨兵埠號保持不變,可以修改,但是我沒有修改


          3.2、### dir 設定:

                dir /root/application/program/redis/sentinel/  //哨兵程式的日誌路徑


          3.3、### Sentinel Monitor 設定:

                sentinel monitor mymaster  192.168.127.129 6379 1


          3.4、### Down-After-Milliseconds 設定:

                sentinel down-after-milliseconds mymaster 5000

                //哨兵程式每5秒檢測一次Master是否正常


          3.5、### Parallel-Syncs 設定:

               sentinel parallel-syncs mymaster 1


          3.5、### Failover-Timeout 設定:

               sentinel failover-timeout mymaster 60000


          3.5、### 啟動:redis-sentinel

                   redis-server sentinel.conf --sentinel & //(&有這可以Ctrl +C退到命令列,沒有這個就直接退出哨兵程序)

                   redis-sentinel /path/to/sentinel.conf & //對於 redis-sentinel 程式, 你可以用以下命令來啟動 Sentinel 系統


          3.6、### 關閉:redis-sentinel

                  pkill redis-server   //這個會關掉Redis伺服器和Sentinel(哨兵)程序

                  kill 程序號     //可以關掉指定程序號的程序
複製程式碼


      4、###### 模式測試


               4.1、在Sentinel.conf配置檔案設定 sentinel monitor:

                         

               4.2、在Sentinel.conf配置檔案設定 sentinel down-after-milliseconds:

                           

               4.3、在Sentinel.conf配置檔案設定 sentinel parallel-syncs:

                           

               4.4、Master 主伺服器的配置詳情:

                          

               4.5、Slave 從伺服器配置詳情:

                         

               4.6、啟動Sentinel(哨兵)程序,開始對Master主伺服器進行監控:

                          


               4.7、我們人為模仿Master主伺服器宕機:

                           

               4.8、實現Master主伺服器和Slave從伺服器的切換:

                          

               4.9、主從切換後,主伺服器變成了Slave 從伺服器,詳情如下:

                            

               4.10、主從切換後,從伺服器變成了Master 主伺服器,詳情如下:

                          

           注意:

                ① INFO
                    sentinel的基本狀態資訊

               ②SENTINEL masters
                   列出所有被監視的主伺服器,以及這些主伺服器的當前狀態

               ③ SENTINEL slaves
                   列出給定主伺服器的所有從伺服器,以及這些從伺服器的當前狀態

               ④SENTINEL get-master-addr-by-name
                    返回給定名字的主伺服器的 IP 地址和埠號

               ⑤SENTINEL reset
                    重置所有名字和給定模式 pattern 相匹配的主伺服器。重置操作清除主伺服器目前的所有狀態, 包括正在執行中的故障轉移, 並移除目前已經發現和關聯的, 主伺服器的所有從伺服器和 Sentinel 。

               ⑥SENTINEL failover
                   當主伺服器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移,但是它會給其他sentinel傳送一個最新的配置,其他sentinel會根據這個配置進行更新


四、主觀下線和客觀下線

           下面我們來解釋一下兩個“下線”的概念,一個是“主觀下線”,另一個就是“客觀下線”。

            主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 例項對伺服器做出的下線判斷。

            客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 例項在對同一個伺服器做出 SDOWN 判斷,並且通過 SENTINEL is-master-down-by-addr 命令互相交流之後,得出的伺服器下線判斷。(一個 Sentinel 可以通過向另一個 Sentinel 傳送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認為給定的伺服器已下線。)


           如果一個伺服器沒有在 master-down-after-milliseconds 選項所指定的時間內,對向它傳送 PING 命令的 Sentinel(哨兵)程序返回一個有效回覆(valid reply),那麼  Sentinel(哨兵)程序就會將這個伺服器標記為主觀下線。

           伺服器對 PING 命令的有效回覆可以是以下三種回覆的其中一種:

               1、返回 +PONG 。

               2、返回 -LOADING 錯誤。

              3、返回 -MASTERDOWN 錯誤。

             如果伺服器返回除以上三種回覆之外的其他回覆,又或者在指定時間內沒有回覆 PING 命令,那麼 Sentinel(哨兵)程序認為伺服器返回的回覆無效(non-valid)。

             如果一個伺服器在 master-down-after-milliseconds 毫秒內,一直返回無效回覆才會被 Sentinel 標記為主觀下線。

             舉個例子,如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒),那麼只要伺服器能在每 29 秒之內返回至少一次有效回覆, 這個伺服器就仍然會被認為是處於正常狀態的。

            從“主觀下線”狀態切換到“客觀下線”狀態並沒有使用嚴格的法定人數演算法(strong quorum algorithm),而是使用了流言協議,該協議解釋為:如果 Sentinel(哨兵)程序在給定的時間範圍內,從其他 Sentinel(哨兵)程序那裡接收到了足夠數量的主伺服器下線報告, 那麼 Sentinel(哨兵)程序就會將主伺服器的狀態從“主觀下線”改變為“客觀下線”。如果之後其他 Sentinel(哨兵)程序不再報告主伺服器已下線,那麼“客觀下線”狀態就會被移除。

           “客觀下線”條件只適用於主伺服器:對於任何其他型別的 Redis 例項,  Sentinel(哨兵)程序在將它們判斷為下線前不需要進行協商,所以Slave從伺服器或者其他 Sentinel(哨兵)程序永遠不會達到“客觀下線”條件。

            只要有一個 Sentinel(哨兵)程序發現某個主伺服器進入了“客觀下線”狀態,這個 Sentinel(哨兵)程序就可能會被其他 Sentinel(哨兵)程序推選出,並對失效的主伺服器執行自動故障遷移操作。

五、Sentinel(哨兵)配置檔案簡介

          在Redis的原始碼中包含了一個名為 sentinel.conf 的檔案, 這個檔案就是帶有註釋的Sentinel(哨兵)的配置檔案的示例。

          如果想要執行一個“哨兵”程式,以下配置項是最少配置:

            sentinel monitor mymaster 127.0.0.1 6379 1

            sentinel down-after-milliseconds mymaster 60000

            sentinel failover-timeout mymaster 180000

            sentinel parallel-syncs mymaster 1


          第一行配置表示 Sentinel(哨兵)程序去監視一個名為 mymaster 的主伺服器,這個主伺服器的 IP 地址為 127.0.0.1 , 埠號為 6379,而將這個主伺服器判斷為失效至少需要 1 個 Sentinel(哨兵)程序的同意。如果在架構系統中已經配置類多個Sentinel(哨兵)程序,在同意“Master主伺服器”下線的 Sentinel(哨兵)程序的數量不達標的情況下,Sentinel(哨兵)程序就不會執行自動故障遷移。在設定多Sentinel(哨兵)程序的情況下,無論設定多少個 Sentinel(哨兵)程序同意才能判斷一個伺服器失效,一個 Sentinel 都需要獲得架構系統中多數 Sentinel(哨兵)程序的支援, 才能發起一次自動故障遷移,並預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主伺服器配置的版本號)。如果您只配置了一個Sentinel(哨兵)程序來做監控,那一個Sentinel(哨兵)程序也可以決定“Master主伺服器”是否下線。

           其他選項的基本格式如下:sentinel <選項的名字> <主伺服器的名字> <選項的值>

           配置選項的解釋如下:

            1、down-after-milliseconds : Sentinel(哨兵)程序判斷伺服器已經掉線所需的毫秒數。

                如果被監控的伺服器在給定的毫秒數之內,並沒有返回 Sentinel(哨兵)程序傳送的 PING 命令的回覆,或者返回一個錯誤,那麼 Sentinel(哨兵)程序將這個伺服器標記為主觀下線(subjectively down,簡稱 SDOWN )。如果在架構系統中配置了多個Sentinel(哨兵)程序的情況下,只有一個Sentinel(哨兵)程序將伺服器標記為主觀下線並不一定會引起伺服器的自動故障遷移,只有在足夠數量的 Sentinel(哨兵)程序都將一個伺服器標記為主觀下線之後,伺服器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ),這時才回執行自動故障遷移。另外一種情況是,在架構系統中只配置了一個Sentinel(哨兵)程序的話,那這Sentinel(哨兵)程序也可以決定被監控的伺服器的是否“下線”。

                將伺服器標記為客觀下線所需的 Sentinel(哨兵)程序數量由對主伺服器的配置決定。


           2、parallel-syncs :在執行故障轉移時,最多可以有多少個從伺服器同時對新的主伺服器進行同步,這個數字越小,完成故障轉移所需的時間就越長。

               如果“Slave從伺服器”被設定為允許使用過期資料集(參見對 redis.conf 檔案中對 slave-serve-stale-data 選項的說明),那麼你可能不希望所有“Slave從伺服器”都在同一時間向新的“Master主伺服器”傳送同步請求, 因為儘管複製過程的絕大部分步驟都不會阻塞“Slave從伺服器”,但“Slave從伺服器”在載入“Master主伺服器”發來的 RDB 檔案時, 仍然會造成“Slave從伺服器”在一段時間內不能處理命令請求,如果全部“Slave從伺服器”一起對新的“Master主伺服器”進行同步, 那麼就可能會造成所有“Slave從伺服器”在短時間內全部不可用的情況出現。

               你可以通過將這個值設為 1 來保證每次只有一個Slave從伺服器處於不能處理命令請求的狀態。

           3、failover-timeout:實現主從切換,完成故障轉移的所需要的最大時間值。若Sentinel(哨兵)程序在該配置值內未能完成故障轉移的操作(即故障時master/slave自動切換),則認為本次故障轉移操作失敗。

           4、notification-script: 指定Sentinel(哨兵)程序檢測到Master-Name所指定的“Master主伺服器”的例項異常的時候,所要呼叫的報警指令碼。該配置項可選,但線上系統建議配置。


六、哨兵模式的優缺點

       優點:

          1、哨兵叢集模式是基於主從模式的,所有主從的優點,哨兵模式同樣具有。

          2、主從可以切換,故障可以轉移,系統可用性更好。

          3、哨兵模式是主從模式的升級,系統更健壯,可用性更高。

       缺點:
        
          1、Redis較難支援線上擴容,在叢集容量達到上限時線上擴容會變得很複雜。為避免這一問題,運維人員在系統上線時必須確保有足夠的空間,這對資源造成了很大的浪費。


七、結束

           今天就寫到這裡了,Redis的哨兵模式是以主從模式為基礎的,所以說,主從模式擁有的一些缺點,在哨兵模式下也具有。哨兵模式主要是監控Master主伺服器的執行情況,當然也會監控Slave從伺服器的執行情況,如果Master主伺服器發生了故障,該模式可以保證Slave從伺服器順利升級為Master主伺服器繼續提供服務,以此提高系統的高可用性。雖然哨兵模式比主從模式提高了不少系統的高可用性,但是該模式不能水平擴容,不能動態的增、刪節點,這也是限制哨兵模式廣泛應用的主要原因。Redis也看到了這個情況,所在在Redis的3.x以後的版本提供了一個更加強大叢集模式,那就是Cluster叢集模式,這個模式也是我們下一篇文章的主題。