redis哨兵(sentinel)系统

原创 2016年06月02日 11:23:14

sentinel(哨兵)是redis的高可用性(high availability)解决方案:由一个或多个sentinel实例组成的Sentinel系统,监视任意多个主服务器及这些主服务器下的从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,代替已下线的主服务器继续处理命令请求。
下图是Sentinel系统监视服务器的例子:
这里写图片描述

1. 启动并初始化Sentinel

参考:http://redisbook.com/preview/sentinel/init_sentinel.html
启动一个Sentinel的命令:

redis> redis-sentinel /path/to/your/sentinel.conf

或者

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

这两个效果完全相同。当启动一个sentinel时,需要执行以下步骤:
1. 初始化服务器
2. 将普通redis服务器使用的代码替换成sentinel专用代码
3. 初始化sentinel状态
4. 根据配置文件,初始化sentinel的监视主服务器列表
5. 创建连向主服务器的网络连接

1.1 初始化服务器

Sentinel 本质上是一个运行在特殊模式下的redis服务器,所以启动Sentinel的第一步(类似)初始化一个普通的redis服务器。

因为 Sentinel 执行的工作和普通 Redis 服务器执行的工作不同, 所以 Sentinel 的初始化过程和普通 Redis 服务器的初始化过程并不完全相同。
普通服务器在初始化时会通过载入 RDB 文件或者 AOF 文件来还原数据库状态, 但是因为 Sentinel 并不使用数据库, 所以初始化 Sentinel 时就不会载入 RDB 文件或者 AOF 文件。

Sentinel 模式下 Redis 服务器主要功能的使用情况

功能 使用情况
数据库和键值对方面的命令, 比如 SET 、 DEL 、 FLUSHDB 。 不使用。
事务命令, 比如 MULTI 和 WATCH 。 不使用。
脚本命令,比如 EVAL 。 不使用。
RDB 持久化命令, 比如 SAVE 和 BGSAVE 。 不使用。
AOF 持久化命令, 比如 BGREWRITEAOF 。 不使用。
复制命令,比如 SLAVEOF 。 Sentinel 内部可以使用,但客户端不可以使用。
发布与订阅命令, 比如 PUBLISH 和 SUBSCRIBE 。 SUBSCRIBE 、 PSUBSCRIBE 、 UNSUBSCRIBE PUNSUBSCRIBE 四个命令在 Sentinel 内部和客户端都可以使用, 但 PUBLISH 命令只能在 Sentinel 内部使用。
文件事件处理器(负责发送命令请求、处理命令回复)。 Sentinel 内部使用, 但关联的文件事件处理器和普通 Redis 服务器不同。
时间事件处理器(负责执行 serverCron 函数)。 Sentinel 内部使用, 时间事件的处理器仍然是 serverCron 函数, serverCron 函数会调用 sentinel.c/sentinelTimer 函数, 后者包含了 Sentinel 要执行的所有操作。

1.2 使用 Sentinel 专用代码

将一部分普通 Redis 服务器使用的代码替换成 Sentinel 专用代码

(1)端口
普通 Redis 服务器使用 redis.h/REDIS_SERVERPORT 常量的值作为服务器端口:

#define REDIS_SERVERPORT 6379

而 Sentinel 则使用 sentinel.c/REDIS_SENTINEL_PORT 常量的值作为服务器端口:

#define REDIS_SENTINEL_PORT 26379

(2)命令表
普通 Redis 服务器使用 redis.c/redisCommandTable 作为服务器的命令表:

struct redisCommand redisCommandTable[] = {
    {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
    {"set",setCommand,-3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    {"setnx",setnxCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    // ...
    {"script",scriptCommand,-2,"ras",0,NULL,0,0,0,0,0},
    {"time",timeCommand,1,"rR",0,NULL,0,0,0,0,0},
    {"bitop",bitopCommand,-4,"wm",0,NULL,2,-1,1,0,0},
    {"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0}
}

而 Sentinel 则使用 sentinel.c/sentinelcmds 作为服务器的命令表, 并且其中的 INFO 命令会使用 Sentinel 模式下的专用实现 sentinel.c/sentinelInfoCommand 函数, 而不是普通 Redis 服务器使用的实现 redis.c/infoCommand 函数:

struct redisCommand sentinelcmds[] = {
    {"ping",pingCommand,1,"",0,NULL,0,0,0,0,0},
    {"sentinel",sentinelCommand,-2,"",0,NULL,0,0,0,0,0},
    {"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"unsubscribe",unsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"psubscribe",psubscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}
};

1.3 初始化 Sentinel 状态

服务器会初始化一个 sentinel.c/sentinelState 结构(“Sentinel 状态”), 保存了服务器中所有和 Sentinel 功能有关的状态 (服务器的一般状态仍然由 redis.h/redisServer 结构保存):

struct sentinelState {

    // 当前纪元,用于实现故障转移
    uint64_t current_epoch;

    // 保存了所有被这个 sentinel 监视的主服务器的相关信息
    // 字典的键是主服务器的名字
    // 字典的值则是一个指向 sentinelRedisInstance 结构的指针
    dict *masters;

    // 是否进入了 TILT 模式?
    int tilt;

    // 目前正在执行的脚本的数量
    int running_scripts;

    // 进入 TILT 模式的时间
    mstime_t tilt_start_time;

    // 最后一次执行时间处理器的时间
    mstime_t previous_time;

    // 一个 FIFO 队列,包含了所有需要执行的用户脚本
    list *scripts_queue;

} sentinel;

1.4 初始化 Sentinel 状态的 masters 属性

Sentinel 状态中的 masters 字典记录了所有被 Sentinel 监视的主服务器的相关信息,是根据被载入的 Sentinel 配置文件对其进行初始化。
1. 字典的键是被监视主服务器的名字。
2. 字典的值则是被监视主服务器对应的 sentinel.c/sentinelRedisInstance 结构。

typedef struct sentinelRedisInstance {

    // 标识值,记录了实例的类型,以及该实例的当前状态
    int flags;

    // 实例的名字
    // 主服务器的名字由用户在配置文件中设置
    // 从服务器以及 Sentinel 的名字由 Sentinel 自动设置
    // 格式为 ip:port ,例如 "127.0.0.1:26379"
    char *name;

    // 实例的运行 ID
    char *runid;

    // 配置纪元,用于实现故障转移
    uint64_t config_epoch;

    // 实例的地址:ip地址和port
    sentinelAddr *addr;

    // SENTINEL down-after-milliseconds 选项设定的值
    // 实例无响应多少毫秒之后才会被判断为主观下线(subjectively down)
    mstime_t down_after_period;

    // SENTINEL monitor <master-name> <IP> <port> <quorum> 选项中的 quorum 参数
    // 判断这个实例为客观下线(objectively down)所需的支持投票数量
    int quorum;

    // SENTINEL parallel-syncs <master-name> <number> 选项的值
    // 在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
    int parallel_syncs;

    // SENTINEL failover-timeout <master-name> <ms> 选项的值
    // 刷新故障迁移状态的最大时限
    mstime_t failover_timeout;

    // ...

} sentinelRedisInstance;

这里写图片描述

1.5 创建连向主服务器的网络连接

对于每个被 Sentinel 监视的主服务器来说, Sentinel 会创建两个连向主服务器的异步网络连接:

  • 一个命令连接, Sentinel 将成为主服务器的客户端, 这个连接专门用于向主服务器发送命令, 并接收命令回复。
  • 一个订阅连接, 这个连接专门用于订阅主服务器的 __sentinel__:hello 频道。

这里写图片描述

2. 获取主服务器信息

Sentinel默认会每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令

这里写图片描述

通过分析INFO命令的回复来获取主服务器的当前信息:
1. 主服务器本身的信息
2. 主服务器属下所有从服务器的信息

这里写图片描述

3. 获取从服务器信息

当sentinel发现主服务器有新的从服务器时,sentinel①为这个从服务器创建相应的实例结构;②创建连接到从服务器的命令连接和订阅连接。

4. 向主服务器和从服务器发送消息

sentinel会每2秒一次的频率,通过命令连接向所有被监视的(主从)服务器的_sentinel_:hello频道发送消息:
PUBLISH _sentinel_:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_epoch>"
1. 以s_开头的参数记录sentinel本身的信息
2. 以m_开头的参数记录主服务器的信息

5. 接收来自主服务器和从服务器的频道信息

当sentinel与一个主服务器或从服务器建立订阅连接后,通过订阅连接发送订阅命令SUBSCRIBE _sentinel_:hello

对于监视同一个服务器的多个sentinel来说,一个sentinel发送的信息会被其他sentinel接收,这些信息用于①更新其他sentinel对发送信息的sentinel的认知②更新其他sentinel对被监视服务器的认知。

这里写图片描述

(1)更新sentinel字典
sentinel为主服务器创建的实例结构的sentinel字典保存了除sentinel本身之外,所有同样监视这个主服务器的其他sentinel的资料。

(2)创建连向其他sentinel的命令连接
这里写图片描述

6. 检测主观下线状态

sentinel会以每秒一次的频率向所有与它从创建了命令连接的实例(包括主服务器、从服务器、其他sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。

7. 检测客观下线状态

当sentinel在判定一个主服务器为主观下线后,为了确认这个主服务器是否真的下线,询问同样监视这个主服务器的其他sentinel,当收到足够数量的已下线判断后,sentinel就会将服务器判定为客观下线,并对服务器执行故障转移操作。

8. 选举领头sentinel

当一个主服务器被判断为客观下线后,监视这个下线服务器的各个sentinel会进行协商,选举出一个领头sentinel,并由领头sentinel对下线服务器执行故障转移操作

9. 故障转移

领头sentinel对下线服务器执行故障转移操作,三个步骤:
1. 在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器。
2. 让已下线服务器属下的所有从服务器改为复制新的主服务器
3. 将已下线服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,它就会成为新的主服务器的从服务器。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Redis源码剖析和注释(二十三)--- Redis Sentinel实现(哨兵的执行过程和执行的内容)

Redis Sentinel实现(上)1. Redis Sentinel 介绍和部署请参考Redis Sentinel 介绍与部署sentinel.c文件详细注释:Redis Sentinel详细注释...
  • men_wen
  • men_wen
  • 2017年05月29日 23:37
  • 1607

基于Sentinel(哨兵)搭建实现Redis高可用集群

概述 Redis哨兵为Redis提供了高可用性。实际上这意味着你可以使用哨兵模式创建一个可以不用人为干预而应对各种故障的Redis部署。 哨兵模式还提供了其他的附加功能,如监控,通知,为客户端提供...
  • shouhuzhezhishen
  • shouhuzhezhishen
  • 2017年04月05日 10:04
  • 1791

Redis的哨兵机制

1、哨兵机制的简介        有了主从复制的实现以后,如果想对主服务器进行监控,那么在redis2.6以后提供了一个"哨兵"的机制。顾名思义,哨兵的含义就是监控Redis系统的运行状态。可以启动...
  • zbw18297786698
  • zbw18297786698
  • 2016年10月22日 14:10
  • 3078

Redis学习笔记(四) Redis哨兵(sentinel)

Redis 的 哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务: • 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和S...
  • a67474506
  • a67474506
  • 2015年12月30日 16:39
  • 11083

Redis-sentinel哨兵模式集群方案配置

最近研究了redis的集群方案,第一个方案是创建 redis cluster,第二种方案就是用哨兵模式来进行主从替换以及故障恢复。...
  • donggang1992
  • donggang1992
  • 2016年03月25日 16:08
  • 16411

Redis 哨兵模式详解

1、Sentinel 哨兵 Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有...
  • woxingwosu0100
  • woxingwosu0100
  • 2017年11月07日 11:24
  • 243

3台服务器Redis高可用哨兵模式

3台服务器Redis高可用哨兵模式@(学习)[redis, 高可用]3台服务器Redis高可用哨兵模式 介绍 redis程序安装 哨兵模式配置 1 主redis配置 2 从redis配置 3 启动re...
  • ygqygq2
  • ygqygq2
  • 2017年05月07日 01:47
  • 993

redis sentinel

redis 哨兵哨兵为redis提供了高可用的性, 在实际应用中, 当redis server 发生故障了,通过使用redis 哨兵实现自动化系统监控和故障恢复,而无需人工的介入.哨兵的特性: - ...
  • jia281460530
  • jia281460530
  • 2016年07月21日 21:06
  • 1794

搭建redis-sentinel(哨兵机制)集群

简单介绍下Redis-sentinel: Redis-sentinel是Redis实例的监控管理、通知和实例失效备援服务,是Redis集群的管理工具。在一般的分布式中心节点数据库中,Redis-sen...
  • ownfire
  • ownfire
  • 2016年05月31日 18:12
  • 17928

Redis哨兵机制

Redis 哨兵的服务框架 哨兵也是 Redis 服务器,只是它与我们平时提到的 Redis 服务器职能不同,哨兵负责监视普通的 Redis 服务器,提高一个服务器集群的健壮和可靠性。哨兵和普通...
  • lee_nacl
  • lee_nacl
  • 2017年03月14日 15:39
  • 906
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:redis哨兵(sentinel)系统
举报原因:
原因补充:

(最多只允许输入30个字)