高可用性的redis服務(wù) (sentinel)

1. 高可用性

redis sentinel 官方文檔
redis sentinel 中文文檔

前面說到使用主從備份的方式可以保證數(shù)據(jù)的安全性,當主節(jié)點掛了的時候,從節(jié)點可以頂上作為主節(jié)點。但是需要手動去切換,這個過程需要認為干預(yù)。那么有沒有一種由程序自己監(jiān)控主節(jié)點狀態(tài)并在主節(jié)點掛了的時候自己選擇一個從節(jié)點的方案呢?答案肯定是有的。redis sentinel(哨兵)。

從宏觀上講,redis sentinel 可以做到的如下幾點:

  1. Monitoring 監(jiān)控,可以監(jiān)控master和slaves實例是不是按照預(yù)期的執(zhí)行
  2. Notification 通知,當被監(jiān)控的redis的實例出現(xiàn)問題。能夠通知系統(tǒng)管理員或者其他應(yīng)用程序
  3. Automatic failover 自動災(zāi)難遷移,當master出現(xiàn)故障的時候,sentinel會開啟一個選舉流程,選擇一個合適slave升級為master
  4. Configuration provider 幫客戶端發(fā)現(xiàn)redis服務(wù)。客戶端連接sentinel,sentinel拿到當前redis master address 給客戶端提供服務(wù)。當redis master 掛了的時候,找到一個新的service address。

sentinel具有分布式的特性,他被設(shè)計成多個Sentinel 進行一起協(xié)同工作。這樣左右兩個有點:

  1. 故障檢測的時候,多個進程認為出現(xiàn)故障的時候才認為出現(xiàn)故障。避免wupan
  2. 多個sentinel進程一起工作,當有部分sentinel死掉的時候,系統(tǒng)仍然能夠繼續(xù)工作。sentinel不一定要求所有的sentinel一起工作

2. 啟動和配置

在主從配置的時候把slave配置bind ,因為他有可能成為master。

sentinel服務(wù)是和redis服務(wù)一起發(fā)布。啟動腳本位置和redis的啟動位置一樣 redis-sentinel 腳本就是的。啟動方式如下:

## pwd=redis-3.2.8
## 方式一
src/redis-sentinel sentinel.conf

## 方式二
src/redis-server sentinel.conf --sentinel

兩種啟動方式是一摸一樣的。redis服務(wù)和sentinel一起使用的使用的時候,redis啟動和sentinel啟動都需要指明配置文件。因為在sentinel進行故障遷移切換master的時候會修改原來的master和slave的redis和sentinel的配置。

sentinel的配置,redis提供個默認的配置sentinel.conf。 配置項如下:

protected-mode no # 設(shè)置成no,沒有訪問限制
port 5000
sentinel monitor mymaster 192.168.206.200 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

官方說法是,使用sentinel的時候,最好3個以上的sentinel實例(instance)較好,因為他的選舉策略要投票過半。

上面的配置,每個實例使用相同的配置即可,如果sentinel有在同一個機器上,需要修改下端口保持不同,避免端口占用的問題

現(xiàn)在來看這個配置各項說明

  1. sentinel monitor mymaster 192.168.206.200 6379 2 他的配置 規(guī)則是
sentinel monitor <master-group-name> <ip> <port> <quorum>

master-group-name: master的名稱,唯一標志,ip, port redis服務(wù) master的ip和端口
quorum: 要確定master掛了,知道要多少個sentinel實例投票

  1. 選項配置
sentinel <option_name> <master_name> <option_value>

down-after-milliseconds:在master沒有回應(yīng)后多久(多少毫秒)認為master掛掉
failover-timeout:故障遷移進程多久超時,設(shè)置時間內(nèi)沒有完成認為超時
parallel-syncs:故障遷移的時候,最多同時幾臺和master數(shù)據(jù)同步。數(shù)字越小,故障遷移越耗時,但是如果slave配置了master遷移繼續(xù)使用old data提供服務(wù)的話。建議配置此項為1。

3. 部署架構(gòu)

在redis得官方文檔中,建議不用使用只有兩個sentinel的實例的方式部署,可用不高,建議知道要3個實例。示例的部署方案如下:

示例中 M1..Mn代表master,R1...R2代表slave , S1....Sn代表sentinel實例,C1.....Cn clients

  1. redis實力和sentinel在同一臺機器,1master ,2slave模式
             +----+
             | M1 |
             | S1 |
             +----+
                 |
    +----+    |       +----+
    | R2 |----+----   | R3 |
    | S2 |            | S3 |
    +----+            +----+

Configuration: quorum = 2
  1. 1 master,1 slave, sentinel放在客戶端這邊
            +----+         +----+
            | M1 |----+----| R1 |
            |    |    |    |    |
            +----+    |    +----+
                      |
         +------------+------------+
         |            |            |
         |            |            |
      +----+        +----+      +----+
      | C1 |        | C2 |      | C3 |
      | S1 |        | S2 |      | S3 |
      +----+        +----+      +----+

      Configuration: quorum = 2
  1. 1 master ,1 slave
           +----+         +----+
            | M1 |----+----| R1 |
            | S1 |    |    | S2 |
            +----+    |    +----+
                      |
               +------+-----+
               |            |  
               |            |
            +----+        +----+
            | C1 |        | C2 |
            | S3 |        | S4 |
            +----+        +----+

      Configuration: quorum = 3

4. 高級概念

大部分概念在文章開頭提到的中英文文檔中都有介紹。這里簡單說下幾個最基本的

4.1. 主觀下線和客觀下線

  1. 主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務(wù)器做出的下線判斷。
  2. 客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務(wù)器做出 SDOWN 判斷, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服務(wù)器下線判斷。 (一個 Sentinel 可以通過向另一個 Sentinel 發(fā)送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認為給定的服務(wù)器已下線。)
    如果一個服務(wù)器沒有在 master-down-after-milliseconds 選項所指定的時間內(nèi), 對向它發(fā)送 PING 命令的 Sentinel 返回一個有效回復(fù)(valid reply), 那么 Sentinel 就會將這個服務(wù)器標記為主觀下線。

客觀下線條件只適用于主服務(wù)器

4.2. 每個 Sentinel 都需要定期執(zhí)行的任務(wù)

  1. 每個 Sentinel 以每秒鐘一次的頻率向它所知的主服務(wù)器、從服務(wù)器以及其他 Sentinel 實例發(fā)送一個 PING 命令。
  2. 如果一個實例(instance)距離最后一次有效回復(fù) PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 那么這個實例會被 Sentinel 標記為主觀下線。 一個有效回復(fù)可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。
  3. 如果一個主服務(wù)器被標記為主觀下線, 那么正在監(jiān)視這個主服務(wù)器的所有 Sentinel 要以每秒一次的頻率確認主服務(wù)器的確進入了主觀下線狀態(tài)。
  4. 如果一個主服務(wù)器被標記為主觀下線, 并且有足夠數(shù)量的 Sentinel (至少要達到配置文件指定的數(shù)量)在指定的時間范圍內(nèi)同意這一判斷, 那么這個主服務(wù)器被標記為客觀下線。
  5. 在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有主服務(wù)器和從服務(wù)器發(fā)送 INFO 命令。 當一個主服務(wù)器被 Sentinel 標記為客觀下線時, Sentinel 向下線主服務(wù)器的所有從服務(wù)器發(fā)送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
  6. 當沒有足夠數(shù)量的 Sentinel 同意主服務(wù)器已經(jīng)下線, 主服務(wù)器的客觀下線狀態(tài)就會被移除。 當主服務(wù)器重新向 Sentinel 的 PING 命令返回有效回復(fù)時, 主服務(wù)器的主管下線狀態(tài)就會被移除。

4.3 自動發(fā)現(xiàn)sentinel和slave

sentinel可以自動的發(fā)現(xiàn)其他的sentinel服務(wù)和slave節(jié)點。具體概念,官網(wǎng)有非常詳細的解釋

5. 代碼實現(xiàn) Jedis示例

部署架構(gòu)如上面提到的第一種方式,當前環(huán)境:

192.168.206.200 redis slave1,sentinel1
192.168.206.201 redis master,sentinel2
192.168.206.202 redis slave2,sentinel3

redis.conf 大部分使用默認配置,列出幾個重要的配置

bind 192.168.206.200 # 跟據(jù)master,slave對應(yīng)修改
protected-mode yes
slave-serve-stale-data yes
slave-read-only yes
slave-priority 100
min-slaves-to-write 1
min-slaves-max-lag 10

appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

#slaveof 192.168.206.201 6379 在slave節(jié)點中才配置。master中不配置這個

sentinel.conf 三個實例一樣的配置

protected-mode no 
port 26379
sentinel monitor mymaster 192.168.206.201 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

redis客戶端配置情況

package com.fun.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by fun
 *
 * @date 2017/5/18.
 */
public class SentinelDemo {

    public static void main(String[] args) throws Exception {

        Set<String> sentinels = new HashSet<String>();
        sentinels.add("192.168.206.200:26379");
        sentinels.add("192.168.206.201:26379");
        sentinels.add("192.168.206.202:26379");
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);

        while(true) {
            System.out.println("press enter to continue");
            System.in.read();

            Jedis jedis = pool.getResource();
            System.out.println(pool.getCurrentHostMaster());
            String name = jedis.get("name");
            System.out.println("redis get key name="+name);
            jedis.close();
        }

    }
}

// output
/*
按下第一次enter的時候
press enter to continue
192.168.206.201:6379
redis get key name=fun

kill -9 殺掉master 后臺選舉,產(chǎn)生新的master 再次按下enter的時候
192.168.206.202:6379
redis get key name=fun
press enter to continue

*/

查看sentinel 的日志情況 ,可以看到切換master的過程。

4440:X 17 May 13:51:18.774 # +vote-for-leader 86a01849eb3e61289300a93a12855b6483088730 11
4440:X 17 May 13:51:19.793 # +odown master mymaster 192.168.206.201 6379 #quorum 3/2
4440:X 17 May 13:51:19.793 # Next failover delay: I will not start a failover before Wed May 17 13:57:19 2017
4440:X 17 May 13:51:19.859 # +config-update-from sentinel 86a01849eb3e61289300a93a12855b6483088730 192.168.206.200 26379 @ mymaster 192.168.206.201 6379
4440:X 17 May 13:51:19.859 # +switch-master mymaster 192.168.206.201 6379 192.168.206.202 6379
4440:X 17 May 13:51:19.859 * +slave slave 192.168.206.200:6379 192.168.206.200 6379 @ mymaster 192.168.206.202 6379
4440:X 17 May 13:51:19.860 * +slave slave 192.168.206.201:6379 192.168.206.201 6379 @ mymaster 192.168.206.202 6379

6. 問題延伸

在實際生產(chǎn)中,如果業(yè)務(wù)量比較大的情況,一臺redis實例作為緩存很有可能回出現(xiàn)不夠使用的情況,這個時候就需要做集群方式,但是redis的官方的說法是集群模式目前還處在驗證階段,沒有statble的版本出現(xiàn)。

大多時候我們都是使用sharding的方式的時候。Jedis中有ShardedJedisPool 來管理鏈接。但是如果我們對分片方式也做主從的話。加入sentinel之后。就要使用JedisSentinelPool方式管理。不難發(fā)現(xiàn),這兩種只能有一種存在。那Jedis如果做到分片情況下也能使用sentinel呢 ?

針對項目的問題,github上面有人開發(fā)了一個 ShardedJedisSentinelPool 可以用來處理這個問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Redis Sentinel 是一個分布式系統(tǒng), 你可以在一個架構(gòu)中運行多個 Sentinel 進程(progre...
    你是妖怪吧閱讀 939評論 0 0
  • 參考:redis官方文檔,Redis 復(fù)制、Sentinel的搭建和原理說明 Redis Sentinel(哨兵)...
    zzzTango閱讀 1,708評論 0 6
  • Redis 2.8版開始正式提供名為Sentinel的主從切換方案,Sentinel用于管理多個Redis服務(wù)器實...
    183207efd207閱讀 624評論 0 1
  • 文/鹿小喵 高考成績出來了,你考了一個不錯的成績,雖然與一本線有差距,但足以報一個好的二本學(xué)校。心滿意足。報志愿的...
    鹿小喵閱讀 344評論 0 3
  • 41周歲生日。 被前夫打擾,很不爽。歷來不懂如何拒絕他的說教,道理,所謂的正確。離了快一年,還在允許他這么做,我真...
    Judy970606閱讀 361評論 0 0

友情鏈接更多精彩內(nèi)容