Redis 主从复制

什么是主从复制

主从复制,就是将一台服务器的数据,复制到另一台服务器,前者称为主服务器,后者称为从服务器。
 
默认情况下,每台服务器都是主节点。
一个主节点可以有多个从节点,但是一个从节点只能有一个主节点。

主从复制的作用

1. 数据冗余:实现多机之间数据的热备份
2. 故障恢复:当主节点断线后,通过哨兵让从节点继续提供服务,实现故障恢复
3. 负载均衡:在主从复制的基础上,配合读写分离,由主节点提供写服务,由从节点提供读服务,分摊服务器的读写压力。在一些读多写少的场景,比如淘宝的商品页面,通过多个从服务器去分担读的压力,可以大大提升服务器的并发量。

主从复制的缺陷

1. 故障恢复无法自动化
2. 写操作无法负载均衡
3. 存储能力收到单机的限制

如何使用主从复制

slaveof

向当前服务器发送slaveof命令,可以让当前服务器成为主服务器的从服务器,主服务器就是下面<master_ip> <master_port>对应的服务器
slaveof <master_ip> <master_port>
向6381端口的服务器发送slaveof命令,使其成为6379的从服务器
 

info replication

用info replication查看当前服务器的主从复制配置
 

slaveof no one

通过slaveof no one可以断开复制,使得当前从节点变回主节点。从节点断开后,不会删除原有的数据,只是不再接受主服务器的数据变化。

主从复制的原理

复制分为三个过程,建立连接阶段、同步阶段、命令传播阶段。

1. 建立连接阶段

2. 同步阶段

在Redis2.8版本之后,使用PSYNC命令替代旧版本的SYNC命令,旧版本的SYNC命令中只有全量同步,而全量同步是非常耗费资源的操作。所以现在更新后的PSYNC命令包含全量同步和增量同步两个操作。
数据同步阶段是主从复制最核心的阶段,根据主从节点的不同状态可以分为全量同步和增量同步两种方式。

2.1 全量同步

全量同步用在初次复制(从节点第一次连接主节点)或者无法增量同步的情况下。
实现:主节点通过BGSAVE生成RDB文件,并开启一个缓冲区用于记录执行BGSAVE命令后所有的写操作,最后把RDB文件和缓冲区里的写操作发送给从节点。
全量同步是非常消耗IO,Cpu,带宽资源的操作,而且从节点载入接收到RDB文件是会阻塞进程的。

2.2 增量同步

当从节点因为网络等原因而掉线,重新连接上主节点后采用增量同步,增量同步只需把中断期间的主节点执行的写命令发送给从节点,与全量同步相比增量同步更高效,耗费资源少的多。
但是如果中断时间过长,期间执行的写命令没有保存在复制积压缓冲区里,仍然要使用全量同步。
实现:增量同步由三部分组成:复制偏移量、复制积压缓冲区、服务器的运行时ID。

复制偏移量(offset)

主节点和从节点分别维护一个复制偏移量,代表主节点向从节点传递的字节数。主节点每次向从节点传播N个字节的数据,就将自己的复制偏移量增加N;从节点每次收到主节点发来的N个字节的数据,就将自己的复制偏移量增加N。
通过复制偏移量可以很方便比较主节点和从节点的数据是否一致。如果二者offset相同,则一致;如果offset不同,则不一致,此时可以根据两个offset找出从节点缺少的那部分数据。如果缺少的那部分还在复制积压缓冲区里,就执行增量同步,否则执行全量同步。

复制积压缓冲区

复制缓冲积压区是主节点维护的一个长度固定,先进先出的队列。作用是备份主节点发送给从节点的数据。
在命令传播阶段,主节点不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面。除了存储写命令,复制积压缓冲区还存储其中每个字节对应的偏移量。
由于缓冲区大小有限,所以可以备份的写命令也是有效的。当主从节点的offset差的那部分数据太多,超过了缓冲区的大小,就只能执行全量复制了。
为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小。复制积压缓冲区的大小可以根据公式(从服务器断线后连上主服务器的平均时间)*(主服务器平均每秒产生的写命令的大小)得出,例如,如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要5秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于5MB,在实际使用中,为了保险起见,可以把大小再乘2设置为10MB,来保证绝大多数断线情况都可以使用部分复制。
在配置文件中通过repl-backlog-size修改复制缓冲积压区大小。

服务器的运行时ID

每个Redis节点,在启动时都会随机生成一个运行时id(每次启动生成的不一样),runid用来唯一识别一个Redis节点。
主从节点初次复制时,主节点会把自己的runid发送给从服务器,从服务器会保存下来。
当从服务器断线重连后,会将保存的主节点runid发送给重连上后的主节点,如果一致,说明主从节点之前同步过,尝试使用增量复制(能不能增量复制还要看offset差的那部分数据还在不在缓冲区里)。如果不一致,说明从节点在断线前同步的主节点并不是当前的主节点,只能进行全量复制。

3. 命令传播阶段

数据同步阶段完成后,主从节点进入命令传播阶段,在这个阶段主节点将接收到的写命令发送给从节点,从节点接受命令并执行,从而保证主从节点的数据一致性。

3.1 心跳检测

在命令传播阶段,从服务器会以每秒一次的频率向主服务器发送REPLCONF ACK{ offset }命令。发送这个命令有三个作用:
1. 检测主从节点的网络连接状态。如果主节点超过1秒没有收到从节点的REPLCONF ACK{ offset }命令,那么主节点知道主从节点之间的连接出了问题。
2. 检测命令丢失。从节点发送了自己的offset,主节点会与自己的offset进行对比看是否相同。
3. 辅助实现min-slave-to-write命令和min-slave-max-lag命令, 来保证主节点在不安全的情况下不会执行写命令。所谓不安全,是指从节点数量太少,或延迟过高。例如min-slaves-to-write和min-slaves-max-lag分别是3和10,含义是如果从节点数量小于3个,或所有从节点的延迟值都大于10s,则主节点拒绝执行写命令。
 
看下面这篇博文,了解在实际应用中主从复制会出现的问题
 

posted @ 2021-10-02 21:01  昂热bobo  阅读(54)  评论(0)    收藏  举报