Redis-哨兵(Sentinel)

前言

Redis 哨兵(Sentinel)的官方文档: Redis Sentinel Documentation

简而言之,哨兵机制是Redis高可用性的保障。

本文主要对该官方文档进行了翻译,同时也结合源码做了部分注解。

概述

Redis Sentinel为Redis提供高可用性。通过Sentinel可以部署一套无需人工干预,即可抵抗某些故障的高可用Redis。

Redis Sentinel还提供了一些附加任务,如监视,通知,给客户端(client)提供配置信息等。

Sentinel的完整功能列表(big picture):

  • 监控。Sentinel会不断检查Redis的Master实例和Slave实例是否按预期工作。
  • 通知。Sentinel可以通过API通知系统管理员或其他计算机程序,其中一个受监视的Redis实例出了问题。
  • 自动故障转移。如果Master未按预期工作,则Sentinel可以启动故障转移过程,在该过程中将某个Slave升级为Master,将其他Slave的主从复制(Replication)目标修改为新的Master,并通知使用Redis应用程序要使用的新地址。
  • 配置提供者。Sentinel为客户端client提供服务发现功能:client连接到Sentinels,询问当前Redis Master实例的地址。如果发生故障转移,Sentinels将报告新地址。

Sentinel的分布式性质

Redis Sentinel是一个分布式系统:

Sentinel本身设计为在有多个Sentinel进程协同合作的配置中运行。具有多个Sentinel进程进行协作的优点如下:

  1. 降低误报的几率:当多个Sentinel就给定的主机不再可用达成共识时,才执行故障转移。
  2. 避免单点故障:故障转移系统本身也可能出现单点故障,多个Sentinel进程协同运行,保证了即使不是所有的Sentinel进程都在工作,Sentinel仍能正常工作,从而使系统能够应对故障。

Sentinels,Redis实例(Master和Slave)以及连接到Sentinel和Redis的客户端的总和也是具有特定属性的大型分布式系统。在本文档中,将逐步介绍各个概念,先介绍基本信息,以便理解Sentinel的基本特性,再介绍Sentinel的工作原理(可选读)。

Quici Start

获取Sentinel

Sentinel的当前版本为Sentinel 2。它对Sentinel初版实现进行了重构,使用了更强大且更易于预测的算法(会在本文档中进行说明)。

自Redis 2.8之后的版本中,都已包含稳定版本的Redis Sentinel。

Redis Sentinel的不稳定分支中进行着迭代开发,一旦新功能稳定,便会立即合并回最新的稳定分支。

Redis 2.6随附的Redis Sentinel版本1已被弃用,不应使用。

运行Sentinel

有两种方法启动Sentinel:

  1. 使用 redis-sentinel(实际上是一个名为redis-sentinel,指向redis-server的软连接):
1
redis-sentinel /path/to/sentinel.conf
  1. 直接使用redis-server以Sentinel模式启动:
1
redis-server /path/to/sentinel.conf --sentinel

两种方法是等效的。

但是在运行Sentinel时必须使用配置文件,因为系统将使用此文件来保存当前状态,以便在重启时重新加载。如果未提供配置文件或配置文件路径不可写,Sentinel会拒绝启动。

Sentinels默认情况下会监听TCP端口26379的连接,因此,要使Sentinels正常工作,必须打开服务器的端口26379,以接收来自其他Sentinel实例的连接。否则,Sentinels无法讨论也不能就该做什么达成共识,因此将永远不会执行故障转移。


译者注

从源码 server.c 里可以看到,判断是否以哨兵模式启动的条件:

1
2
3
4
5
6
7
8
9
10
/* Returns 1 if there is --sentinel among the arguments or if
* argv[0] contains "redis-sentinel". */
int checkForSentinelMode(int argc, char **argv) {
int j;

if (strstr(argv[0],"redis-sentinel") != NULL) return 1;
for (j = 1; j < argc; j++)
if (!strcmp(argv[j],"--sentinel")) return 1;
return 0;
}

如果执行的文件名包含”redis-sentinel”,或者执行参数中有”–sentinel”,就以哨兵模式启动。


部署前有关Sentinel的基本知识

  1. 一个健壮的部署至少需要三个Sentinel实例。
  2. 应将三个Sentinel实例放置到独立计算机或虚拟机中(不会同时发生故障),例如在不同的可用区域上执行的不同物理服务器或虚拟机。
  3. 由于Redis使用异步复制,因此Sentinel + Redis分布式系统不能保证在故障期间保留已确认的写入。但是,部署Sentinel时可以采取一些方法,使得数据写入丢失窗口仅限于某些时刻。还有其他一些不太安全的方法来部署它。
  4. 客户端需要Sentinel支持。并非所有的流行客户端库都具有Sentinel支持。
  5. 如果您不在开发环境中不时进行测试,则没有安全的HA设置,如果可以,则在生产环境中甚至可以更好地进行测试。您可能有一个错误的配置,只有在为时已晚时(主服务器停止工作的凌晨3点),该错误才会变得明显。
  6. Sentinel,Docker或其他形式的网络地址转换或端口映射应格外小心:Docker执行端口重新映射,会破坏Sentinel对其他Sentinel进程的自动发现以及主副本的列表。有关更多信息,请参阅本文档后面有关Sentinel和Docker的部分。

配置前哨

Redis源码目录内包含一个名为sentinel.conf的文件 ,该文件是一个示例配置文件,可用于配置Sentinel。如下所示的是典型的最小配置文件:

1
2
3
4
5
6
7
8
9
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

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

上面的示例中监视了两组Redis实例,每个实例由一个master和未定义数量的slave组成。一组实例名为mymaster,另一组名为resque

配置中只需要指定要监视的master,无需指定slave,slave是自动发现的。Sentinel会将slave的其他信息自动更新进配置文件中(以便在重新启动时保留该信息)。当在故障转移期间将slave提升为master时,以及每次发现新的Sentinel时,都会重写配置。

配置需要监控的Master

sentinel monitor语句参数的含义如下:

1
sentinel monitor <master-group-name> <ip> <port> <quorum>

各配置选项的含义:

第一行用于告诉Redis监视一个名为 mymaster 的master,其地址为127.0.0.1,端口为6379,仲裁数为2。其中 quorum 表示仲裁数,其意义为:

  • 当判定master不可用的Sentinel进程数量 ≥ quorum时,才能真正标记master不可用,并最终开始故障转移过程。
  • 但是,quorum仅用于检测故障。为了实际执行故障转移,需要将其中一名Sentinels选为故障转移的负责人,并授权其进行操作。必须有超过半数的Sentinel进程投票,才会进行故障转移。

例如,有5个Sentinel进程,并且给定主服务器的仲裁设置为2,则将发生以下情况:

  • 如果有两个Sentinel同时认为master不可访问,则这两个Sentinel中的一个将尝试启动故障转移。
  • 如果总共至少有三个Sentinel可以访问,则故障转移将被授权并实际上开始。

这意味着在发生故障期间,如果超过半数的Sentinel进程无法进行对话,Sentinel不会启动故障转移(即:不过半数无故障转移)。

其他配置项

其他配置项几乎总是采用以下形式:

1
sentinel <option_name> <master_name> <option_value>

配置项:

  • down-after-milliseconds 不可用时间,以毫秒为单位。是指Sentinel无法访问某实例(实例未答复PING或答复错误),持续所指定的时间后,认为实例不可用。
  • parallel-syncs配置了在故障转移时,同时和新master的同步数据的slave数量。数字越小,完成故障转移过程所花费的时间越多;但越大就意味着越多的slave因为复制而不可用(尽管slave在复制过程中绝大部分时间是非阻塞的,但仍会在载入大量数据时对外停止服务一小段时间)。将此选项设置为值1,可以确保一次只有一个副本无法访问。

其他选项在本文档的其余部分中进行了描述,并在sentinel.confRedis分发随附的示例文件中进行了说明。

使用SENTINEL SET命令,可以在运行时修改所有配置参数。有关更多信息,请参见“在运行时重新配置Sentinel”部分。