一:Redis从节点是如何向主节点同步数据的(首次)
-
从节点先设置同步信息
SLAVEOF IP PORT
-
建立套接字链接
-
从节点向主节点发送PING命令,主节点在网络正常的情况下会返回PONG
-
根据从节点的配置,决定是否进行身份验证 即 masterauth 配置项
-
发送从节点的监听端口号给主节点(目前仅用于主节点上展示客户端的状态 INFO replication)
-
同步(PSYNC命令的解释放到后续)
- 从节点发送PSYNC命令,由于是首次,所以是完整的全同步(PSYNC ? -1)
- 主节点异步执行BGSAVE并返回 +FULLRESYNC <runid> <offset> 命令(runid即当前主节点的运行id,offset即主节点当前的复制偏移量)
- 从节点获取主节点的runid和offset,用于下次增量同步操作
- 待主节点BGSAVE生成RDB文件后,从节点根据主节点传递过来的RDB文件开始同步
little tips:
PSYNC <runid> <offset>
runid:上次复制的主服务器的运行ID,同步后会保存下来供下次同步使用
offset:从服务器当前的复制偏移量
二:Redis从节点是如何向主节点同步增量数据的
与上一步的操作相差的地方之一:因为已经建立了连接,所以不需要在重新进行前五步(建立连接的操作)
另外,主从服务器都会维护一个复制偏移量
在主节点主动向从节点同步数据时:主节点每次向从节点传输N个字节的数据,主节点的偏移量会增加N。同时,在从节点收到主节点传来的N个字节的数据时,从节点的偏移量也会增加N
那么问题来了,假如主节点向从节点传输数据时,由于网络原因或者从节点宕机,导致从节点偏移量落后了,该怎么办?
此处我们分两种情况考虑:
- 从节点宕机:在从节点宕机重启后,他会重新SLAVEOF当前的主节点。并经过一系列操作后发送PSYNC命令给主节点,此时带上主节点的runid和自己当前的偏移量offset。此时主节点发现从节点落后了,便会将落后的数据同步给从节点
- 从节点由于网络问题丢失了主节点的同步请求:从节点会定期向主节点发送REPLCONF ACK命令,主节点会发现从节点的偏移量落后于主节点,便会做刚刚相同的操作,将从节点落后的数据同步给主节点
此时,回到问题的前面,Redis是拿什么来记录同步时的增量数据的呢?
此处用到了一个 复制积压缓存区(固定长度的先进先出队列)。该队列会记录每个偏移量和字节的值
既然复制积压缓存区是固定长度的,那么我们该如何设置他的大小?
second * write_size_per_second (second:从服务器断线后重新连上主服务器所需的平均时间 单位为秒)(write_size_per_second 主服务器平均每秒产生的写命令数据量)
三:关于主节点也是从节点的客户端的原因
关于这个原因,我们在前面也有提到。
之所以主节点也要是从节点的客户端,为了就是 主节点能够主动将写操作产生的数据同步给从节点。
四:什么是复制积压缓存区
前面我们提到了复制积压缓存区,那么什么是复制积压缓存区呢?
引用上面的一个描述:复制积压缓存区(固定长度的先进先出队列),他的作用是记录一部分最近传播的写命令
回到一开始的全同步,主节点在执行BGSAVE的期间,也会有一部分的写命令产生,此时这一部分的写命令便会被存储在复制积压缓存区中。在从节点同步完RDB文件内的东西之后,便会把复制积压缓存区里的命令也执行一遍。
积压缓存区大小设置不合理会导致的情况:假如从节点和主节点间的网络断连时间过长,复制积压缓冲区可能被新写入的命令覆盖,此时就不能通过复制积压缓存区来增加同步了,而是只能进行全量复制
网友评论