Redis之哨兵机制
前言
Redis
的 主从复制 模式下,一旦 主节点 由于故障不能提供服务,需要手动将 从节点 晋升为 主节点,同时还要通知 客户端 更新 主节点地址,这种故障处理方式从一定程度上是无法接受的。Redis 2.8
以后提供了 Redis Sentinel
哨兵机制 来解决这个问题。
其他文章
正文
1. Redis高可用概述
在 Web
服务器中,高可用 是指服务器可以 正常访问 的时间,衡量的标准是在 多长时间 内可以提供正常服务(99.9%
、99.99%
、99.999%
等等)。在 Redis
层面,高可用 的含义要宽泛一些,除了保证提供 正常服务(如 主从分离、快速容灾技术 等),还需要考虑 数据容量扩展、数据安全 等等。
在 Redis
中,实现 高可用 的技术主要包括 持久化、复制、哨兵 和 集群,下面简单说明它们的作用,以及解决了什么样的问题:
-
持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。
-
复制:复制是高可用
Redis
的基础,哨兵 和 集群 都是在 复制基础 上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。 -
哨兵:在复制的基础上,哨兵实现了 自动化 的 故障恢复。缺陷是 写操作 无法 负载均衡,存储能力 受到 单机 的限制。
-
集群:通过集群,
Redis
解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善 的 高可用方案。
PS:Redis集群方式共有三种:主从模式(复制),哨兵模式,cluster(集群)模式
2. Redis Sentinel的基本概念
Redis Sentinel
是 Redis
高可用 的实现方案。Sentinel
是一个管理多个 Redis
实例的工具,它可以实现对 Redis
的 监控、通知、自动故障转移。下面先对 Redis Sentinel
的 基本概念 进行简单的介绍。
基本名词说明:
基本名词 | 逻辑结构 | 物理结构 |
---|---|---|
Redis数据节点 | 主节点和从节点 | 主节点和从节点的进程 |
主节点(master) | Redis主数据库 | 一个独立的Redis进程 |
从节点(slave) | Redis从数据库 | 一个独立的Redis进程 |
Sentinel节点 | 监控Redis数据节点 | 一个独立的Sentinel进程 |
Sentinel节点集合 | 若干Sentinel节点的抽象组合 | 若干Sentinel节点进程 |
Redis Sentinel | Redis高可用实现方案 | Sentinel节点集合和Redis数据节点进程 |
应用客户端 | 泛指一个或多个客户端 | 一个或者多个客户端进程或者线程 |
如图所示,Redis
的 主从复制模式 和 Sentinel
高可用架构 的示意图:
3. Redis主从复制的问题
Redis
主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:
- 一旦 主节点宕机,从节点 作为 主节点 的 备份 可以随时顶上来。
- 扩展 主节点 的 读能力,分担主节点读压力。
主从复制 同时存在以下几个问题:
-
一旦 主节点宕机,从节点 晋升成 主节点,同时需要修改 应用方 的 主节点地址,还需要命令所有 从节点 去 复制 新的主节点,整个过程需要 人工干预。
-
主节点 的 写能力 受到 单机的限制。
-
主节点 的 存储能力 受到 单机的限制。
-
原生复制 的弊端在早期的版本中也会比较突出,比如:
Redis
复制中断 后,从节点 会发起psync
。此时如果 同步不成功,则会进行 全量同步,主库 执行 全量备份 的同时,可能会造成毫秒或秒级的 卡顿。
4. Redis Sentinel深入探究
4.1. Redis Sentinel的架构
4.2. Redis Sentinel的主要功能
Sentinel
的主要功能包括 主节点存活检测、主从运行情况检测、自动故障转移 (failover
)、主从切换。Redis
的 Sentinel
最小配置是 一主一从。
Redis
的 Sentinel
系统可以用来管理多个 Redis
服务器,该系统可以执行以下四个任务:
- 监控
Sentinel
会不断的检查 主服务器 和 从服务器 是否正常运行。
- 通知
当被监控的某个 Redis
服务器出现问题,Sentinel
通过 API
脚本 向 管理员 或者其他的 应用程序 发送通知。
- 自动故障转移
当 主节点 不能正常工作时,Sentinel
会开始一次 自动的 故障转移操作,它会将与 失效主节点 是 主从关系 的其中一个 从节点 升级为新的 主节点,并且将其他的 从节点 指向 新的主节点。
- 配置提供者
在 Redis Sentinel
模式下,客户端应用 在初始化时连接的是 Sentinel
节点集合,从中获取 主节点 的信息。
4.3. 主观下线和客观下线
默认情况下,每个 Sentinel
节点会以 每秒一次 的频率对 Redis
节点和 其它 的 Sentinel
节点发送 PING
命令,并通过节点的 回复 来判断节点是否在线。
- 主观下线
主观下线 适用于所有 主节点 和 从节点。如果在 down-after-milliseconds
毫秒内,Sentinel
没有收到 目标节点 的有效回复,则会判定 该节点 为 主观下线。
- 客观下线
客观下线 只适用于 主节点。如果 主节点 出现故障,Sentinel
节点会通过 sentinel is-master-down-by-addr
命令,向其它 Sentinel
节点询问对该节点的 状态判断。如果超过 <quorum>
个数的节点判定 主节点 不可达,则该 Sentinel
节点会判断 主节点 为 客观下线。
4.4. Sentinel的通信命令
Sentinel
节点连接一个 Redis
实例的时候,会创建 cmd
和 pub/sub
两个 连接。Sentinel
通过 cmd
连接给 Redis
发送命令,通过 pub/sub
连接到 Redis
实例上的其他 Sentinel
实例。
Sentinel
与 Redis
主节点 和 从节点 交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING |
Sentinel 向 Redis 节点发送 PING 命令,检查节点的状态 |
INFO |
Sentinel 向 Redis 节点发送 INFO 命令,获取它的 从节点信息
|
PUBLISH |
Sentinel 向其监控的 Redis 节点 __sentinel__:hello 这个 channel 发布 自己的信息 及 主节点 相关的配置 |
SUBSCRIBE |
Sentinel 通过订阅 Redis 主节点 和 从节点 的 __sentinel__:hello 这个 channnel ,获取正在监控相同服务的其他 Sentinel 节点 |
Sentinel
与 Sentinel
交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING |
Sentinel 向其他 Sentinel 节点发送 PING 命令,检查节点的状态 |
SENTINEL:is-master-down-by-addr | 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点
|
4.5. Redis Sentinel的工作原理
每个 Sentinel
节点都需要 定期执行 以下任务:
- 每个
Sentinel
以 每秒钟 一次的频率,向它所知的 主服务器、从服务器 以及其他Sentinel
实例 发送一个PING
命令。
- 如果一个 实例(
instance
)距离 最后一次 有效回复PING
命令的时间超过down-after-milliseconds
所指定的值,那么这个实例会被Sentinel
标记为 主观下线。
- 如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有
Sentinel
节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。
- 如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的
Sentinel
(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线。
- 在一般情况下, 每个
Sentinel
会以每10
秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送INFO
命令。当一个 主服务器 被Sentinel
标记为 客观下线 时,Sentinel
向 下线主服务器 的所有 从服务器 发送INFO
命令的频率,会从10
秒一次改为 每秒一次。
-
Sentinel
和其他Sentinel
协商 主节点 的状态,如果 主节点 处于SDOWN
状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
- 当没有足够数量的
Sentinel
同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向Sentinel
的PING
命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。
注意:一个有效的
PING
回复可以是:+PONG
、-LOADING
或者-MASTERDOWN
。如果 服务器 返回除以上三种回复之外的其他回复,又或者在 指定时间 内没有回复PING
命令, 那么Sentinel
认为服务器返回的回复 无效(non-valid
)。