Redis笔记——Sentinel
Sentinel(哨兵)
-
什么是 Sentinel ?
Sentinel(哨兵)是 Redis 的高可用性解决方案:由一个或多个 Sentinel 实例组成的 Sentinel 系统可以监视任意多个主服务器,以及由这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
启动并初始化 Sentinel
启动 Sentinel 命令:
redis-sentinel /path/to/your/sentinel.conf 或者 redis-server /path/to/your/sentinel.conf --sentinel
当一个 Sentinel 启动时,需要执行以下步骤:
1)初始化服务器
Sentinel 本质上只是一个运行在特殊模式下的 Redis 服务器,所以启动 Sentinel 的第一步,就是初始化一个普通的 Redis 服务器。
Sentinel 不使用数据库,初始化 Sentinel 时不会载入 RDB 文件或者 AOF 文件。
2)使用 Sentinel 专用代码
Sentinel 使用 sentinel.c/sentinelcmds 作为服务器的命令表,只有七个命令。
3)初始化 Sentinel 状态
4)初始化 Sentinel 状态的 masters 属性
masters 字典的初始化是根据被载入的 Sentinel 配置文件来进行的。
Sentinel 状态的 masters 字典记录了所有被 Sentinel 监视的主服务器的相关信息。其中:- 字典的键是被监视主服务器的名字。
- 字典的值是被监视主服务器对应的 sentinelRedisInstance 结构(实例结构)
sentinelRedisInstance 代表一个被 Sentinel 监视的 Redis 服务器实例,这个实例可以是主服务器、从服务器,或者另一个 Sentinel。
sentinelRedisInstance结构Sentinel状态以及masters字典
5)创建连向主服务器的网络连接
对于每个被 Sentinel 监视的主服务器来说,Sentinel 会创建两个连向主服务器的异步网络连接:- 命令连接,专门用于向主服务器发送命令,并接收命令回复。
- 订阅连接,专门用于订阅主服务器的 __sentinel__:hello 频道。
获取主服务器、从服务器的信息
Sentinel 默认每十秒一次的频率,通过命令连接向被监视的主服务器发送 INFO 命令,并通过分析 INFO 命令来获取主服务器的当前信息。
- 主服务器本身的信息。包括 run_id 域记录的服务器运行 ID,以及 role 域记录的服务器角色;
- 主服务器属性所有从服务器信息。
根据 run_id 域和 role 域记录的信息,Sentinel 将会对主服务器的实例结构进行更新,至于主服务器返回的从服务器信息,则会用来更新主服务器实例结构的 slave 字典,这个字典记录了主服务器属下从服务器的名单。
主服务器和它的三个从服务器器
当 Sentinel 发现主服务器有新的从服务器出现时,Sentinel 除了会为这个新的从服务器创建相应的实例结构以外,Sentinel 还会创建连接到从服务器的命令连接和订阅连接。
创建命令连接之后,Sentinel 默认每十秒一次的频率,通过命令连接向从服务器发送 INFO 命令。根据 INFO 命令的回复,Sentinel 会对从服务器的实例结构进行更新。接受来自主服务器和从服务器的频道信息
Sentinel 对 __sentinel__:hello 频道的订阅会一直持续到 Sentinel 与服务器的连接断开为止。
对于监视同一个服务器的多个 Sentinel 来说,一个 Sentinel 发送的消息会被其他 Sentinel 接收到,这些信息会被用于更新其他 Sentinel 对发送消息 Sentinel 的认知,也会用于更新其他 Sentinel 对被监视服务器的认知。
更新sentinels字典
当 Sentinel 通过频道信息发现一个新的 Sentinel 时,不仅会为新 Sentinel 在 sentinels 字典中创建相应的实例结构,还会创建一个连向新 Sentinel 的命令连接,而新 Sentinel 也同样会创建连向这个 Sentinel 的命令连接,最终监视同一个主服务器的多个 Sentinel 将形成相互连接的网络。
Sentinel 之间不会创建订阅连接。因为 Sentinel 需要通过接受主服务器或者从服务器发来的频道信息来发现未知的新 Sentinel ,所以才需要建立订阅连接,而相互已知的 Sentinel 只要使用命令连接来进行通信就足够了。检测主观下线和客观下线
检测主观下线
默认情况下,Sentinel 以每秒一次的频率向所有与它创建了命令连接的实例发送 PING 命令,并通过返回的 PING 命令回复来判断实例是否在线。
如果一个实例在 down-after-milliseconds 毫秒内,连续向 Sentinel 返回无效回复,那么 Sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中打开SRI_S_DOWN 标识,表示这个实例已经进入主观下线状态。
注意:多个 Sentinel 设置的主观下线时长可能不同。
检测客观下线
当 Sentinel 将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线,会向同样监视这一主服务器的其他 Sentinel 进行询问,看它们是否也认为主服务器已经进入下线状态。当 Sentinel 从其他 Sentinel 那里接收到足够数量(超过 Sentinel 配置中设置的 quorum参数的值)的已下线判断以后,Sentinel 就会将从服务器判定为客观下线,并对主服务器执行故障转移操作。
发送 SENTINEL is-master-down-by-addr 命令询问其他 Sentinel 是否同意主服务器已下线。命令中的各个参数的意义如下所示。
接收 SENTINEL is-master-down-by-addr 命令并返回 Multi Bulk 回复。回复参数的意义如下所示:
注意:不同 Sentinel 判断客观下线的条件可能不同。选举领头 Sentinel 和故障转移
当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个 Sentinel 会选举出一个领头 Sentinel,并由领头 Sentinel 对下线主服务器进行故障转移操作。
Redis选举领头 Sentinel 的规则和方法:- 所有在线的 Sentinel 都有被选为领头 Sentinel 的资格。
- 每次进行领头 Sentinel 选举之后,无论选举是否成功,所有 Sentinel 的配置纪元的值都会自增一次。配置纪元实际上就是一个计数器。
- 在一个配置纪元里,所有 Sentinel 都有一次机会将某个 Sentinel 设置为局部领头 Sentinel 的机会,并且局部领头一旦设置,在这个配置纪元里面就不能再更改。
- Sentinel 设置局部领头 Sentinel 的规则是先到先得。
- 如果由某个 Sentinel 被半数以上的 Sentinel 设置成了局部领头 Sentinel,那么这个 Sentinel 成为了领头 Sentinel。
- 如果给定时限内,没有一个 Sentinel 被选举为领头 Sentinel,那么各个 Sentinel 将在一段时间内再次进行选举,直到选出领头 Sentinel 为止。
故障转移
1)在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将器转换为主服务器。
2)让已下线主服务器属下的所有从服务器改为复制新的主服务器。
3)将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,它会成为新的主服务器的从服务器。