sentinel初始化
sentinel运作
- 监控:如何获取主服务器,从服务器,其他哨兵的状态信息
- 提醒:如何与主从服务器沟通
- 检测下线状态:当有主服务器下线时,如何检测
- 自动故障迁移
1.Sentinel启动与初始化
启动命令:
redis-sentinel /path/to/your/sentinel.conf
初始化步骤:
- 启动服务器,使用sentinel专用代码
- 初始化SentinelState,建立与主服务器的连接
(1)初始化服务器
具体步骤与服务器初始化差不多,但是少了点步骤,比如不会进行RDB/AOF恢复
(2)使用sentinel专用代码
比如:
1.使用 define REDIS_SENTINEL_PORT 26379 作为端口号
2.命令表不一样,只有一些简单的命令
(3)初始化SentinelState
sentinelState专门记录与哨兵有关的状态
sentinelRedisInstance用来记录每个被监视的服务器的消息,这些服务器可以是主服务器,从服务器,或者其他sentinel。其中比较重要的属性有addr(记录这个服务器的ip+端口号),slaves字典(记录它的从服务器),sentinels(监视它的其他sentinels)
struct sentinelState {
// 当前纪元,用于实现故障转移
uint64_t current_epoch;
// 保存了所有被这个 sentinel 监视的主服务器
// 字典的键是主服务器的名字
// 字典的值则是一个指向 sentinelRedisInstance 结构的指针
dict *masters;
// 是否进入了 TILT 模式?
int tilt;
// 目前正在执行的脚本的数量
int running_scripts;
// 进入 TILT 模式的时间
mstime_t tilt_start_time;
// 最后一次执行时间处理器的时间
mstime_t previous_time;
// 一个 FIFO 队列,包含了所有需要执行的用户脚本
list *scripts_queue;
} sentinel;
struct sentinelRedisInstance {
// 标识值,记录了实例的类型,以及该实例的当前状态
int flags;
// 实例的名字
// 主服务器的名字由用户在配置文件中设置
// 从服务器以及Sentinel的名字由Sentinel自动设置
// 格式为ip:port
char *name;
// 实例的运行ID
char *runid;
// 配置纪元,用于实现故障转移
unit64_t config_epoch;
// 实例的地址
sentinelAddr *addr;
// 实例无响应多少毫秒之后才会被判断为主观下线
mstime_t down_after_period;
// 判断这个实例为客观下线所需的支持投票数量
int quorum;
// 在执行故障转移操作时,可以同事对行的主服务器进行同步的从服务器数量
int parallel_syncs;
// 刷新故障迁移状态的最大时限
mstime_t failover_timeout;
// 一个主服务器所有从服务器实例
dict *slaves;
// 监视这个主服务器的所有sentinels实例
dict *sentinels;
// ...
} sentinelRedisInstance;
(4)连接主服务器
最后一步是创建与主服务器的网络连接。sentinel会创建两个连接:命令连接+订阅连接(__sentinel__:hellp频道)
2.监控
这里监控指:sentinel维护其他主服务器,从服务器,sentinel的状态信息
(1)获取主服务器状态信息
默认每10秒给主服务器发送INFO命令,更新sentinelRedisInstance的信息。
INFO指令返回的信息如下图所示。
(2)获取从服务器状态信息
根据从主服务器那里获取的信息,再对从服务器们创建命令连接和订阅连接,并更新
默认每10秒给从服务器发送INFO命令,获取从服务器信息(如:run_id,角色role,主服务器的ip和端口,连接状态,优先级,偏移量)
(3)获取其他哨兵状态信息
由于Sentinel会用订阅模式给 __sentinel__:hello 频道发信息,每个sentinel收到该信息时:
- 如果判断出是自己发送的,则忽略
- 如果是其他sentinel发送的,则将那个sentinel更新到sentinelRedisInstance中
(4)每个主服务器的sentinelRedisInstance如下图所示
3.提醒
这里提醒是指:sentinel向其他发送消息
(1)向主服务器和从服务器发送信息
默认情况下,每2秒发送订阅信息(s_*:自己的信息,m_*:主服务器的信息)
- 如果发送给主服务器,那么m_*就是它的信息
- 如果发送给从服务器,那么m_*就是它的主服务器的信息
(2)接受主服务器和从服务器的信息
sentinel订阅了 __sentinel__:hello 频道的信息
4.检测下线状态
检查主观下线(发现某一master可能下线)——> 检查客观下线(询问其他哨兵,确定是否下线) ——> 选举领头
(1)主观下线:自己判断
Sentinel会以每秒1次的频率发送给(从服务器+主服务器+其他哨兵)PING命令。
有效回复为: PONG, LOADING, MASTERDOWN。其他都为无效回复
Sentinel配置文件中的 down-after-milliseconds指定了时间。
eg. sentinel down-after-milliseconds master 50000。
如果master在50秒内都没有进行有效回复,则sentinel认定它已经下线。并把对应的master的flags增加一个标志位 SRI_S_DOWN
(2)客观下线:询问其他
当sentinel主观判断一个主服务器下线后,为了再次确认,会向其他sentinel询问。
2.1 先向其他sentinel发送命令
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
//ip,port为被判断下线的主服务器的ip和port
//current_epoch为配置纪元
//runid:1. * :向其他哨兵检测客观下线
// 2. sentinel的运行id:判断完客观下线后,用于选举领头sentinel
2.2 其他sentinel的回复
<down_state> //1代表判断主服务器已经下线;0代表未下线
<leader_runid> //*:代表检测下线的回复
//runid:用于选举领头哨兵
<leader_epoch> //当runid=*时:总是为0,无意义
//选举时,有效
eg.
1) 1
2) *
3) 0
这个消息代表其他sentinel也同意服务器下线
2.3 收到其他sentinel的回复
当收到的回复大于一定数量(根据配置信息),该sentinel会认定该主服务器已经客观下线,再增加一个标志位 SRI_O_DOWN
配置: sentinel monitor master 127.0.0.1 6379 5
表示 >=5个时,就认定已经客观下线
(3)选举领头
当一个sentinel主观客观检测都判断主服务器下线后,会继续发送 is-master-down-by-addr 指令。
不过这次的 runid不再是*, 而是自己的id。
每个sentinel在同一个epoch中只能投一票,对最先收到的那个sentinel进行回复投票,内容如 2.2。
当某个sentinel收到的票数>n/2时(比如,n=10,则需要6票),它将成为领头哨兵
5.故障转移
流程:
(1)挑选新的主服务器
(2)让所有从服务器复制新的主服务器
(3)让原来的主服务器变成从服务器
1.选出新的主服务器
领头sentinel会选出新的主服务器,要求如下
(1)必须在线
(2)响应快的(最近与领头sentinel成功通信过的)
(3)最近与原来的主服务器保持联系的(换句话说,从服务器中保存的数据都是比较新的)
(4)如果有多个满足,则排序:优先级——offset——runid
选出新主服务器后,领头sentinel会给其发送 slaveof no one 命令
发送完后,领头sentinel会以每秒一次给它发送INFO命令,当返回的角色从slave变成master后,就确认成功了
2.修改从服务器的复制目标
给其他从服务器发送 slaveof 命令
3.将旧的主服务器变成从服务器
当旧服务器上线时,向其发送 slaveof 命令