Redis 的 Sentinel 哨兵是个特殊的 Redis 服务,不提供读写服务,主要用于管理多个 Redis 服务器实例, 执行以下三个任务:
在主从模式下,哨兵是一个独立的进程。其原理是哨兵进程向所有的 redis 机器发送命令,等待 redis 服务器响应,从而监控运行的多个 redis 实例。
哨兵可以有多个,为了便于决策选举,尽量使用奇数个哨兵。多个哨兵构成一个哨兵集群,哨兵直接也会相互通信,检查哨兵是否正常运行,当发现 master 宕机后哨兵之间会进行决策选举新的 master。
主从模式下,主节点会自动将数据同步到从节点,为了分载 master 的读操作压力,slave 服务器可以为客户端提供只读操作的服务,写服务依然必须由 master 来完成,实现读写分离。
当主节点宕机后,需要手动把一台从节点切换为主节点,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。
在哨兵模式下当 redis 的主节点发生变化,哨兵会第一时间感知到,并且将新的 redis 主节点通知给 client 端(主要是依靠发布/订阅)。
注意:
在哨兵模式下 client 端第一次从哨兵找出 redis 的主节点,后续就直接访问 redis 的主节点,不会每次都通过 sentinel 代理访问 redis 的主节点。
Redis 的 Sentinel 中关于下线(down)有两个不同的概念:
如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线。
注意:一个服务器必须在 master-down-after-milliseconds 毫秒内, 一直返回无效回复才会被 Sentinel 标记为主观下线。
举例:如果 master-down-after-milliseconds 选项的值为 30000 毫秒(30 秒), 那么只要服务器能在每 29 秒之内返回至少一次有效回复, 这个服务器就仍然会被认为是处于正常状态的。
从主观下线状态切换到客观下线状态并没有使用算法,而是使用了流言协议:
客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。
只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
配置启动哨兵时未曾配置对应的IP,哨兵之间是怎么发现对方的?
因为 Sentinel 可以通过发布与订阅功能来自动发现正在监视相同主服务器的其他 Sentinel , 这一功能是通过向频道 sentinel:hello 发送信息来实现的。
因此就不需要手动列出主服务器属下的所有从服务器, 因为 Sentinel 可以通过询问主服务器来获得所有从服务器的信息。
如果一个哨兵连接到主节点,则会获取主节上所有连接的从节点为,然后通过发布/订阅功能发现其他哨兵。
Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。
运行一个 Sentinel 所需的最少配置如下所示:
port 26379
#开启守护线程
daemonize yes
# 指定主节点信息
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
# 选举master时的quorum值
sentinel parallel-syncs mymaster 1
配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。
不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移, 并预留一个给定的一个新主服务器配置的版本号。
在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。其他选项的基本格式如下:
sentinel <选项的名字> <主服务器的名字> <选项的值>
各个选项的功能如下:
如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。
不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。
将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。
如果从服务器被设置为允许使用过期数据集(参见对 redis.conf 文件中对 slave-serve-stale-data 选项的说明), 那么你可能不希望所有从服务器都在同一时间向新的主服务器发送同步请求, 因为尽管复制过程的绝大部分步骤都不会阻塞从服务器, 但从服务器在载入主服务器发来的 RDB 文件时, 仍然会造成从服务器在一段时间内不能处理命令请求: 如果全部从服务器一起对新的主服务器进行同步, 那么就可能会造成所有从服务器在短时间内全部不可用的情况出现。
你可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。
搭建一个三节点的 Sentinel 集群,来监管之前的 Redis 主从集群,如图:
参考上述配置,分别复制 redis 下的 sentinel.conf 文件,如图:
文件中除端口外,其它配置都是一样的。
使用 redis-sentinel 命令来启动,也可以使用 redis-server 命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:
redis-sentinel /etc/redis/sentinel/26379.conf
# OR
redis-server /etc/redis/sentinel/26379.conf --sentinel
两种方法都可以启动一个 Sentinel 实例。
启动 Sentinel 实例必须指定相应的配置文件, 系统会使用配置文件来保存 Sentinel 的当前状态, 并在 Sentinel 重启时通过载入配置文件来进行状态还原。
如果启动 Sentinel 时没有指定相应的配置文件, 或者指定的配置文件不可写(not writable), 那么 Sentinel 会拒绝启动。
启动日志如下:
测试 6379 master节点宕机,并查看sentinel日志:
想要了解更多信息请参考:Redis Sentinel 的高可用性