Redis哨兵Sentinel模式快速入门

9次阅读

共计 3346 个字符,预计需要花费 9 分钟才能阅读完成。

更多内容,欢迎关注微信公众号:全菜工程师小辉。公众号回复关键词,领取免费学习资料。

当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。所以更多时候,我们优先考虑哨兵(sentinel) 模式。

Redis sentinel 是 Redis 高可用实现方案:故障发现、故障自动转移、配置中心、客户端通知。从 Redis 的 2.6 版本开始提供的,但是当时这个版本的模式是不稳定的,直到 Redis 的 2.8 版本以后,这个哨兵模式才稳定下来,在生产环境中,如果想要使用 Redis 的哨兵模式,也会尽量使用 Redis 的 2.8 版本之后的版本。

哨兵虽然有一个单独的可执行文件 Redis-sentinel,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵,哨兵的一些设计思路和 zookeeper 非常类似。

sentinel 的定时任务

sentinel 机制中有三种重要的定时任务。

  1. 每 10 秒每个 sentinel 对 master 和 slave 执行 info

作用:

  • 发现 slave 节点。
  • 确认主从关系。
  1. 每 2 秒每个 sentinel 通过 master 节点的 channel 交换信息(pub/sub)

作用:

  • 互相通信掌握节点的信息和自身信息,可以感知新加入的 sentinel

通过 master 节点的__sentinel__:hello 频道进行交互,所有 sentinel 订阅这个频道并每 2 秒向该频道发布信息

  1. 每 1 秒每个 sentinel 对其他 sentinel 和 master,slave 进行 ping

作用:

  • 心跳检测

主观下线和客观下线

主观下线

主观下线:单个 sentinel 节点对 Redis 节点通信失败的“偏见”。

这是一种主观下线。因为在复杂的网络环境下,这个 sentinel 与这个 master 不通,但是如果 master 与其他的 sentinel 都是通的呢?所以是一种“偏见”。

这是依靠的第三种定时:每秒去 ping 一下周围的 sentinel 和 Redis。对于 slave Redis, 可以使用这个主观下线,因为他不需要进行故障转移;但是对于 master Redis,必须使用客观下线。

客观下线

客观下线:所有 sentinel 节点对 master Redis 节点失败“达成共识”(超过 quorum 个则统一,quorum 可配置)。

这是依靠的第二种定时:每两秒,sentinel 之间进行“商量”(一个 sentinel 可以通过向另一个 sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)

对于 master redis 的下线,必须要达成共识才可以,因为涉及故障转移,仅仅依靠一个 sentinel 判断是不够的

领导者选举

当 sentinel 集群需要故障转移的时候会在集群中选出 Leader 执行故障转移操作。sentinel 采用了 Raft 协议实现了 sentinel 间选举 Leader 的算法,不过也不完全跟论文描述的步骤一致。sentinel 集群运行过程中故障转移完成,所有 sentinel 又会恢复平等。Leader 仅仅是故障转移操作出现的角色。

选举流程

  1. 某个 sentinel 认定 master 客观下线的节点后,该 sentinel 会先看看自己有没有投过票,如果自己已经投过票给其他 sentinel 了,在 2 倍故障转移的超时时间自己就不会成为 Leader。相当于它是一个 Follower。
  2. 如果该 sentinel 还没投过票,那么它就成为 Candidate。
  3. 和 Raft 协议描述的一样,成为 Candidate,sentinel 需要完成几件事情

3.1 更新故障转移状态为 start
3.2 当前 epoch 加 1,相当于进入一个新 term,在 sentinel 中 epoch 就是 Raft 协议中的 term。
3.3 更新自己的超时时间为当前时间随机加上一段时间,随机时间为 1s 内的随机毫秒数。
3.4 向其他节点发送 is-master-down-by-addr 命令请求投票。命令会带上自己的 epoch。
3.5 给自己投一票,在 sentinel 中,投票的方式是把自己 master 结构体里的 leader 和 leader_epoch 改成投给的 sentinel 和它的 epoch。

  1. 其他 sentinel 会收到 Candidate 的 is-master-down-by-addr 命令。如果 sentinel 当前 epoch 和 Candidate 传给他的 epoch 一样,说明他已经把自己 master 结构体里的 leader 和 leader_epoch 改成其他 Candidate,相当于把票投给了其他 Candidate。投过票给别的 sentinel 后,在当前 epoch 内自己就只能成为 Follower。
  2. Candidate 会不断的统计自己的票数,直到他发现认同他成为 Leader 的票数超过一半而且超过它配置的 quorum(quorum 可以参考《redis sentinel 设计与实现》)。sentinel 比 Raft 协议增加了 quorum,这样一个 sentinel 能否当选 Leader 还取决于它配置的 quorum。
  3. 如果在一个选举时间内,Candidate 没有获得超过一半且超过它配置的 quorum 的票数,自己的这次选举就失败了。
  4. 如果在一个 epoch 内,没有一个 Candidate 获得更多的票数。那么等待超过 2 倍故障转移的超时时间后,Candidate 增加 epoch 重新投票。
  5. 如果某个 Candidate 获得超过一半且超过它配置的 quorum 的票数,那么它就成为了 Leader。
  6. 与 Raft 协议不同,Leader 并不会把自己成为 Leader 的消息发给其他 sentinel。其他 sentinel 等待 Leader 从 slave 选出 master 后,检测到新的 master 正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程。

故障转移过程

  1. 当多个 sentinel 发现并确认了 master 有问题
  2. 接着会选举出一个 sentinel 作为领导
  3. 再选举出一个 slave 作为 master
  4. 通知其余的 slave,新的 master 是谁
  5. 通知客户端一个主从的变化
  6. 最后,sentinel 会等待旧的 master 复活,然后将新 master 成为 slave

那么,如何选择“合适”的 slave 节点呢?

  1. 选择 slave-priority(slave 节点优先级,人为配置)最高的 slave 节点,如果存在则返回,不存在则继续。
  2. 其次会选择复制偏移量最大的 slave 节点(复制得最完整),如果存在则返回,不存在则继续
  3. 最后会选择 run_id 最小的 slave 节点(启动最早的节点)

客户端实现高可用的基本原理

故障转移后客户端无法感知将无法保证正常的使用。所以,实现客户端高可用的步骤如下:

  1. 客户端获取 sentinel 节点集合

  1. 客户端通过 sentinel get-master-addr-by-name master-name 这个 api 来获取对应主节点信息

  1. 客户端验证当前获取的“主节点”是真正的主节点,这样的目的是为了防止故障转移期间主节点的变化

  1. 客户端保持和 sentinel 节点集合的联系,即订阅 sentinel 节点相关频道,时刻获取关于主节点的相关信息

从上面的模型可以看出,Redis sentinel 客户端只有在初始化和切换主节点时需要和 sentinel 进行通信来获取主节点信息,所以在设计客户端时需要将 sentinel 节点集合考虑成配置(相关节点信息和变化)发现服务。

需要说明的问题

  • 尽可能在不同物理机上和同一个网络部署 Redis sentinel 的所有节点
  • Redis sentinel 中的 sentinel 节点个数应该大于等于 3 且最好是奇数。(节点数多可以保证高可用)
  • Redis sentinel 中的数据节点和普通数据节点没有区别。每个 sentinel 节点在本质上还是一个 Redis 实例,只不过和 Redis 数据节点不同的是,其主要作用是监控 Redis 数据节点
  • 客户端初始化时连接的是 sentinel 节点集合,不再是具体的 Redis 节点,但 sentinel 只是配置中心不是代理。

更多内容,欢迎关注微信公众号:全菜工程师小辉。公众号回复关键词,领取免费学习资料。

正文完
 0