Redis 的主从复制、哨兵模式、集群脑裂

主从复制

主从复制是 Redis 高可用服务最基础的保证,将一台 Redis 主服务器,同步数据到多台 Redis 从服务器上,即一主多从的模式,且主从服务器之间采用的是「读写分离」的方式。

主服务器可以进行读写操作,当发生写操作时,自动将写操作同步给从服务器,而从服务器一般是只读,并接收主服务器同步过来的写操作命令,然后执行这条命令。

在这里插入图片描述

我们可以使用 replicaof(Redis 5.0 之前使用 slaveof)命令形成主服务器和从服务器的关系。

// 服务器B执行这条命令
replicaof <服务器A的IP地址> <服务器A的Redis端口号>

主从复制共有三种模式:全量复制、基于长连接的命令传播、增量复制。

主从服务器第一次同步的时候,就是采用全量复制,此时主服务器会两个耗时的地方,分别是生成 RDB 文件和传输 RDB 文件。

  1. 建立连接、协商同步。给全量复制做准备
  2. 主服务器同步数据给从服务器。主服务器会执行 bgsave 命令来生成 RDB 文件,然后把文件发送给从服务器。从服务器收到 RDB 文件后,会先清空当前的数据,然后载入 RDB 文件
  3. 主服务器发送新的写操作命令给从服务器。为了保证主从服务器的数据一致性,主服务器将 bgsave 期间收到的写操作命令,写入到 replication buffer 缓冲区里。在主服务器生成的 RDB 文件发送完,从服务器完成 RDB 文件的载入后,会回复一个确认消息给主服务器。接着,主服务器将 replication buffer 缓冲区里所记录的写操作命令发送给从服务器,从服务器执行命令,这时主从服务器的数据就一致了

为了避免过多的从服务器和主服务器进行全量复制,可以把一部分从服务器升级为「经理角色」,让它也有自己的从服务器,分摊主服务器的压力。

在「从服务器」上执行下面这条命令,使其作为目标服务器的从服务器。如果目标服务器本身也是「从服务器」,那么该目标服务器就会成为「经理角色」,不仅可以接收主服务器同步的数据,也会把数据同步给自己旗下的从服务器,从而减轻主服务器的负担。

replicaof <目标服务器的IP> 6379

第一次同步完成后,主从服务器会维护着一个长连接,主服务器在接收到写操作命令后,会通过这个连接将写命令传播给从服务器,来保证主从服务器的数据一致性。

如果遇到网络异常中断,导致无法进行命令传播时,就利用 repl_backlog_size 缓冲区进行增量复制,实现主从服务器的数据一致性。

哨兵模式

在使用 Redis 主从服务时,当 Redis 的主从服务器出现故障宕机,需要进行手动恢复。

为了解决这个问题,Redis 增加了哨兵模式(Redis Sentinel),哨兵模式做到了可以监控主从服务器,并且提供主从节点故障转移的功能。

在这里插入图片描述

如果主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令,哨兵就会将它们标记为「主观下线」。这个「规定的时间」是由配置项 down-after-milliseconds 参数设定的,单位是毫秒。

同时针对「主节点」,设计「主观下线」和「客观下线」两个状态,客观下线只适用于主节点。因为有可能「主节点」其实并没有故障,只是因为主节点的系统压力比较大或者网络拥塞,导致主节点没有在规定时间内响应哨兵的 PING 命令。

所以,为了减少误判,哨兵在部署时会用多个节点部署成哨兵集群(最少需要三台机器来部署哨兵集群),通过多个哨兵节点一起判断,就可以避免因为单个哨兵自身网络状况不好,导致误判主节点下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

当一个哨兵判断主节点「主观下线」后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。

在这里插入图片描述

当这个哨兵的赞同票数达到配置文件中的 quorum 配置项设定的值后,主节点就会被该哨兵标记为「客观下线」。

哨兵判断完主节点客观下线后,就要开始在多个「从节点」中,选出一个从节点来做新主节点。这时候,还需要在哨兵集群中选出一个 leader,让 leader 来执行主从切换。

选举 leader 的过程其实也是一个投票的过程,在投票开始前,是哪个哨兵节点判断主节点为「客观下线」,这个哨兵节点就是候选者,所谓的候选者,就是想当 leader 的哨兵。

候选者会向其他哨兵发送命令,表明希望成为 leader 来执行主从切换,并让其他哨兵对它进行投票。每个哨兵只有一次投票机会,如果用完就不能再参与投票了,可以投给自己或投给别人,但是只有候选者才能把票投给自己。

举例来说,假设哨兵节点有 3 个,quorum 设置为 2,那么任何一个想成为 leader 的哨兵只要拿到 2 张赞成票,就可以选举成功了。如果没有满足条件,就需要重新进行选举。

选举出哨兵 leader 后,就可以进行主从故障转移的过程了。

  1. 在已下线的主节点(旧主节点)下属的所有「从节点」里,挑选出一个从节点,并将其转换为主节点(根据节点的优先级、复制进度、ID 号,尽可能让数据最全的节点成为新主节点)
  2. 让已下线的主节点下属的所有「从节点」修改复制目标,修改为复制「新主节点」
  3. 将新主节点的 IP 地址和信息,通过「发布/订阅机制」通知给客户端
  4. 继续监视旧主节点,等这个旧主节点重新上线时,将它设置为新主节点的从节点

集群脑裂

在 Redis 主从架构中,假设主节点网络突然发生了问题,它与所有的从节点都失联了,但是和客户端的网络还是正常的。客户端并不知道 Redis 内部已经出现了问题,继续向主节点写数据,因为主从节点之间的网络问题,这些数据始终无法同步给从节点。

这时,哨兵也发现主节点失联,它就认为主节点挂了(但实际上主节点还是正常运行,只是网络出问题了),于是哨兵就会在「从节点」中选举出一个新主节点,这时集群就有两个主节点了 —— 脑裂出现了(相当于出现了两个大脑)。

过了一会,主节点网络突然好了,重新上线时,因为哨兵之前已经选举出了一个新主节点,就会把旧主节点降级为从节点,然后从节点会向新主节点请求数据同步。

因为第一次同步是全量同步,从节点会清空本地的数据,再做全量同步。所以,之前客户端写入的数据就会丢失。

简单来说,由于网络问题,集群节点之间失去联系,主从数据不同步,哨兵重新平衡选举后产生两个主服务。等网络恢复后,旧主节点会降级为从节点,再与新主节点进行同步复制时,由于从节点会清空自己的缓冲区,导致之前客户端写入的数据丢失。

解决方案

当主节点发现从节点下线或者通信超时的总数量达到阈值时,禁止写数据,直接返回错误给客户端。

在 Redis 配置文件中,有两个参数可以设置。

  • min-slaves-to-write x,主节点必须要有至少 x 个从节点连接,如果小于这个数,主节点就会禁止写数据
  • min-slaves-max-lag x,主从数据复制和同步的延迟不能超过 x 秒,如果超过,主节点就会禁止写数据

可以把这两个配置项搭配起来使用,分别给它们设置一定的阈值,假设为 N 和 T。即主库连接的从库中至少有 N 个从库,且和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则主库就不会再接收客户端的写请求了。

等到选举出新主库时,只有新主库能接收和处理客户端请求,此时新写的数据会直接写到新主库中。而原主库会被哨兵降为从库,即使它的数据被清空了,也不会有数据丢失的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值