1. 程式人生 > >四、redis系列之主從複製與哨兵機制

四、redis系列之主從複製與哨兵機制

1. 緒言

  在現實應用環境中,出於資料容量、容災、效能等因素的考慮,往往不會只使用一臺伺服器,而是使用叢集的方式。Redis 中也有類似的維持一主多從的方式提高 Redis 叢集的高可用性的方案,而其中不可避免的則是如何保證主從例項間的資料一致性,複製(Replication)是其解決辦法。本篇介紹redis的主從複製及哨兵機制。

2. redis主從複製

2.1 主從拓撲

  Redis 支援簡單且易用的主從複製(master-slave replication)功能, 這一功能可以讓從伺服器(slave server)成為主伺服器(master server)的精確複製品,實現了資料的備份。一個主伺服器可以有多個從伺服器,而且不僅主伺服器可以有從伺服器, 從伺服器也可以有自己的從伺服器, 多個從伺服器之間可以構成一個圖狀結構。
下圖為redis多種主從模式的拓撲結構:
1)一主一從:



  這一拓撲結構主要用於主節點故障轉移從節點,當主節點的“寫”命令併發高且需要持久化,可以只在從節點開啟AOF(主節點不需要),這樣即保證了資料的安全性,也避免持久化對主節點的影響
2)一主多從:

  這一結構主要針對“讀”較多的場景,“讀”由多個從節點來分擔,但節點越多,主節點同步到多節點的次數也越多,影響頻寬,也加重主節點的穩定。
3)樹狀主從

  這一拓撲結構是對一主多從的補充,主節點只推送一次資料到slave1和slave2,再由從slave2推送到slave3和 slave4,減輕主節點推送的壓力。

2.2 配置

  我在virtualBox上配置了4伺服器,機器名分別為chb、chb1、chb2、chb3,ip地址如圖所示,且都已經安裝配置好了redis資料庫。我們要將chb設為主伺服器,其他三臺配置為從伺服器,該如何配置呢?


  Redis主從伺服器配置有一條規律叫做“配主不配從”,也就是說,進行主從伺服器配置時,對於主伺服器,我們不需要進行配置,只要配置從伺服器即可。所以,在上圖的4臺機器中,我們只需要對chb1、chb2、chb3進行配置即可。出於安全考慮,在配置前,我們在系統根目錄下新建一個myredis目錄,並將redis的配置檔案(redis.conf)拷貝一份到該目錄下,本篇主從複製操作我們主要基於該配置檔案進行(當然你也可以直接在安裝目錄配置下進行,非硬性要求)。對從伺服器(chb1、chb2、chb3)剛拷貝好的配置檔案新增如下配置:

slaveof 192.168.56.100 6379

  也就是:slaveof 主伺服器ip 埠號。

  然後修改配置中的bind屬性,bind屬性預設繫結127.0.0.1,如果redis主伺服器綁定了127.0.0.1,那麼跨伺服器IP的訪問就會失敗,從伺服器用IP和埠訪問主的時候,主伺服器發現本機6379埠綁在了127.0.0.1上,也就是隻能本機才能訪問,外部請求會被過濾,這是Linux的網路安全策略管理的。所以我們要進行修改(注:為方便下面的哨兵部分內容測試,4臺伺服器都要修改):

bind 0.0.0.0

  這是在測試環境上的配置,如果在生產環境中,就要繫結主伺服器的實際ip和埠。

  然後如下圖所示,我們分別啟動了4臺伺服器上的redis:


  然後,可以通過info replication命令檢視主從資訊:

  可以看到,chb(主伺服器)上有了3臺從伺服器,在從伺服器(chb1、chb2、chb3)上可以看到從屬於chb。
上面使用的是在配置檔案中進行主從伺服器配置,還有一種方法就是通過命令列的方式配置,這種方式直接在從伺服器上執行命令slaveof 192.168.56.100 6379就可以了(當然,也要去配置檔案中修改bind屬性)。通過命令列的方式修改是一次性的,也就是說,當redis服務關閉後,下次重啟就無效了。

2.3 功能

  主從複製有什麼作用呢?
  第一:容災恢復。當主伺服器發生故障時,從伺服器還有資料備份,亦可轉換為主伺服器使用。
  我們嘗試分別在主從伺服器上分別進行資料操作:

  我們現在chb主伺服器上新建了k1、k2,然後分別在三臺從伺服器上獲取k1、k2的值,發現時可以成功獲取的。證明從伺服器可以成功複製主伺服器上的資料,而且複製的是主伺服器上的所有資料,可不單單是主從關係建立之後才新建的資料。
  第二:讀寫分離。對於讀佔比較高的場景,可以通過把一部分流量分攤匯出從伺服器 來減輕主主伺服器壓力,同時需要主要只對主節點執行寫操作。

  如上圖所示,只能在主伺服器上進行寫操作,在從伺服器上的寫操作都失敗了,這就實現了讀寫分離。

3. 哨兵(sentinel)

  上面說到容災恢復是提到主伺服器出現故障(宕機)或者關機時,從伺服器可以轉換成主伺服器來用,從伺服器怎麼結束之前的主從關係,轉換為主伺服器呢?

slaveof no one

  如上圖所示,我們先把chb主伺服器上的redis服務關閉,然後在chb1上執行slaveof no one
命令,可以看到,chb1已經變成了master,chb2和chb3還是從屬於之前的chb。如果我們現在想要chb2和chb3從屬於chb1,就需要重新進行配置。
但是,在實際生產環境中,不可能時時刻刻都人為得進行監控主伺服器是否正常工作,所以,主伺服器如果發生故障,最好讓伺服器自動完成主從轉換,並修改其他從伺服器的從屬。這就涉及到redis的哨兵(sentinel)了。

3.1 Sentinel的主要任務

  Redis 的 Sentinel 系統用於管理多個 Redis 伺服器(instance), 該系統執行以下三個任務:
  1)監控(Monitoring): Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。
  2)提醒(Notification): 當被監控的某個 Redis 伺服器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程式傳送通知。
  3)自動故障遷移(Automatic failover): 當一個主伺服器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器, 並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時, 叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。
  Redis Sentinel 是一個分散式系統, 我們可以在一個架構中執行多個 Sentinel 程序(progress), 這些程序使用流言協議(gossip protocols)來接收關於主伺服器是否下線的資訊, 並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從伺服器作為新的主伺服器。

3.2 配置sentinel

  在chb、chb1、chb2三臺伺服器/myredis目錄下新建一個名為sentinel.conf的檔案,並在檔案中輸入一下內容:

#哨兵埠 
port 26379
#2表示在sentinel叢集中最少需要有兩個節點檢測到redis主節點出故障就進行主從切換
sentinel monitor mymaster
192.168.56.100 6379 2

#如果3s內mymaster無響應,則認為mymaster宕機了
sentinel down-after-milliseconds mymaster 3000
#如果10秒後,mysater仍沒活過來,則啟動failover
sentinel failover
-timeout mymaster 10000

#後臺執行
daemonize yes
#指定工作目錄
dir
"/myredis"

protected-mode no
#制定日誌檔案
logfile
"/myredis/sentinel.log"
#redis主節點密碼,本篇中並未對主伺服器設定密碼,故省略 #sentinel auth
-pass mymaster 123456

  第一行配置指示 Sentinel 去監視一個名為 mymaster 的主伺服器, 這個主伺服器的 IP 地址為 192.168.56.100 , 埠號為 6379 , 而將這個主伺服器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。

  不過要注意, 無論你設定要多少個 Sentinel 同意才能判斷一個伺服器失效, 一個 Sentinel 都需要獲得系統中多數(majority) Sentinel 的支援, 才能發起一次自動故障遷移。換句話說, 在只有少數(minority) Sentinel 程序正常運作的情況下, Sentinel 是不能執行自動故障遷移的。
  上述配置中各個選項的功能如下:
down-after-milliseconds 選項指定了 Sentinel 認為伺服器已經斷線所需的毫秒數。
如果伺服器在給定的毫秒數之內, 沒有返回 Sentinel 傳送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個伺服器標記為主觀下線(subjectively down,簡稱 SDOWN,指的是單個 Sentinel 例項對伺服器做出的下線判斷 )。
  不過只有一個 Sentinel 將伺服器標記為主觀下線並不一定會引起伺服器的自動故障遷移: 只有在足夠數量的 Sentinel 都將一個伺服器標記為主觀下線之後, 伺服器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ,指的是多個 Sentinel 例項在對同一個伺服器做出 SDOWN 判斷, 並且通過 SENTINEL is-master-down-by-addr 命令互相交流之後, 得出的伺服器下線判斷), 這時自動故障遷移才會執行。將伺服器標記為客觀下線所需的 Sentinel 數量由對主伺服器的配置決定。
  parallel-syncs 選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。

3.3 啟動 Sentinel

  對於 redis-sentinel 程式, 你可以用以下命令來啟動 Sentinel 系統:

redis-sentinel /path/to/sentinel.conf

  對於 redis-server 程式, 你可以用以下命令來啟動一個執行在 Sentinel 模式下的 Redis 伺服器:

redis-server /path/to/sentinel.conf --sentinel

  兩種方法都可以啟動一個 Sentinel 例項。

  啟動sentinel後,還要一次啟動個伺服器的redis服務,然後我們再次檢視主從關係如下圖所示:



  同時,我們也可以在日誌檔案/myreids/sentinel.log中檢視到資訊:

2057:X 01 Dec 2018 10:43:57.026 * +slave slave 192.168.56.101:6379 192.168.56.101 6379 @ mymaster 192.168.56.100 6379
2057:X 01 Dec 2018 10:44:17.115 * +slave slave 192.168.56.102:6379 192.168.56.102 6379 @ mymaster 192.168.56.100 6379
2057:X 01 Dec 2018 10:44:37.166 * +slave slave 192.168.56.103:6379 192.168.56.103 6379 @ mymaster 192.168.56.100 6379

  哨兵日誌說明主從關係已建立。

  然後我們關閉chb(主伺服器)上的reids服務,然後在檢視主從關係:

  從上圖中可以看到,主從關係已經發生了改變,關閉主伺服器chb後,chb3變成了主伺服器,且chb1和chb2也紛紛開始從屬於chb3。那麼,如果此時chb又開機上線了,是否會再次變成主伺服器呢?

從上圖看出,chb就算繼續上線,chb3也還是主機,chb1、chb2和新上線的chb都會從屬於chb3。