Redis 哨兵集群

什么是哨兵?

我们知道,在主从集群的基础上,如果主机宕机的话,我们就得要手动去将从机升级为主机,使系统正常运行。而哨兵就是为了代替我们人的存在,它也是一个独立的进程,不做任何具体的业务,只是来监视主从机的运行状况,并在出现故障时自动处理。

为什么要有哨兵集群呢?

一个哨兵的情况下,如果哨兵和主机都挂了,那么整个系统就不可用了。为了系统更加高可用,避免出现哨兵宕机,主节点同时宕机而使系统崩溃的情况。

哨兵是怎么工作的?

  • 每个哨兵都会定时向它所知的 master,slave 以及其他的哨兵发送一条 ping 命令;
  • 每个节点收到 ping 命令后都会回复 pong;
  • 如果一个节点距离最后一次回复 pong 的时间超过了 down-after-milliseconds 所规定的值,那么这个实例就会被当前的哨兵标记为主观下线;
  • 如果一个 master 被标记为主观下线,则哨兵就会以更加短的时间发送信息给 master 以确保真正下线;
  • 当有了足够数量的哨兵在指定的时间范围内确认 master 的确进入了主观下线状态,则 master 就会转为客观下线状态;
  • 当 Master 被所有哨兵标记为客观下线,哨兵向所有的 Slave 发送 INFO 命令,重新选举新的 master;
  • 如果没有足够数量的哨兵同意 master 已下线,并且 master 重新向哨兵发送 ping 回复命令,master 的主观下线状态就会被移除。

优点:

  • 哨兵集群部署简单;
  • 能够解决 redis 主从模式下的高可用切换问题;
  • 方便实现 redis 数据节点的线性扩展,轻松突破 reids 单线程瓶颈;

缺点:

  • 相对于主从模式要更复杂;
  • 开启进程会消耗一定的资源;
  • 哨兵主要针对 redis 主节点的高可用切换,对 redis 的数据节点做失败判断,分为主观下线和客观线性,并不执行故障转移;

Redis 是如何选举主节点的?

Redis 选举主节点需要两个步骤,第一个步从哨兵节点中选择一个 Leader,第二步是让这个 leader 在执行故障转移操作。

  1. 选举 Leader:

    • 哨兵发现 master 节点下线,便把他标记为主观下线,并通知其他节点也对此 master 进行检查。
    • 哨兵多次判断此 master 为主观下线后,就向其他哨兵广播一条信息,请求同意自己作为 Leader。其他节点收到信息后,如果在此之前没有发送过同意,就能够发送同意(即每个哨兵只能同意一个节点)。
    • 当某个节点收到的同意数量超过一半时,就升级为 leader,否则再进行一轮选举。(这种选举算法为 Raft 算法)
  2. 故障转移

    • Leader 选举完成后就执行故障转移操作:每个 slave 节点都将自己的优先级,offest,runid 发送给 Leader,Leader 根据这三者的顺序选举出最大的节点,将其升级为 master 节点。

具体实践

在配置好主从的情况下,配置哨兵节点:

// sentinel.conf
sentinel monitor 主机名称 主机ip 主机端口 监听个数
sentinel auth-pass 主机名称 主机密码

虽然我们在 sentinel 的配置文件中只配置了主节点,没有配置从节点,但哨兵会去主节点中获取从节点的信息,从而实现整个 Redis 的监控。

为什么哨兵集群必须部署两个以上的节点呢?

假设只有两个哨兵节点,如果 Master 和哨兵1 都宕机了,此时哨兵2知道 Master 宕机,对其进行主观下线,并且想升级为 Leader,但没有其他节点响应,所以 Master 就一直不被切换。

在哨兵模式下,还会不会出现数据丢失的问题?

哨兵只是为了保证在 Master 挂掉的时候能快速选举出新的 Master,从而保证服务的高可用;并不会处理数据同步间出现的问题。

数据丢失主要有两方面:

  1. 异步复制导致数据丢失:由于 Master -> Slave 的复制是异步的,如果 Master 还没复制数据到 Slave 就宕机了,并且哨兵把 Slave 选举为 Master,那么这部分数据就丢失了。
  2. 脑裂导致数据丢失:当某个 Master 突然脱离了正常网络(不是宕机,可能是部分网络瘫痪),并且哨兵集群认为它宕机了,重新选举 Master。但这个时候旧 Master 还能顺利的接收客户端发送的数据,而哨兵此时维护新 Master。当旧 Master 网络回复后,则会同步新 Master 的数据,导致数据丢失。

脑裂的解决方法:通过配置文件设置如果 Master 和 Slave 节点超过一定的时间无法联系,则 Master 拒绝写请求。

有什么方式可以实现数据一致呢?

由 CAP 理论得知,一致性和可用性并不能同时成立。为了达到数据的强一致性,我们必须先暂停下服务,等数据同步完再开启服务。以 RedLock (获取分布式锁)为例:一开始有 5 台 Master 节点(都是作为主节点),每当要获取锁时,需要通过轮询的方式从 5 台 Master 节点中获取锁(短暂的服务停顿,等数据同步),保证超过 1/2 的节点都能获取锁后才能继续执行,否则就会超时,获取锁失败。

updatedupdated2022-06-232022-06-23