上篇博文我们了解该如何实现Redis的持久化,这篇博文再get下Redis的主从复制的相关知识点,理解主从复制的操作、原理以及完全重新同步和部分重新同步的区别,能优化主从复制并且进行故障诊断。
Redis的安装和持久化
Redis的主从复制(replication)
Redis的主从复制是组成Redis高可用的一部分,也是必不可少的一部分,通过Redis提供的复制功能,将数据从Redis(master节点)向另一个Redis(slave节点)复制。
我们还是带着问题去整理这个知识点
- Redis是高可用的一个组成部分,我们为什么需要Redis的主从复制,他有哪些作用
- Redis该如何主从复制,需要注意哪些问题
- Redis的主从复制原理和机制是怎么样的
- Redis的主从复制该如何调优
- Redis发生故障时该如何进行故障诊断
准备工作
主从复制,大多数是为了数据备份、高并发和高可用,而要满足高可用的要求,一般都是两台不同的服务器或者虚拟机节点,以保证主节点服务器宕机或者其他不可知的原因导致服务不能使用,则需要子节点的服务能替代主节点的服务器继续对外提供服务。所以我们先准备两台虚拟机,分别安装redis服务,并且启动服务,其次如果读的QPS比较多的话,一般采用读写分离的模式来分离读数据和写数据(主写从读),通过横向扩容从Redis的实例来扩大读QPS,而实现这一功能,主从复制必不可少
具体安装可以参考上一篇的博文《Redis的安装》
我们准备一下两台虚拟机,分别对外提供Redis服务:
- 主节点:192.168.56.105:7000
- 子节点:192.168.56.106:7000
Redis主从复制
Redis复制的启动
复制不仅提高了整个redis的容错能力,同时也可以对系统进行横向扩容等,开启子节点复制父节点很容易,有三种方法可以进行复制父节点数据
- redis.conf的配置文件中 添加
slaveof master_ip master_port
## redis 5.x 版本中
replicaof master_ip master_port
- 在启动redis的时候,使用命令来启动
redis-server --slaveof master_ip master_port
- 在客户端cli中指定主节点
redis> slaveof master_ip master_port
Redis复制注意事项
- 将主节点中的
protected-mode
改为no
如果是保护模式开启,则slave node中 使用 info replication 会发现 master_link_status:down 从而导致复制不成功
- 如果master node中
开启了授权,则在slave node中需要给予主节点的密码
masterauth
master node 中
requirepass passwd
slave node 中
masterauth passwd
- 在最新的版本中
slaveof
已经替换为replicaof
,但是slaveof
同样可以使用,并且作用是相同的,至于为什么可以通用,我从技术领域角度来说,闲的无聊,找点事做。 - 个人建议在做主从复制时,一定要将master node做持久化操作,原因是当master node节点重启服务时,如果不做持久化的话,到时会将数据清空,同时slave node的数据也会被清空,导致不仅仅master数据丢失,slave node的数据也会丢失
- 如果想实现部分重新同步,那么在redis4.x版本之后,需要将slave node也做持久化操作,至于原因会在下面的原理中给予解释
Redis复制的验证
- 开启rdis复制之后,我们可以在客户端中使用
info replication
命令来查看是否已经开启复制成功
## 主节点中 cli中执行 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.56.106,port=7000,state=online,offset=28,lag=0
## master node中的节点id
master_replid:43db81ea472435516baa83e0164574bef8ac65f8
master_replid2:0000000000000000000000000000000000000000
## master node中的节点偏移量
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
## 子节点中 cli中执行 info replication
# Replication
role:slave
master_host:192.168.56.105
master_port:7000
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:42
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:43db81ea472435516baa83e0164574bef8ac65f8
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:42
出现如上所述的master node 中 connected_slaves:1
,说明master node存在一个连接的slave node节点,并且slave0
是关于第一个子节点的配置信息。在slave node节点中role
表明这个是子节点,并且master_host
显示master node的IP信息,master_link_status
表明是否连接上,up表示连接中,down表示连接失败,此处连接失败,可能是master node中protected-mode
为yes导致。
Redis主从复制的原理和核心机制
Redis主从复制的原理:
- slave node启动时,会向master node发送 sync命令。相当于向master node注册slave node的相关节点信息,让master node知道他存在一个子节点
- slave node刚启动时,会发送
master_repl_offset
给master node,由master node决定是走完全重新同步还是部分重新同步步骤,如果master_repl_offset
与master node是中的backlog中能找到,则是部分重新同步,否则是完全重新同步。 - 是完全重新同步:master node会将缓存所有的写入操作命令,同时fork一个子线程,生成RDB快照,master node将RDB文件传给slave node,slave node再将所有的命令同步到本地的内存中,如果此时slave node也做了持久化,则会将数据持久化到磁盘中
- 部分重新同步:不需要从master node中转存数据文件,master node直接将偏移量之后的所有命令同步发送给slave node节点,在slave node节点来完成数据的更新
流程图如下:
为了更深层次的理解Redis是如何进行主从复制的,我们需要知道Redis复制的核心机制
- Redis采用异步方式复制数据到slave节点
- 一个master node 可以配置多个slave node
- slave node之间可以互联互通,传递类似心跳的数据
- slave node在做复制的时候,不会阻塞master node的正常工作
- slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了
- slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量
Redis主从复制调优
根据上面的主从复制的原理,我们可以知道主从复制进行的是完全重新同步还是部分重新同步的主要依据是slave提交给master的offset偏移量能否在master的replication backlog中查找到,如果能查找到则说明进行部分重新同步操作,如果查找不到则说明进行完全重新同步操作
再次之前我们先了解下 replication backlog是什么?
replication backlog是master中的环形缓冲区,该区域记录的是最新所有的写入命令,是一个固定长度的列表!
知道上述原理,我们可以通过控制backlog中的值的大小来控制是否进行完全重新同步还是部分重新同步,在redis.conf配置文件中backlog的大小是通过 repl-backlog-size
来控制的,默认是1mb
在实际生产中,我们可以通过info replication中获取 master_repl_offset
的大小来估算backlog的大小
Redis主从复制故障诊断
影响Redis主从复制故障的原因可能有:磁盘IO、网络连接、数据集大小和长时间的阻塞等因素。
说起主从复制,我们需要先了解主从之间是怎么判断彼此之间的通讯,master想要知道slave是否正常运行,则会向slave发送ping命令,我们可以通过repl-ping-replica-period
参数来调整这个间隔,默认间隔是10s
那么主从实例又是如何判断彼此之间复制链接被断开呢?
slave会向master发送REPLCONF ACK来报告他的复制偏移量,对Ping和REPLCONF ACK来说,都可以通过repl-timeout
来指定超时时间,该值默认时间是60s,如果两次PING护着REPLCONF ACK之间的时间间隔比超时时间差,则可以认为主从复制链接被断开。
master向slave进行完全重新同步时,master会生成RDB快照文件,然后发送给slave,slave将RDB快照中的文件数据存储到slave的内存中,在这个步骤执行的过程中,如果master有新的数据写入,则master会将这部分数据写入到从客户端缓冲区(slave client buffer)中,在slaveRDB加载之后,将该缓冲区的数据发送给slave实例。但是这个实例是有大小限制的,当缓冲区的数据超过这个默认值时,则会导致复制重新开始。
所以我们在复制故障诊断时,需要注意参数repl-ping-replication-period
和repl-timeout
的值的控制,在生产环境中 repl-ping-replication-period
一定要比repl-timeout
小,否则容易造成复制超时。