【redis】哨兵模式

redis哨兵的高可用性

在不使用redis cluster时,哨兵能够保证redis的高可用。

redis哨兵也会提供其他的附带功能,如监控、通知、作为配置提供者。

哨兵功能概述:

  • 监控:哨兵会不断检查主从实例是否正常工作。
  • 通知:哨兵可以通知系统或其他程序有某个监控下的实例出错了。
  • 自动故障恢复:当redis主节点不正常工作,哨兵会启动故障恢复程序,将从节点升级为主节点,其他的从节点会重新配置来使用新的主节点,使用redis的程序在连接时也会被通知新的地址。
  • 配置提供:哨兵可以作为服务发现的中心,客户端连接到哨兵来请求当前提供服务的Redis主机地址。如果发生故障切换,哨兵会返回新地址。

哨兵作为分布式系统

Redis哨兵是一个分布式系统:

哨兵本身是设计成可以多个哨兵进程协同工作的配置。优点如下:

  1. 故障检测是由多个哨兵认为master不可用决定的,降低了误报的概率。
  2. 即使部分哨兵进程不可用,哨兵功能也正常工作,健壮性更好。毕竟一个故障恢复程序本身就可能发生单点故障的话也没什么意义。

哨兵快速启动

使用哨兵

当前的哨兵版本为哨兵2,使用了更强大且更容易预测的算法重写了原来的哨兵实现。

从redis2.8开始包实装了稳定的哨兵版本。

哨兵1版本实装在redis2.6,已经不推荐使用。

运行哨兵

如果您使用的是redis sentinel可执行文件,则可以使用以下命令行运行哨兵:

redis-sentinel /path/to/sentinel.conf

或者可以直接使用redis server可执行文件启动哨兵模式:

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

两种模式启动是一样的。

然而使用哨兵模式需要强制使用配置文件,系统将使用此文件来保存当前状态以便在重启时恢复。如果没有配置文件或者配置文件路径没有写权限的话哨兵模式会拒绝启动。

默认情况哨兵会监听26379的tcp端口,为了哨兵正常工作,必须要把26379端口必须要开放给其他哨兵实例的ip地址。否则哨兵不能通知或同意该做什么,故障恢复也无法正常工作。

部署前要了解的事
  1. 为了健壮性,至少要3个哨兵实例。
  2. 这3个实例要分开在不同的地方。
  3. 哨兵+Redis的分布式模式不能保证已写入的操作不会丢失,因为redis使用异步副本。有一些部署方法可以让丢失局限于某个时刻,还有一些其他不太安全的部署方法。
  4. 你的客户端需要支持哨兵。
  5. 你需要在开发环境甚至生产环境不断测试来保证安全。例如你可能由一些错误配置很晚才会暴露出来(凌晨3点主节点挂了)
  6. 哨兵、docker或其他形式的网络地址交换或端口映射应该小心:docker支持端口重映射,破坏了哨兵对其他哨兵进程和从节点list的发现。有关更多信息,请参阅本文档后面关于Sentinel和Docker的章节。
配置哨兵

redis源码中包含一个sentinel.conf文件可以用来做配置示例,但是一个最小化的哨兵配置文件类似下面的:

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

您只需要指定要监视的主机,为每个单独的主机(可能有任意数量的副本)指定不同的名称。副本不需要指定,会自动发现。哨兵将使用有关副本的附加信息自动更新配置(以便在重新启动时保留信息)。在故障切换期间,每当复制副本升级为主副本时,以及每当发现新的Sentinel时,也会重写配置

上面的示例监控了两组redis实例,每个都包含了一个master和若干的副本。一组叫mymaster,一组叫resque。

sentinel monitor命令的意思如下:

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

下面逐行解释配置:
第一行指定监控一个叫mymaster的主节点,地址是127.0.0.1,端口是6379,quorum为2,下面解释一下quorum:

  • quorum表示需要2个哨兵认为主节点故障,然后标记主节点不可用,启动故障恢复。
  • quorum只是用来检测故障,为了实际执行故障切换,其中一个哨兵需要被选为故障切换的领导者,并获得继续执行的授权。这只有在大多数哨兵进程投票的情况下才会发生。

例如我们有5个哨兵进程,quorum设置为2:

  • 如果两个哨兵同时认为主节点不可用,其中一个会尝试启动故障恢复。
  • 如果至少有3个哨兵正在运行,才会真正开始授权并执行故障恢复。

实际上,这意味着在发生故障时,如果大多数哨兵进程无法对话,就不会启动故障切换。就是说少数哨兵无法开始故障恢复。

其他配置

其他的配置格式总是下面这样:

sentinel <option_name> <master_name> <option_value>
  • down-after-milliseconds表示经过多少毫秒的哨兵认为这个节点不可用(ping不通或者返回一个错误)。
  • parallel-syncs表示故障恢复之后同时有多少个副本使用新的master,这个值越少,故障恢复需要的时间就越多。然而如果副本被配置为服务于旧数据的话,你可能不希望所有的副本都同时和新的master同步。尽管同步程序对副本来说是非阻塞的,也还是会有一段停止时间来从master获取大量数据。如果你希望一次只有一个副本停止服务的话需要将这个值设置为1。(简单来说就是一次可以有多少副本同步数据,如果一共10个副本,每次1秒同步1个,需要10秒。如果每次同步5个则需要2秒)。

哨兵部署实例

3个机器的部署

两个哨兵实例的情况不做讨论,因为没什么意义

最简单的3个哨兵:

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2

假设3台机器,每一台上都有redis实例和哨兵实例,M代表master,R代表replica,S代表Sentinel。
如果M1挂了,S2和S3会认为发生故障并授权故障转移。

在每个哨兵设置中,由于Redis使用异步副本,因此始终存在丢失某些写入的风险,因为已确认的写入可能无法同步到新选举的master。然而,上面的配置中由于客户端请求始终打在旧的master上,风险更高,如下图:

         +----+
         | M1 |
         | S1 | <- C1 (writes will be lost)
         +----+
            |
            /
            /
+------+    |    +----+
| [M2] |----+----| R3 |
| S2   |         | S3 |
+------+         +----+

在这个示例中,S2和S3所在的网络与S1不能通信,于是选举了新的master M2,但是客户端C1可能和M1在同一个分区中,所以仍然会将数据写入M1。当网络恢复之后,M1会降为M2的副本并同步M2的数据集,之前的数据就会永久丢失。

使用以下Redis复制功能可以缓解此问题,该功能会在master不能将数据同步给指定数量的副本时,停止接收新的请求。

min-replicas-to-write 1
min-replicas-max-lag 10

上面的配置解释:当一个master不能给至少一个副本同步数据时,会停止服务。因为副本是异步的,所以检测标准是在经过min-replicas-max-lag秒之后依然不能连接到副本,或者收到副本的确认。

在使用这种配置时,上面的M1会在10秒之后变得不可用。当分区通信恢复后,,哨兵配置将收敛到新的配置,客户端C1将能够获取有效的配置,并将继续使用新的主机。

然而这种情况下,如果两个副本都挂了,那么master不会再接收任何请求。这需要权衡。

当哨兵部署在客户机上时

有时我们只有两个可用的redis机器,一主一从。上面的配置就不适用了。所以我们使用下面这种将哨兵部署在客户端的方式:

            +----+         +----+
            | M1 |----+----| R1 |
            |    |    |    |    |
            +----+    |    +----+
                      |
         +------------+------------+
         |            |            |
         |            |            |
      +----+        +----+      +----+
      | C1 |        | C2 |      | C3 |
      | S1 |        | S2 |      | S3 |
      +----+        +----+      +----+

      Configuration: quorum = 2

这种配置下,哨兵视角和客户端相同,如果大多数客户端可以访问master就正常工作。这里的C指广义的客户端,并不是某个指定的连接到Redis的客户端。更像是应用服务器。

如果M1和R1都挂了,故障转移会正常调度。但是网络在这里会有明显影响。比如客户端和redis服务端不能正常通信,那么哨兵也就不能正常启动,因为M1和R1都不可用了。

如果C3和master不能通信了,那么就造成和上面的例子一样的问题。不同的是这里我们不能用上面的方法,因为只有一主一从,master不能再副本挂掉的情况下停止服务,否则一旦副本挂了整个redis都无法再提供服务。

因此,这个示例也是一种有效的配置,但之前的配置中的具有一些优点,例如Redis的高可用系统与Redis本身运行在同一个box中,这可能更易于管理,并且能够限制少数分区中的主机可以接收写操作的时间。

哨兵部署在少于3个的客户端中

如果我们的客户端不足3个,上面的例子也不适用。这时候我们需要下面这种混合配置:

            +----+         +----+
            | M1 |----+----| R1 |
            | S1 |    |    | S2 |
            +----+    |    +----+
                      |
               +------+-----+
               |            |
               |            |
            +----+        +----+
            | C1 |        | C2 |
            | S3 |        | S4 |
            +----+        +----+

      Configuration: quorum = 3

这里我们在4个机器中都部署了哨兵,如果M1不可用了,其他3个哨兵会执行故障转移。理论上没有C2和S4所在的机器依然能生效。但是我们一般不希望redis是高可用的但我们的应用服务不是高可用。

你可能感兴趣的:(redis)