目录
高可用有两个含义:一是数据尽量不丢失,二是服务尽可能提供服务。
主从复制概述
一台宕机了无法提供服务,那多台呢?是不是就可以解决了。Redis 提供了主从模式,通过主从复制,将数据冗余一份复制到其他 Redis 服务器。
前者称为主节点 (master),后者称为从节点 (slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台 Redis 服务器都是主节点;且一个主节点可以有多个从节点 (或没有从节点),但一个从节点只能有一个主节点。
为了保证副本数据的一致性,主从架构采用了读写分离的方式。
读操作:主、从库都可以执行;
写操作:主库先执行,之后将写操作同步到从库;
我们可以假设主从库都可以执行写指令,假如对同一份数据分别修改了多次,每次修改发送到不同的主从实例上,就导致是实例的副本数据不一致了。
如果为了保证数据一致,Redis 需要加锁,协调多个实例的修改,Redis 自然不会这么干!
主从复制的其他作用
- 故障恢复:当主节点宕机,其他节点依然可以提供服务;
- 负载均衡:Master 节点提供写服务,Slave 节点提供读服务,分担压力;
- 高可用基石:是哨兵和 cluster 实施的基础,是高可用的基石。
搭建主从复制
主从复制的开启,完全是在从节点发起的,不需要我们在主节点做任何事情。
可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系。
在从节点开启主从复制,有 3 种方式:
配置文件
在从服务器的配置文件中加入 replicaof <masterip> <masterport>
启动命令
redis-server 启动命令后面加入 --replicaof <masterip> <masterport>
客户端命令
启动多个 Redis 实例后,直接通过客户端执行命令:replicaof <masterip> <masterport>,则该 Redis 实例成为从节点。
比如假设现在有实例 1(172.16.88.1)、实例 2(172.16.88.2)和实例 3 (172.16.88.3),在实例 2 和实例 3 上分别执行以下命令,实例 2 和 实例 3 就成为了实例 1 的从库,实例 1 成为 Master。
replicaof 192.168.1.20 6379
主从复制原理
主从库模式一旦采用了读写分离,所有数据的写操作只会在主库上进行,不用协调三个实例。
主库有了最新的数据后,会同步给从库,这样,主从库的数据就是一致的。
- 第一次主从库全量复制;
- 主从正常运行期间的同步;
- 主从库间网络断开重连同步。
主从库——全量复制
主从库第一次复制过程大体可以分为 3 个阶段:连接建立阶段(即准备阶段)、主库同步数据到从库阶段、发送同步期间新写命令到从库阶段;
直接上图,从整体上有一个全局观的感知,后面具体介绍。
第一阶段:建立连接
该阶段的主要作用是在主从节点之间建立连接,为数据全量同步做好准备。从库会和主库建立连接,从库执行 replicaof 并发送 psync 命令并告诉主库即将进行同步,主库确认回复后,主从库间就开始同步了。
在从节点的配置文件中的 replicaof 配置项中配置了主节点的 IP 和 port 后,从节点就知道自己要和那个主节点进行连接了。
从节点内部维护了两个字段,masterhost 和 masterport,用于存储主节点的 IP 和 port 信息。
从库执行 replicaof 并发送 psync 命令,表示要执行数据同步,主库收到命令后根据参数启动复制。命令包含了主库的 runID 和 复制进度 offset 两个参数。
runID:每个 Redis 实例启动都会自动生成一个 唯一标识 ID,第一次主从复制,还不知道主库 runID,参数设置为 「?」。
offset:第一次复制设置为 -1,表示第一次复制,记录复制进度偏移量。
主库收到 psync 命令后,会用 FULLRESYNC 响应命令带上两个参数:主库 runID 和主库目前的复制进度 offset,返回给从库。从库收到响应后,会记录下这两个参数。
FULLRESYNC 响应表示第一次复制采用的全量复制,也就是说,主库会把当前所有的数据都复制给从库。
第二阶段:主库同步数据给从库
master 执行 bgsave命令生成 RDB 文件,并将文件发送给从库,同时主库为每一个 slave 开辟一块 replication buffer 缓冲区记录从生成 RDB 文件开始收到的所有写命令。
从库收到 RDB 文件后保存到磁盘,并清空当前数据库的数据,再加载 RDB 文件数据到内存中。
第三阶段:发送新写命令到从库
从节点加载 RDB 完成后,主节点将 replication buffer 缓冲区的数据发送到从节点,Slave 接收并执行,从节点同步至主节点相同的状态。
希望能对大家有所帮助。