这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
一、前言
在主从库模式下:
- 如果从库故障了,主库和其他从库仍可以保证集群正常运行。
- 可如果主库挂了呢?
那么在主从库模式下,主库挂了会发生什么:
- 读操作:从库仍可以继续提供读操作服务
- 写操作:写操作异常(因为主库提供写操作服务)
- 数据同步:从库无法进行数据同步
如果主库挂了,就需要选举出一个新的主库,才能继续提供正常的服务。
在这个场景下,就需要回答三个问题:
- 如何判断主库挂了?
- 选择哪个从库作为主库?
- 如何把主库的信息同步给其他从库和其他端?
这时候就需要另外一个机制来监控 Redis
实例:哨兵机制。
那么这个哨兵机制就需要回答这三个问题:
- 监控:主库是否存活?
- 选主:在从库中选择一个成为主库。
- 通知:告诉其他从库,新主库的信息。
二、哨兵机制
哨兵其实一个运行在特殊模式下的
Redis
进程,主从库运行的同时,它也在运行。
如上所知,哨兵必须拥有以下三种能力:
- 监控:判断主从库下线
- 选主:选出新主库
- 通知:让从库执行
replicaof
,与新主库同步; 通知客户端,与新主库连接
(1)监控
监控:说白就是定时去问候下,是否还活着。
即:哨兵进程在运行时,周期性给所有的主从库发送
PING
命令,检测是否正常运行。
如果没在规定时间内响应哨兵的 PING
命令:
- 从库:会被标记为 “下线状态”
- 主库:会被判定为 “主库下线”,之后开始自动切换主库流程
哨兵对主库的下线判断有:“主观下线”、“客观下线”
- “主观下线”:哨兵发现主库或从库对
PING
命令的响应超时。 - “客观下线”:当有
N
个哨兵实例时,有N/2 + 1
个实例判断主库为 “主观下线”,才能最终判定主库为 “客观下线”。
如果哨兵对主库进行了误判下线,就会触发从库切换,从而带来额外的计算和通信开销。
但实际上只是集群网络压力过大、网络阻塞或者主库本身压力较大,造成短暂响应超时。
为减少误判,就不能一个哨兵说了算,得有一个哨兵集群(多实例组成),来一起进行判断:
- 可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况
- 多个哨兵的网络同时不稳定的概率较小
举个栗子:
Redis
主从集群有一个主库、三个从库、三个哨兵实例- 情况一(左边):哨兵2 判断主库为 “主观下线”,哨兵1 和 哨兵2 判断主库为 “上线状态”; 最终,主库仍判定为 “上线状态”。
- 情况二(右边):哨兵3 判断主库为 “上线状态”,哨兵1 和 哨兵2 判断主库为 “主观下线”; 最终,主库仍判定为 “客观下线”。
(2)选主
既然判断主库下线了,那接下来就得选主了。
选主基本流程:筛选 + 打分
- 筛选:根据在线状态、网络状态过滤一些不符合要求的从库。
- 打分:依次按照优先级、复制进度、
ID
号大小进行打分,得分最高的从库选为新主库。
筛选
筛选标准:
- 从库当前的在线状态:是否在线
- 从库之前的网络连接状态:从库和主库断连次数是否超出了一定的阈值
断连次数如何判断?使用配置项 down-after-milliseconds * 10
:
down-after-milliseconds
:表示从库断连的最大连接超时时间10
:发送断连的次数超过 10 次,说明这个从库的网络状况不好
打分
打分,可以按照三个规则进行三轮打分:
- 从库优先级
- 从库复制进度
- 从库
ID
号
第一轮:优先级最高的从库
用户可以通过 slave-priority
配置项,给不同从库设置不同优先级。
一般根据从库所在机子的配置,设置相应的权重:
- 如果一个从库的优先级最高,则它就是新主库了
- 如果从库优先级都一致,则进行第二轮打分
第二轮:和旧主库同步程度最接近
参数标准:
master_repl_offset
:主库记录当前的最新写操作在repl_backlog_buffer
中的位置slave_repl_offset
:从库记录当前的复制进度
根据以上两个参数,就可以判断从库和旧主库间的同步进度。
slave_repl_offset
越接近master_repl_offset
,得分就越高,会被选为新主库。实际上,比较的还是
slave_repl_offset
,因为旧主库宕机了,拿不到master_repl_offset
。
master_repl_offset
会单调递增。
举个栗子:
- 旧主库:
master_repl_offset
是 1000 - 从库 1、2和3的
slave_repl_offset
:950、990 和 900 - 则从库2 会被选为新主库
如果从库的 slave_reple_offset
值大小是一样的,就需要进行第三轮打分了。
第三轮:ID
号小的从库得分高
到了决赛圈了,每个从库的 ID
号一定不同的。
Redis
在选主库时,有个默认的规定:在优先级和复制进度都相同的情况下,ID
号最小的从库得分最高,会被选为新主库。
本文转载自: 掘金