Redis Sentinel 是 Redis官方提供的高可用解决方案。Redis本身可以实现主从复制,但是并没有自动切换主备的功能,当出现其中一个主实例宕机的情况,客户端将无法执行写入命令,Sentinel可以在没有人工干预的情况下执行故障转移,不影响正常的写入操作。Sentinel是一个分布式的系统,多个Sentinel进程之间协调工作,一来保证故障检测的误报率,二来保证了Sentinel本身的可用性。
Sentinel提供了以下功能:
- 监控。Sentinel会不断检查主从是否按预期工作。
- 通知。Sentinel可以通过API通知系统管理员,另一台计算机程序,其中一个受监控的Redis实例出现问题。
- 自动故障转移。如果主服务器未按预期工作,Sentinel可以启动故障转移过程,其中从服务器升级为主服务器,其他其他服务器重新配置为使用新主服务器,并且使用Redis服务器的应用程序通知有关新服务器的地址连接。
- 配置提供商。Sentinel充当客户端服务发现的权限来源:客户端连接到Sentinels,以便询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,Sentinels将报告新地址。
配置
我挑了一些主要的配置项出来,其它的都与redis.conf类似
# sentinel announce-ip
# sentinel announce-port
sentinel auth-pass mymaster
# sentinel monitor
sentinel monitor mymaster 127.0.0.1 6379 2
# sentinel down-after-milliseconds
sentinel down-after-milliseconds mymaster 30000
# sentinel parallel-syncs
sentinel parallel-syncs mymaster 1
# sentinel failover-timeout
sentinel failover-timeout mymaster 180000
-
sentinel auth-pass
,配置主服务器的密码 -
sentinel monitor
,配置需要监视的主服务器,最后一个为仲裁参数
,代表Sentinel集群中必须有至少2个实例认为主服务器不可用,其中一个尝试启动故障转移,默认127.0.0.1 6379 2
-
sentinel down-after-milliseconds
, 主服务器未回复sentinel ping的时长,如果超过这个时长,则这个sentinel实例主观的认为主服务器不可用,默认3000
-
sentinel parallel-syncs
, 设置可在同一故障转移后重新配置以使用新主服务器的从服务器数,默认1
-
sentinel failover-timeout
,指定故障转移超时时长,默认180000
启动
可以通过以下两种方式开启Sentinel:
redis-server sentinel.conf --sentinel
或
redis-sentinel sentinel.conf
Sentinel 解析
任何一个sentinel实例主要达到SDOWN的条件,就将该服务器标记为 SDOWN,如果有至少 qurom
个实例都认为该服务器SDOWN,就标记为 ODOWN,此时触发故障转移,需要满足大多数Sentinel实例的授权才能进行故障转移。例设有5个sentinel 实例,配置 qurom 为 2 , 5个实例,有2个认为服务器无法访问,就尝试故障转移,只有3个或以上实例授权后才能执行故障转移,如果qurom设置为5,则当ODOWN时,直接进行故障转移。
Sentinel 实例之间的通信
Sentinel 实例之间通过名为 __sentinel__:hello
的 Pub/Sub channel 进行通信
- 每个 Sentinel 每隔2秒向 channel 中发送 ip port runid 宣布它的存在
- 每个 Sentinel 订阅 channel ,当检测到新的 Sentinel 后,将它添加进集群中
- 消息中包括完整的当前服务器的配置,如果某个Sentinel 还是旧的服务器的配置,将会立刻更新
- 在向主服务器添加新的标记之前,Sentinel始终检查是否已存在具有相同runid或相同地址(ip和端口对)的标记。在这种情况下,将删除所有匹配的标记,并添加新的标记。
SDOWN 和 ODOWN状态
- Subjectively Down(SDOWN,主观下线),单个实例对服务器做出的下线判断
- Objectively Down(ODOWN,客观下线),多个实例对同一个服务器做出的下线判断,并且多个实例之间已经通过
SENTINEL is-master-down-by-addr
交流之后做出的下线判断。
Sentinel 每隔1秒向服务器发出 ping 命令,如果服务器距离上次回复ping 已经超过了 down-after-milliseconds
所设置的时长,或者不是以下三个中的命令时,sentinel 认为这个服务器下线了(主观下线):
- +PONG
- -LOADING
- -MASTERDOWN
当多个sentinel实例(qurom)对同一个服务器做出主观下线的判断后,状态变为 ODOWN
Slave 选择和优先权
当Sentinel开始执行故障转移时,需要在 从服务器之间选出一个,来提升为主服务器,只要参考以下4个方面:
- 与原主服务器断开连接的时长
- Slave priority,在 redis.conf 中有配置
slave-priority
,默认为100,数字越小将越优先 - 已经处理的复制偏移量
- Run ID
分区下的一致性
+-------------+
| Sentinel 1 | <--- Client A
| Redis 1 (M) |
+-------------+
|
|
+-------------+ | +------------+
| Sentinel 2 |-----+-- / partition / ----| Sentinel 3 | <--- Client B
| Redis 2 (S) | | Redis 3 (M)|
+-------------+ +------------+
初始状态下redis3是master, redis1和redis2是slave。之后redis3所在的主机网络不可用了,sentinel1和sentinel2启动了failover并把redis1选举为master。
Sentinel集群的特性保证了sentinel1和sentinel2得到了关于master的最新配置。但是sentinel3依然持着的是旧的配置,因为它与外界隔离了。
客户端将依然可以向redis3写数据,但是当网络恢复后,redis3就会变成redis的一个slave,那么,在网络隔离期间,客户端向redis3写的数据将会丢失。
如果你把redis当做缓存来使用,那么你也许能容忍这部分数据的丢失。
但如果你把redis当做一个存储系统来使用,你也许就无法容忍这部分数据的丢失了。
因为redis采用的是异步复制,在这样的场景下,没有办法避免数据的丢失。然而,你可以通过以下配置来配置redis3和redis1,使得数据不会丢失。
可以通过下面2个参数进行配置,保证只要有一个从服务器断开了与主服务器的连接就不执行写入操作。具体可以参考 Redis从入门到精通(六、Redis主从复制)
min-slaves-to-write 1
min-slaves-max-lag 10
Sentinel persistent state
Sentinel状态保留在sentinel配置文件中。这意味着停止并重新启动Sentinel进程是安全的。
更多详细资料参考:
Redis Sentinel 官方文档