十一:TILT模式
根据之前的介绍可知,哨兵的运行,非常依赖于系统时间,但是当系统时间被调整,或者哨兵中的流程因为某种原因(比如负载较高、IO发生阻塞、进程被信号停止等)而被阻塞时,哨兵的行为就会变得不可预知了。
所谓TILT模式,就是一种特殊的保护模式。进入TILT模式后,哨兵只定期发送命令用于收集信息,而不采取实质性的动作,比如不会进行故障转移流程。
当恢复正常30秒后,哨兵就是退出TILT模式。
在哨兵的定时器函数sentinelTimer中,首先就是调用函数sentinelCheckTiltCondition判断哨兵当前是否需要进入TILT模式。该函数的代码如下:
void sentinelCheckTiltCondition(void) {
mstime_t now = mstime();
mstime_t delta = now - sentinel.previous_time;
if (delta < 0 || delta > SENTINEL_TILT_TRIGGER) {
sentinel.tilt = 1;
sentinel.tilt_start_time = mstime();
sentinelEvent(REDIS_WARNING,"+tilt",NULL,"#tilt mode entered");
}
sentinel.previous_time = mstime();
}
正常情况下,本函数每隔100ms执行一次。每次执行都会更新sentinel.previous_time属性。如果某次调用本函数时,发现当前时间与sentinel.previous_time间的差值为负值,或者大于SENTINEL_TILT_TRIGGER(2000),则置sentinel.tilt为1,说明哨兵进入了TILT模式,并且置sentinel.tilt_start_time为当前时间。
当进入TILT模式后,在收到其他实例的”INFO”命令回复后的回调函数sentinelRefreshInstanceInfo中,仅将收到的信息保存下来,而后续涉及到主从角色变化、故障转移流程等,都不再处理;而且当收到其他哨兵发来的,用于询问某主节点是否下线的"is-master-down-by-addr"命令时,一律回复“未下线”,因为处于TILT模式下的哨兵的判断,已经不可信了。
在哨兵的“主函数”sentinelHandleRedisInstance中,在调用函数sentinelSendPeriodicCommands发送完周期性的命令之后,有下面的代码:
void sentinelHandleRedisInstance(sentinelRedisInstance *ri) {
/* ========== MONITORING HALF ============ */
/* Every kind of instance */
sentinelReconnectInstance(ri);
sentinelSendPeriodicCommands(ri);
/* ============== ACTING HALF ============= */
/* We don't proceed with the acting half if we are in TILT mode.
* TILT happens when we find something odd with the time, like a
* sudden change in the clock. */
if (sentinel.tilt) {
if (mstime()-sentinel.tilt_start_time < SENTINEL_TILT_PERIOD) return;
sentinel.tilt = 0;
sentinelEvent(REDIS_WARNING,"-tilt",NULL,"#tilt mode exited");
}
/* Every kind of instance */
sentinelCheckSubjectivelyDown(ri);
...
}
因此,在TILT模式下,仅仅发送命令收集信息,而不会进行故障转移流程相关的动作。并且,当哨兵处于TILT模式下连续超过SENTINEL_TILT_PERIOD(30秒)后,就会退出TILT模式。
十二:执行脚本
哨兵支持在发生某种事件,或者是因发生了故障转移而主节点的地址发生变化时,能够执行相应的脚本,以便通知系统管理员事件的发生,或是通知客户端主节点的新地址信息。
目前哨兵支持两种脚本。一种是当发生某种WARNING级别的事件(比如实例主观下线、客观下线等)时,调用脚本以便通过邮件、短信或者其他方式,将事件通知给系统管理员。脚本调用时,会传递两个参数,一是事件的类型,一是事件的描述信息。
这种脚本可以通过配置文件中的” notification-script”选项配置:
sentinel notification-script mymaster /var/redis/notify.sh
另一种是当发生故障转移,导致主节点