Redis 「9」主从、高可用性方案

230 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

01-主从复制

主从复制是一种数据冗余方式,主要用来保存数据。在此基础上,可以实现故障恢复、读写分离、高可用。

Redis 中主从复制分为两类:1)全量复制;2)增量复制

01.1-全量复制

全量复制分为两个阶段:同步阶段(1-3)和命令传播阶段(4)。

  1. 从机向主机发送SYNC命令。
  2. 主机启动 BGSAVE 子进程,生成 RDB 文件,并将其发送给从机。
  3. 从机根据收到的 RDB 文件,恢复数据库状态。
  4. 主机将SYNC命令之后的所有写命令(记录在缓冲区中)传播到从机,从机根据这些命令更新自己的数据库状态。

仔细思考下上面的过程,全量复制存在两个问题:

  • 从机会根据主机发送过来的 RDB 文件恢复数据库状态,也就是说,它会丢掉自己成为某个主机的从机之前的数据库状态。而且,不管是首次同步,还是断线重连后的同步,全量复制都是重复上述1-4步骤。
  • 存在主从数据不一致的可能。或者换句话说,在某个事件段内,主从机数据可能不一致。

01.2-增量复制

为解决断线重连后全量复制的问题,Redis 2.8 引入了增量复制命令PSYNC,分为两种模式:完整重同步和部分重同步(主要解决重连后的同步问题)。

完整重同步与前节中的全量复制过程类似。

部分重同步的实现依赖于以下三部分:

  1. 复制偏移量。主从服务器都保存有一个 offset,通过其可判断主从数据库状态是否一致。
  2. 复制积压缓冲区。是一个固定长度的 FIFO 队列,每个字节都对应一个 offset。如果从服务器的 offset 与主服务器的 offset 不一致,且从服务器的 offset 在 FIFO 队列中,则部分重同步(内容为 FIFO 队列中未同步到从服务器的部分);否则,完整重同步。
  3. 服务器运行 ID。主从服务器都保存这一个 ID,标识自己。断线重连后,从服务器向当前主服务器发送其之前保存的主服务器 ID,若当前主服务器发现 ID并非自己的,说明是首次连接,则进行完成重同步;否则,根据步骤2决定同步的内容。

01.3-PSYNC 实现

下图以从服务器角度,展示了其使用SLAVEOF命令后,同步的基本过程:

Untitled.png

02-高可用方案

Sentinel 是 Redis 开箱即用的一种高可用方案,由一个或多个(通常是多个)Sentinel 实例组成,可监视任意多个主服务器及它们的从服务器。Sentinel 可以提供:

  • 监视服务,监视主服务器的状态,并在主服务器故障时,提供故障切换功能。
  • 故障切换(高可用性),主服务器发生故障时,在从服务器中选举新的主服务器。
  • 配置服务,客户端通过连接哨兵,获得当前主服务器的地址信息。
  • 通知服务,将故障转移的结果发送给客户端。

更多关于 Sentinel 的信息,请参考[1].

接下来将分享一个基于 keepalived + 主从复制的高可用性方案。在两台机器上安装 keepalived 软件,根据配置,会生成一个虚拟 IP,在应用程序中只需要配置其虚拟 IP即可,对应用配置负担最小。

在 /etc/keepalived/keepalived.conf 中,定义 vrrp_instance 和 vrrp_script:

vrrp_instance redis {
	virtrual_ipaddress {
		172.17.196.253/24
	}
	virtual_script {
		check_redis
	}
	notify_master ""   // 指定变主时的脚本,将当前 redis 设置为主机
	notify_backup ""   
	notify_fault  ""
}
vrrp_script check_redis {
	script "" // 指定检查脚本
}

notify_master: specify a shell script to be executed during transition to master state notify_backup: specify a shell script to be executed during transition to backup state notify_fault: specify a shell script to be executed during transition to fault state

更多实现相关的信息,可以查参考[2]

[1] Redis进阶 - 高可用:哨兵机制(Redis Sentinel)详解

[2] redis+Keepalived实现Redis高可用性


历史文章

Redis 「8」实现分布式限流与延时队列

Redis 「7」实现分布式锁

Redis 「6」实现消息队列

Redis 「5」事件处理模型与键过期策略

Redis 「4」Redis 在秒杀系统中的应用

Redis 「3」持久化

Redis 「2」缓存一致性与异常处理

Redis 「1」流水线、事务、Lua 脚本