四、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。
四、redis系列之主從復制與哨兵機制