高可用性的redis服务 (sentinel)

1. 高可用性

redis sentinel 官方文档
redis sentinel 中文文档

前面说到使用主从备份的方式可以保证数据的安全性,当主节点挂了的时候,从节点可以顶上作为主节点。但是需要手动去切换,这个过程需要认为干预。那么有没有一种由程序自己监控主节点状态并在主节点挂了的时候自己选择一个从节点的方案呢?答案肯定是有的。redis sentinel(哨兵)。

从宏观上讲,redis sentinel 可以做到的如下几点:

  1. Monitoring 监控,可以监控master和slaves实例是不是按照预期的执行
  2. Notification 通知,当被监控的redis的实例出现问题。能够通知系统管理员或者其他应用程序
  3. Automatic failover 自动灾难迁移,当master出现故障的时候,sentinel会开启一个选举流程,选择一个合适slave升级为master
  4. Configuration provider 帮客户端发现redis服务。客户端连接sentinel,sentinel拿到当前redis master address 给客户端提供服务。当redis master 挂了的时候,找到一个新的service address。

sentinel具有分布式的特性,他被设计成多个Sentinel 进行一起协同工作。这样左右两个有点:

  1. 故障检测的时候,多个进程认为出现故障的时候才认为出现故障。避免wupan
  2. 多个sentinel进程一起工作,当有部分sentinel死掉的时候,系统仍然能够继续工作。sentinel不一定要求所有的sentinel一起工作

2. 启动和配置

在主从配置的时候把slave配置bind ,因为他有可能成为master。

sentinel服务是和redis服务一起发布。启动脚本位置和redis的启动位置一样 redis-sentinel 脚本就是的。启动方式如下:

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

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

两种启动方式是一摸一样的。redis服务和sentinel一起使用的使用的时候,redis启动和sentinel启动都需要指明配置文件。因为在sentinel进行故障迁移切换master的时候会修改原来的master和slave的redis和sentinel的配置

sentinel的配置,redis提供个默认的配置sentinel.conf。 配置项如下:

protected-mode no # 设置成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有在同一个机器上,需要修改下端口保持不同,避免端口占用的问题

现在来看这个配置各项说明

  1. sentinel monitor mymaster 192.168.206.200 6379 2 他的配置 规则是
sentinel monitor <master-group-name> <ip> <port> <quorum>

master-group-name: master的名称,唯一标志,ip, port redis服务 master的ip和端口
quorum: 要确定master挂了,知道要多少个sentinel实例投票

  1. 选项配置
sentinel <option_name> <master_name> <option_value>

down-after-milliseconds:在master没有回应后多久(多少毫秒)认为master挂掉
failover-timeout:故障迁移进程多久超时,设置时间内没有完成认为超时
parallel-syncs:故障迁移的时候,最多同时几台和master数据同步。数字越小,故障迁移越耗时,但是如果slave配置了master迁移继续使用old data提供服务的话。建议配置此项为1。

3. 部署架构

在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 实例对服务器做出的下线判断。
  2. 客观下线(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 就会将这个服务器标记为主观下线。

客观下线条件只适用于主服务器

4.2. 每个 Sentinel 都需要定期执行的任务

  1. 每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。
  3. 如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。
  4. 如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线。
  5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  6. 当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除。

4.3 自动发现sentinel和slave

sentinel可以自动的发现其他的sentinel服务和slave节点。具体概念,官网有非常详细的解释

5. 代码实现 Jedis示例

部署架构如上面提到的第一种方式,当前环境:

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 # 跟据master,slave对应修改
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节点中才配置。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 后台选举,产生新的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. 问题延伸

在实际生产中,如果业务量比较大的情况,一台redis实例作为缓存很有可能回出现不够使用的情况,这个时候就需要做集群方式,但是redis的官方的说法是集群模式目前还处在验证阶段,没有statble的版本出现。

大多时候我们都是使用sharding的方式的时候。Jedis中有ShardedJedisPool 来管理链接。但是如果我们对分片方式也做主从的话。加入sentinel之后。就要使用JedisSentinelPool方式管理。不难发现,这两种只能有一种存在。那Jedis如果做到分片情况下也能使用sentinel呢 ?

针对项目的问题,github上面有人开发了一个 ShardedJedisSentinelPool 可以用来处理这个问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progre...
    你是妖怪吧阅读 898评论 0 0
  • 参考:redis官方文档,Redis 复制、Sentinel的搭建和原理说明 Redis Sentinel(哨兵)...
    zzzTango阅读 1,634评论 0 6
  • Redis 2.8版开始正式提供名为Sentinel的主从切换方案,Sentinel用于管理多个Redis服务器实...
    183207efd207阅读 609评论 0 1
  • 文/鹿小喵 高考成绩出来了,你考了一个不错的成绩,虽然与一本线有差距,但足以报一个好的二本学校。心满意足。报志愿的...
    鹿小喵阅读 311评论 0 3
  • 41周岁生日。 被前夫打扰,很不爽。历来不懂如何拒绝他的说教,道理,所谓的正确。离了快一年,还在允许他这么做,我真...
    Judy970606阅读 337评论 0 0