目的
解决redis的高可用问题,
主要通过监听主从服务器,在主服务器宕机的时候,选择一个最合适的从服务器作为主服务器,并在主服务器重启后,将其作为新主的从机
如何操作
- 使用
redis-sentinel或者reids-server --sentinel来启动sentinel - 配置需要监听的主服务器
ip和端口,可以同时配置多个主服务器 - 启动即可
- 不需要填写从机信息
- 不需要设置其它
sentinel信息
sentinel
sentinel 本质上就是redis-server ,但是其redisCommand表包含的命令和普通的redis-server不同,只有subscribe,unsubscribe,ping,psubscribe,punsubscribe,info等查询,订阅相关的命令。
除了拥有redisService结构体信息外,还拥有redisSentinel结构体信息,里面存放在如下信息
struct redisSentinel{
int epoch;//选主纪元,参考分布式一致性算法Rfat
SentinelRedisInstance * master;//监听的主机列表
}
struct SentinelRedisInstance {
char * run_id;
char *ip;
int port;
char* name;
SentinelRedisInstance *slaves;
SentinelReidsInstance *sentinels;
int flags;
}
学前问题
- 只配置了主机,如何获取从机信息?
- 可以多个
Sentinel可以监听同一主机,那么Sentinel之间如何知晓对方? - 如何判断主机是否真正下线?
- 如何选择从机作为主机?选择标准是什么?
具体过程
-
启动
sentinel,同监视主机建立连接 -
以每10s一次的频率发送
info给主机,获取主机信息,并从中获取从机信息。然后同才同从机建立连接。- 当发现新
从机后,会建立对应的connection,并以同样的频率发送info命令,获取从机信息,包括从服务器优先级,复制偏移量等.并添加到对应主机的slaves列表中。
# Server...run_id:32be0699dd27b410f7c90dada3a6fab17f97899f... # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up slave_repl_offset:11887 slave_priority:100 # Other sections... - 当发现新
-
订阅主从服务的
__sentinel__:hello频道,并以每2s的频率向订阅频道发送PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>",其中s开头表示是sentinel自己本身的信息,m开头表示接收消息主机的信息.如此就可以知晓其它sentinel,并将其记录在对应master的sentinels列表。并同其它sentinel建立连接(那就相当于两个sentinel各自和对方建立一个连接,而不能复用) -
检测主观下线
- 以
1s每次的频率向所有建立连接的实例发送ping命令来判断是否在线, - 当在
down-after-milliseconds内连续收到无效的回复或者指定时间内没返回结果的化,就认为其主观下线,并修改对应SentinelRedisInstance中的flags,新增主观下线标识。
- 以
-
判断客观下线:
-
当
sentinel认定某一实例主机为主观下线后,会向其它同样监听该实例的sentinel发送请求,让其判断是否下线,如果超过 一定数量的话(quorum参数配置),就认为其主观下线。 -
请求命令为
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>其中ip和port是 主机的ip,port,current_epoch是当前纪元。runid则为*,该命令也使用sentinel之间选主。此时runid则等于发送sentinel的runid -
返回内容则为:
1) <down_state> 2) <leader_runid> 选主的时候填写,否则为* 3) <leader_epoch> 选主的时候填写,否则为0
-
-
选择领头
sentinel来进行故障切换-
使用Raft来选主
-
每一个
sentinel都可以使用sentinel is-master-down-by-addr发起选主请求。- 每一个收到该请求的
sentinel - 首先判断请求纪元是否和自身纪元相等
- 如果相等,则返回同意。同时本身
纪元+1。 - 如果不相等,则返回不同意。
- 每一个收到该请求的
-
当超过一半的
sentienl同意后,请求的sentinel成为领头sentinel,执行选主操作,否则等待随机时间后,再次进行投票选择
-
-
故障切换
-
剔除无效的从机
- 以及客观下线的
- 最近5s 回复
sentinel的info请求的(存疑,info 默认是10s发送一次) - 于主机断开时间超过
down-after-milliseconds*10毫秒的从服务器,保证从机不会过早的于主机断开 - 从剩余的从机按优先级,复制量,runid(正序)选择候选主机
-
向候选主机发送
slaveof no one -
向其它从机发送
slaveof newip newport -
当主机从新上线后,向其发送
slaveof newip newport命令
-
学后问题
- 如果同时向多个主机发送
ping? - 如何监听已下线的主机重新上线?猜测使用
serverCron - 从机同步新的主机的时候,是不是全量同步?是,因为
服务器id都不相同