在不使用redis cluster时,哨兵能够保证redis的高可用。
redis哨兵也会提供其他的附带功能,如监控、通知、作为配置提供者。
哨兵功能概述:
Redis哨兵是一个分布式系统:
哨兵本身是设计成可以多个哨兵进程协同工作的配置。优点如下:
当前的哨兵版本为哨兵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地址。否则哨兵不能通知或同意该做什么,故障恢复也无法正常工作。
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:
例如我们有5个哨兵进程,quorum设置为2:
实际上,这意味着在发生故障时,如果大多数哨兵进程无法对话,就不会启动故障切换。就是说少数哨兵无法开始故障恢复。
其他的配置格式总是下面这样:
sentinel <option_name> <master_name> <option_value>
两个哨兵实例的情况不做讨论,因为没什么意义
最简单的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个,上面的例子也不适用。这时候我们需要下面这种混合配置:
+----+ +----+
| M1 |----+----| R1 |
| S1 | | | S2 |
+----+ | +----+
|
+------+-----+
| |
| |
+----+ +----+
| C1 | | C2 |
| S3 | | S4 |
+----+ +----+
Configuration: quorum = 3
这里我们在4个机器中都部署了哨兵,如果M1不可用了,其他3个哨兵会执行故障转移。理论上没有C2和S4所在的机器依然能生效。但是我们一般不希望redis是高可用的但我们的应用服务不是高可用。