Redis高可用方案


目录

问题

解决方案

1、主从同步

2、哨兵模式

3、集群模式

方案选型


问题

Redis单机部署时,可能因为机器宕机导致整个缓存不可用,此时就需要实现Redis的高可用,那么Redis的高可用方案有哪些呢?

解决方案

1、主从同步

整体流程:从节点与主节点建立主从关系,主节点全量同步信息至从节点,同步完成后,将增量数据同步至从节点

零、相关数据结构

  1. runId:每个redis节点启动都会生成唯一的uuid,每次redis重启后,runId都会发生变化。
  2. offset:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。
  3. repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是1MB。
  4. 从节点发送psync[runId][offset]命令,主节点有三种响应:
  • FULLRESYNC:第一次连接,进行全量复制
  • CONTINUE:进行部分复制
  • ERR:不支持psync命令,进行全量复制

一、主从关系建立

  1. 从节点执行slaveof[masterIP][masterPort],保存主节点信息
  2. 从节点中的定时任务发现主节点信息,建立和主节点的socket连接
  3. 从节点发送Ping信号,主节点返回Pong,两边能互相通信

二、第一次全量同步

  1. 连接建立后,从节点发送 psync ?-1 命令(因为第一次发送,不知道主节点runld所以为?,因为是第一次复制,所以offset=-1)。主节点发现从节点是第一次复制,返回 FULLRESYNC { runld } { offset },runld 是主节点的 runld , offset 是主节点目前的 offset
  2. 从节点接收主节点信息后,保存到 info 中
  3. 主节点在发送 FULLRESYNC 后,启动 bgsave 命令,生成 RDB 文件,生成后将 RDB 文件发送给从节点
  4. 主节点发送 RDB 文件给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中
  5. 从节点清理自己的数据库数据,然后加载 RDB 文件,将数据存到自己的数据库中(如果从节点开启了 AOF,从节点会异步重写 AOF 文件)
  6. 主节点把当前缓冲区的写命令同步给从节点后,便完成了全量同步的过程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性,同时还会将写命令写入复制积压缓冲区,用于增量同步。

三、增量同步

  1. 当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点将积压缓冲区数据直接发送给从节点,这样就可以保持主从节点复制的一致性.补发的这部分数据一般远远小于全量数据
  2. 主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内的复制积压缓冲区依然可以保存最近一段时间的写命令数据
  3. 当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID,因此会把它们当做 psync 参数发送给主节点,要求进行部分复制
  4. 主节点接收到 psync 命令后首先核对参数 runld 是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset 在复制积压缓冲区中查找,如果offset 之后的数据存在,则对从节点发送+ COUTINUE命令,表示可以进行部分复制。因为缓冲区大小固定,若发生缓冲溢出,则进行全量复制。
  5. 主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态

2、哨兵模式

主从模式存在一个缺点,一旦主节点宕机,需要人工修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点。这就需要哨兵模式来帮我们自动完成主从切换。

整体流程:哨兵对所有实例进行监听,在需要切换主库时,会在 Sentinel 集群中选举出一个 Sentinel 节点,该 Sentinel 节点会从剩余的从节点中根据策略挑选出一个节点,将它作为主节点,并和其他从节点建立主从联系

一、健康检测

哨兵进程启动运行时,周期性给所有主、从库发送 PING 命令,检测他们是否仍然在线运行。

主库、从库没有在规定时间内响应哨兵的 PING 命令,该哨兵就会把它标记为“主观下线”;

哨兵会询问其他哨兵,当超过一半的哨兵实例判断主库都已经“主观下线” , 主库会被标记“客观下线”;客观下线只适用于主库。

因集群网络压力较大,网络拥塞,哨兵误认为主库下线,易产生脑裂问题

通过引入哨兵集群,集群同时不稳定的概率较小,一起决策降低误判率

二、选举 Sentinel 节点

故障转移并不是所有的 sentinel 共同完成,而是选举出一台 sentinel 节点作为领导者来完成这次故障转移,所以当主服务器被标记为客观下线时,sentinel 之间就会通过 Raft 算法选举出一个领导者来完成故障转移工作。redis 选举领头的 sentinel 的规则和方法大致如下:

  • 所有在线的 sentinel 都有资格被选为领导者,也就是说每个 sentinel 都有成为领导者的机会
  • 当 sentinel 标记主服务器为主观下线时,会向其他 Sentinel 节点发送 sentinel is-master-down-by-addr 命令, 要求将自己设置为领导者
  • 收到命令的 Sentinel 节点,采用先到先得的规则,如果没有同意过其他 Sentinel 节点的 sentinel is-master-down-by-addr 命令,将同意该请求,否则拒绝
  • 如果该 Sentinel 节点发现自己的票数已经超过半数,那么它将成为领导者
  • 如果在规定时间内,没有选举出 sentinel 领导者,那么将在一段时间后再次选举,直到选出 sentinel 领导者为止。

三、故障转移

选举出来的 sentinel 领导者将完成故障转移工作,故障转移主要有以下三步

  1. 根据选主策略从剩余的从节点中挑选出一个节点
  2. 剩余的从节点与新的主节点建立主从联系,进行数据复制
  3. 将旧的主节点变为从节点

四、选主策略

  1. 过滤网络状态不好的节点( down-after-milliseconds是我们认定主从库断连的最大连接超时时间。断连次数超过 10 次,说明从库网络状态不好)
  2. 优先级高的作为主库( slave-priority 配置项),如优先级一致,则进入 3
  3. 同步程度最高的作为主库(从库的 slave_repl_offset 最接近旧主库的 master_repl_offset ) ,如同步程度一致,则进入 4
  4. ID最小的作为主库(实例在创建时候都会有一个ID)

3、集群模式

主从和哨兵解决了单个Redis的高可用,但无法解决单节点下内存不足和高并发写操作的资源问题,所以Redis提供了一种集群模式,将Redis进行水平扩展,实现分布式存储

整体流程:Redis 内部设置了16383个槽位,每个槽位对应一部分数据,当有存取操作时,Redis先对 key 使用 crc16 算法算出一个整数结果,然后把结果对 16384 求余数,得到的结果便是该记录所存放的槽位,集群节点则平均的负责相应槽位数据的存取。

一、数据分片

Redis 内部设置了16383个槽位,每个槽位对应一部分数据,当有存取操作时,Redis先对 key 使用 crc16 算法算出一个整数结果,然后把结果对 16384 求余数,得到的结果便是该记录所存放的槽位。

集群中的每个节点都会将自己负责的槽位通过消息发送给其他节点,其他节点则会将槽位信息存储起来,因此,集群中的每个节点都会知道16384个槽位分别被指派给哪些节点。

当某个节点接收到客户端发起的存取操作,计算出其所属槽位后,如是自己负责的槽位,则直接执行该命令,否则返回一个MOVED错误,指引客户端重定向至正确的节点,并再次发送想要执行的命令

二、集群高可用

集群有多个主节点负责槽位,为了集群的高可用,每个主节点下也可以有对应的从节点。当某个主节点不可用时,其下的从节点会向其他节点发起请求,尝试成为新的主节点

三、增删节点

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐