Redis Sentinel實現集羣節點故障轉移

1. 簡介

Redis Sentinel爲Redis提供了很高的可用性,在實踐中,這意味着你可以部署一個可以解決非人爲干預導致節點故障的Redis集羣系統。Redis Sentinel還提供了其他的功能:如監控,通知和客戶端配置服務的提供方。下面列出來了Redis Sentinel的功能列表:

  • 監控:Sentinel能夠監控master節點或slave節點是否處於按照預期工作的狀態。
  • 通知:Sentinel能夠通過api通知系統管理原,其他的計算機程序,Redis實例運行過程中發生了錯誤。
  • 自動故障轉移:如果Redis的master節點出現問題,Sentinel能夠啓動一個故障轉移處理,該處理會將一個slave節點提升爲master節點,其他的slave節點則會自動配置成新的master節點的slave節點,如果原來的master重新正常啓動後,也會成爲該新Master的slave節點。
  • 客戶端配置提供者:Sentinel可作爲客戶端服務發現的一個權威來源,客戶端通過連接到Sentinel來請求當前的Redis Master節點,如果Master節點發生故障,Sentinel將會提供新的master地址。
Redis Sentinel 是一個分佈式系統, 你可以在架構中運行多個 Sentinel 進程,這些進程通過相互通訊來判斷一個主服務器是否斷線,以及是否應該執行故障轉移。在配置Redis Sentinel時,至少需要有1個Master和1個Slave。當Master失效後,Redis Sentinel會報出失效警告,並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從服務器作爲新的主服務器,並提供讀寫服務;當失效的Master恢復後,Redis Sentinel會自動識別,將Master自動轉換爲Slave並完成數據同步。通過Redis Sentinel可以實現Redis零手工干預並且短時間內進行M-S切換,減少業務影響時間。

雖然 Redis Sentinel 釋出爲一個單獨的可執行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis 服務器, 你可以在啓動一個普通 Redis 服務器時通過給定 --sentinel 選項來啓動 Redis Sentinel。

2. 部署

2.1  部署Redis集羣

先在3個機器上部署1個master, 2個slave, 具體部署過程參考上一邊文章:Redis

本次部署的節點如下:

 10.7.112.52 部署Master節點
 10.7.12.52   部署Slave節點
 10.5.35.3     部署Slave節點

2.2  部署Redis Sentinel

1. 將master拷貝一份,重新命名爲master-sentinel(可任意命名)。
2. 在master-sentinel的redis.conf同目錄下增加一個文件:sentinel.conf,在文件中添加一下內容:

<span style="font-size:14px;">sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1</span>

第一行配置指示 Sentinel 去監視一個名爲 mymaster 的主服務器, 這個主服務器的 IP 地址爲 127.0.0.1 , 端口號爲 6379 , 而將這個主服務器判斷爲失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。不過要注意, 無論你設置要多少個 Sentinel 同意才能判斷一個服務器失效, 一個 Sentinel 都需要獲得系統中多數(majority) Sentinel 的支持, 才能發起一次自動故障遷移, 並預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主服務器配置的版本號)。換句話說, 在只有少數(minority) Sentinel 進程正常運作的情況下, Sentinel 是不能執行自動故障遷移的。

其他選項的基本格式如下:

sentinel <選項的名字> <主服務器的名字> <選項的值>

各個選項的功能如下:
  • down-after-milliseconds:指定了 Sentinel 認爲服務器已經斷線所需的毫秒數。如果服務器在給定的毫秒數之內, 沒有返回 Sentinel 發送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個服務器標記爲主觀下線(subjectively down,簡稱 SDOWN )。不過只有一個 Sentinel 將服務器標記爲主觀下線並不一定會引起服務器的自動故障遷移: 只有在足夠數量的 Sentinel 都將一個服務器標記爲主觀下線之後, 服務器纔會被標記爲客觀下線(objectively down, 簡稱 ODOWN ), 這時自動故障遷移纔會執行。將服務器標記爲客觀下線所需的 Sentinel 數量由對主服務器的配置決定。
  • parallel-syncs :指定了在執行故障轉移時, 最多可以有多少個從服務器同時對新的主服務器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。如果從服務器被設置爲允許使用過期數據集(參見對 redis.conf 文件中對 slave-serve-stale-data 選項的說明), 那麼你可能不希望所有從服務器都在同一時間向新的主服務器發送同步請求, 因爲儘管複製過程的絕大部分步驟都不會阻塞從服務器, 但從服務器在載入主服務器發來的 RDB 文件時, 仍然會造成從服務器在一段時間內不能處理命令請求: 如果全部從服務器一起對新的主服務器進行同步, 那麼就可能會造成所有從服務器在短時間內全部不可用的情況出現。你可以通過將這個值設爲 1 來保證每次只有一個從服務器處於不能處理命令請求的狀態。
3.  添加bat文件

redis-server.exe sentinel.conf --sentinel

最後的文件結構:


4. 將maser-sentinel文件夾拷貝到10.7.12.52和10.5.35.3機器上各一份

5. 分別啓動各自的start-sentinel.bat命令來啓動redis-sentinel節點

10.7.112.52上的啓動信息:


10.7.12.52上的啓動信息


10.5.35.3上的啓動信息


啓動完之後發現sentinel.conf文件內容也自動發生了改變:

<span style="font-size:14px;">sentinel monitor mymaster 10.7.112.52 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
# Generated by CONFIG REWRITE
port 26379
dir "D:\\redis\\redis-cluster\\master-sentinel\\redis-64.2.8.17"
sentinel known-slave mymaster 10.5.35.3 6380
sentinel known-slave mymaster 10.7.12.52 6379
sentinel known-sentinel mymaster 10.7.12.52 26379 5356501f2b6b773704718527020dd88da1c43725
sentinel known-sentinel mymaster 10.5.35.3 26379 80bfae8b3c96aca804268b7f660ce1acdc80bc7d
sentinel current-epoch 0</span>

此已經將redis sentinel的3個節點啓動完成了,用redis-cli連接到master節點查看下集羣信息:


我們用客戶端程序來測試下redis的使用。

	<span style="font-size:14px;">public static void main(String[] args){
		Set sentinels = new HashSet();
        sentinels.add(new HostAndPort("10.7.112.52", 26379).toString());
        sentinels.add(new HostAndPort("10.7.12.52", 26379).toString());
        sentinels.add(new HostAndPort("10.5.35.3", 26379).toString());
        JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
        System.out.println("Current master: " + sentinelPool.getCurrentHostMaster().toString());
        Jedis master = sentinelPool.getResource();
        master.set("name","張三");
        sentinelPool.returnResource(master);
        Jedis master2 = sentinelPool.getResource();
        String value = master2.get("name");
        System.out.println("name: " + value);
        master2.close();
        sentinelPool.destroy();
	}</span>
運行結果:

<span style="font-size:14px;">六月 08, 2015 3:35:24 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
六月 08, 2015 3:35:24 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 10.7.112.52:6379, starting Sentinel listeners...
六月 08, 2015 3:35:24 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 10.7.112.52:6379
Current master: 10.7.112.52:6379
name: 張三</span>

2.3  模擬master節點故障轉移

現在來模擬master節點發生故障,看看redis sentinel對節點的故障轉移,關閉10.7.112.52上的master節點,然後會發現10.7.112.52,10.7.12.52,10.5.35.3的sentinel節點上打印以下信息,實際上就是進行新Master節點的選舉:


這裏我們可以看到10.5.35.3上的slave節點被選舉成爲新的Master節點,然後10.7.12.52上的slave節點開始從這個新的master節點上同步數據:


這時查看10.7.112.52上的sentinel.conf文件,發現已經發生改變了:

<span style="font-size:14px;">sentinel monitor mymaster 10.5.35.3 6380 2
sentinel down-after-milliseconds mymaster 60000
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
# Generated by CONFIG REWRITE
port 26379
dir "D:\\redis\\redis-cluster\\master-sentinel\\redis-64.2.8.17"
sentinel known-slave mymaster 10.7.12.52 6379
sentinel known-slave mymaster 10.7.112.52 6379
sentinel known-sentinel mymaster 10.5.35.3 26379 80bfae8b3c96aca804268b7f660ce1acdc80bc7d
sentinel known-sentinel mymaster 10.7.112.52 26379 1167bab5c8882cbc3b01a974c30ad6997e4e1d9d

sentinel current-epoch 1</span>
而10.7.12.52上的redis.conf的文件也發生了改變,原來配置的是屬於10.7.112.52的slave節點,現在調整成10.5.35.3的slave節點:

原來配置爲:slaveof 10.7.112.52 6379

現在配置爲:slaveof 10.5.35.3 6380

可見,當重新選舉master節點時,各個slave節點的配置文件redis.conf和各個sentinel節點的配置文件sentinel.conf都會自動發生調整。

現在我們用redis-cli客戶端連接到10.5.35.3上的master節點查看集羣節點信息:

現在再把10.7.112.52上的redis節點啓動起來,會發現該節點會自動加入redis集羣,並且成爲新maste(10.5.35.3)的slave節點:

現在我們再用redis-cli客戶端連接到10.5.35.3上的master節點查看集羣節點信息:


再次執行測試程序,結果如下:

<span style="font-size:14px;">六月 08, 2015 3:59:53 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
六月 08, 2015 3:59:53 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 10.5.35.3:6380, starting Sentinel listeners...
六月 08, 2015 3:59:53 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 10.5.35.3:6380
Current master: 10.5.35.3:6380
name: 張三
</span>


從結果可發現,對客戶端而言,master節點已經切換到10.5.35.3上去了,而且客戶端程序也不用更新代碼。


發佈了73 篇原創文章 · 獲贊 18 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章