05-Redis 多机之1 - 主从复制
1 主从复制
主从复制 是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为 **主节点(master)**,后者称为 **从节点(slave)**。
数据的复制是 单向 的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
Redis 主从复制支持 主从同步 和 从从同步 两种,后者是 Redis 后续版本新增的功能,以减轻主节点的同步负担。
2 主从复制的作用
- 数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复(实际上是一种服务的冗余)。
- 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础,因此说主从复制是 Redis 高可用的基础。
3 快速体验
在 Redis 中,用户可以通过执行 SLAVEOF
命令或者设置 slaveof
选项,让一个服务器去复制另一个服务器,以下三种方式是 完全等效 的:
- 配置文件:在从服务器的配置文件中加入:
slaveof <masterip> <masterport>
- 启动命令:redis-server 启动命令后加入
--slaveof <masterip> <masterport>
- 客户端命令:Redis 服务器启动后,直接通过客户端执行命令:
slaveof <masterip> <masterport>
,让该 Redis 实例成为从节点。
注意:主从复制的开启,完全是在从节点发起的,不需要我们在主节点做任何事情。
实验所使用的主从节点是在一台机器上的不同Redis实例,其中主节点监听6379端口,从节点监听6380端口
3.1 第一步:本地启动两个节点
安装好 Redis 之后,我们可以使用 redis-server --port <port>
的方式指定创建两个不同端口的 Redis 实例,例如分别创建端口为 6379
和 6380
两个 Redis 实例:
1 |
|
此时两个 Redis 节点启动后,都默认为 主节点。
3.2 第二步:建立复制
我们在 6380
端口的节点中执行 slaveof
命令,使之变为从节点:
1 |
|
3.3 第三步:观察效果
下面我们来验证一下,主节点的数据是否会复制到从节点之中:
先在 从节点 中查询一个 不存在 的 key:
1
2127.0.0.1:6380> GET mykey
(nil)再在 主节点 中添加这个 key:
1
127.0.0.1:6379> SET mykey myvalueOK
此时再从 从节点 中查询,会发现已经从 主节点 同步到 从节点:
1
2127.0.0.1:6380> GET mykey
"myvalue"
3.4 第四步:断开复制
通过 slaveof <masterip> <masterport>
命令建立主从复制关系以后,可以通过 slaveof no one
断开。
需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。
从节点执行 slaveof no one
之后,从节点和主节点分别打印日志如下:
1 |
|
4 实现原理简析
上图为 Redis 主从复制的原理, 可以分为成三个阶段:准备阶段-数据同步阶段-命令传播阶段。
除此之外,我们还要进行一些其他说明。
4.1 身份验证 | 主从复制安全问题
如果 主节点 配置 requirepass
设置了密码,那 从节点 该怎么设置呢?
我们可以在 从节点 中对应配置 masterauth
参数 (与主节点 _requirepass_
保持一致), 这样就能够进行正常复制了。
4.2 SYNC 命令是一个非常耗费资源的操作
每次执行 SYNC
命令,主从服务器需要执行如下动作:
- 主服务器 需要执行
BGSAVE
命令来生成 RDB 文件,这个生成操作会 消耗 主服务器大量的 CPU、内存和磁盘 I/O 的资源; - 主服务器 需要将自己生成的 RDB 文件 发送给从服务器,这个发送操作会 消耗 主服务器 大量的网络资源 (带宽和流量),并对主服务器响应命令请求的时间产生影响;
- 接收到 RDB 文件的 从服务器 需要载入主服务器发来的 RBD 文件,并且在载入期间,从服务器 会因为阻塞而没办法处理命令请求;
特别是当出现 断线重复制 的情况是时,为了让从服务器补足断线时确实的那一小部分数据,却要执行一次如此耗资源的 SYNC
命令,显然是不合理的。
PSYNC 命令的引入
所以在 Redis 2.8 中引入了 PSYNC
命令来代替 SYNC
,它具有两种模式:
全量复制: 用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作;
部分复制: 用于网络中断等情况后的复制,只将 中断期间主节点执行的写命令 发送给从节点,与全量复制相比更加高效。
需要注意 的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制;部分复制的原理主要是靠主从节点分别维护一个 复制偏移量,有了这个偏移量之后断线重连之后一比较,之后就可以仅仅把从服务器断线之后确实的这部分数据给补回来了。
更多的详细内容可以参考:https://www.cnblogs.com/kismetv/p/9236731.html
参考资料
- https://www.cnblogs.com/wmyskxz/p/12511834.html
- 《Redis 设计与实现》 | 黄健宏 著 - http://redisbook.com/
- 深入学习Redis(3):主从复制 - https://www.cnblogs.com/kismetv/p/9236731.html