参与复制的redis节点分为master和slave,也就是主从,默认情况下都为master节点。复制过程,数据是单向的,只能从主节点复制到从节点。
建立复制和断开连接
建立复制的方式有三种:
- 在配置文件中加入 slaveof {host} {port},表示将{host:port}对应的节点作为自己的主节点。
- 在redis-server启动命令中加入–slaveof参数
- 在客户端中使用命令:slaveof
复制的过程是一个异步过程,在执行命令后,只保存master节点信息并立即返回,后续复制过程异步执行。
建立复制成功后,可以分别在master和slave节点上查看状态
1
2
3
4
5
6
7
8
9
10
11
12
13
localhost:6379> info replication
# Replication
role:master # 表明自己是主节点,对应的slave是6378
connected_slaves:1
slave0:ip=127.0.0.1,port=6378,state=online,offset=1079997,lag=0
master_replid:d67a40111ca08c6871fcc411632b16e368fbe54f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1079997
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:31422
repl_backlog_histlen:1048576
- 断开连接,
slaveof no one
,注意断开连接,只是不再复制master的数据,但之前的数据还保存
复制过程
保存主节点信息
主从节点建立socket连接,通过定时任务维护复制逻辑,发现新的主节点后,会尝试与该节点建立网络连接(专门开启一个端口)。
发送ping命令,从节点发送ping请求通信,如果失败,会断开socket连接,下次定时任务重新开启
权限验证,如果主节点配置了密码,从节点需要配置masterauth参数,否则重新发起复制流程。
同步数据集,成功后,进入首次复制流程,主节点采用复制命令psync(sync是旧版本,这里不做讲解)
全量复制: 在初次复制场景,会一次性把所有数据发给从节点,是一个非常耗时的操作。
从节点发送psync-1命令,代表没有偏移量
主节点发送+FULLRESYNC,以及当前偏移量和server id,从节点保存该信息
主节点会首先执行bgsave,保存当前的数据到RDB文件
发送到从节点上(网络开销较大)可以看日志
MASTER<->SLAVE
,如果超过时间(默认60s),则会复制失败从节点接受到数据后保存,并直接作为本节点的数据文件,然后清空现有数据并加载数据
从节点如果开启了AOF,则会立即bgrewriteaof操作,重新备份aof文件。
部分同步: 用于处理由于网络或其他原因导致的数据丢失(采用offset机制),补发丢失数据,另外主节点和从节点同步时,也会把命令写入复制积压缓冲区,如果发生了断连,等重新连接后,可以从复制积压缓冲区中同步。
复制缓冲区: 在全量复制的过程中,master节点还会收到来自其他客户端的请求,这一部分数据会保存在复制缓冲区当中,当RDB发送成功之后,会把缓冲区内的数据发给从节点,如果缓冲区内的数据溢出,也就是同步期间master接受到的命令过多,会导致同步失败,重新开始
复制积压缓冲区: 是在master和slave节点追加同步过程中,发生了网络断开,从节点再次连接后,会从复制积压缓冲区里同步,如果超过了复制积压缓冲区的数量(会根据从节点发过来的offset在复制缓冲区里查找),则会触发全量复制。
命令持续复制,当前的数据同步到从节点后,后面就是持续同步的过程,也就是只同步新增的命令
每个redis节点启动后都会重新分配一个唯一的ID,从节点是根据ID来识别master的,所以在ID变化后(master重启)从节点将做一次全量复制。
如何在不改边id的情况重启?可以使用debug-reload命令重新加载(会阻塞)
授权
默认情况下,我们没有设置密码,也就是任意机器都可以复制我们的信息,为了增加安全,master节点通常会设置密码,来保证安全。
- 设置本机密码:CONFIG set requirepass password (也可在配置文件中配置)
- 客户端连接:启动客户端后,
auth password
- slave连接:
config set masterauth password
(否则日志会一直报错)
一般如果配置成从节点,可以使用
slave-read-only=yes
,这样可以避免修改从节点导致的主从数据不一致问题
传输延迟
- redis提供了repl-disable-tcp-nodelay参数,当关闭时,无论命令数据大小都会及时的发给从节点,这样延迟会减小,但会增加带宽,如果开启,则会将小的数据合并再发送
部署方案
- 主从结构
- 树状结构
- 读写分离(复制数据延迟,读到过期数据)
规避全量复制
全量复制是一个很耗资源的操作,包括内存、cpu、网络io等。应该尽量规避
- 第一次建立复制:应该尽量在业务量少的情况进行
- 节点运行ID不匹配:当主节点因故障重启,它的id会发生改变,这个时候会进行全量复制。这种情况应该从架构上规避,比如采用集群模式或者哨兵模式。
- 复制积压缓冲区不足:对于大流量场景,应需估计网络波动时长,增大积压缓冲区。
- 复制风暴:一般发生在一个master节点挂载多个slave节点的情况。可以采用树状结构