作者:微信小助手
发布时间:2018-09-18T00:26:51
在前面的两篇文章中,分别介绍了 Redis 的内存模型和 Redis 的持久化,今天我们来深入学习 Redis 的主从复制。
在 Redis 的持久化中曾提到,Redis 高可用的方案包括持久化、主从复制(及读写分离)、哨兵和集群。
其中持久化侧重解决的是 Redis 数据的单机备份问题(从内存到硬盘的备份);而主从复制则侧重解决数据的多机热备。此外,主从复制还可以实现负载均衡和故障恢复。
我将从以下几个部分详细介绍 Redis 主从复制的方方面面:
主从复制概述
如何使用主从复制
主从复制的实现原理
应用中的问题
总结
主从复制概述
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台 Redis 服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制的作用主要包括:
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是 Redis 高可用的基础。
如何使用主从复制
为了更直观的理解主从复制,在介绍其内部原理之前,先说明我们需要如何操作才能开启主从复制。
建立复制
需要注意,主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。
从节点开启主从复制,有 3 种方式:
在从服务器的配置文件中加入:slaveof <masterip> <masterport>。
redis-server 启动命令后加入 --slaveof <masterip> <masterport>。
Redis 服务器启动后,直接通过客户端执行命令:slaveof <masterip> <masterport>,则该 Redis 实例成为从节点。
上述 3 种方式是等效的,下面以客户端命令的方式为例,看一下当执行了 slaveof 后,Redis 主节点和从节点的变化。
实例
准备工作:启动两个节点。为了方便起见,实验所使用的主从节点是在一台机器上的不同 Redis 实例。
其中主节点监听 6379 端口,从节点监听 6380 端口;从节点监听的端口号可以在配置文件中修改:
启动后可以看到:
两个 Redis 节点启动后(分别称为6379节点和6380节点),默认都是主节点。
建立复制:此时在 6380 节点执行 slaveof 命令,使之变为从节点。
观察效果:下面验证一下,在主从复制建立后,主节点的数据会复制到从节点中。
首先在从节点查询一个不存在的 key:
然后在主节点中增加这个 key:
此时在从节点中再次查询这个 key,会发现主节点的操作已经同步至从节点:
然后在主节点删除这个 key:
此时在从节点中再次查询这个 key,会发现主节点的操作已经同步至从节点:
断开复制
通过 slaveof <masterip> <masterport> 命令建立主从复制关系以后,可以通过 slaveof no one 断开。
需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。
从节点执行 slaveof no one 后,打印日志如下图所示;可以看出断开复制后,从节点又变回为主节点。
主节点打印日志如下:
主从复制的实现原理
上面一节中,我们介绍了如何操作可以建立主从关系;本小节将介绍主从复制的实现原理。
主从复制过程大体可以分为 3 个阶段:
连接建立阶段(即准备阶段)
数据同步阶段
命令传播阶段
连接建立阶段
该阶段的主要作用是在主从节点之间建立连接,为数据同步做好准备。
步骤 1:保存主节点信息
从节点服务器内部维护了两个字段,即 masterhost 和 masterport 字段,用于存储主节点的 ip 和 port 信息。
需要注意的是,slaveof 是异步命令,从节点完成主节点 ip 和 port 的保存后,向发送 slaveof 命令的客户端直接返回 OK,实际的复制操作在这之后才开始进行。
这个过程中,可以看到从节点打印日志如下:
步骤 2:建立 Socket 连接
从节点每秒 1 次调用复制定时函数 replicationCron(),如果发现了有主节点可以连接,便会根据主节点的 ip 和 port,创建 socket 连接。
如果连接成功,则:
从节点:为该 socket 建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如接收 RDB 文件、接收命令传播等。
主节点:接收到从节点的 socket 连接后(即 accept 之后),为该 socket 创建相应的客户端状态,并将从节点看做是连接到主节点