用户可以使用 slaveof命令 去复制另一个服务器,被复制的服务器称为主服务器,请求复制的称为从服务器。达到两个服务器的数据状态一致。
这样有什么好处?
1.对于插入,修改,删除来说要同时修改两个服务器的值,增加了消耗,但是对于get来说,就可以进行分流了。可以间接实现数据持久化,一个服务器挂了,另外一个还在。
2.负载均衡:独写分离,主服务负责写,从服务器负责读。
3.高可用基石:主从复制是哨兵和集群实施的基础。
一,复制的实现
以从服务器:127.0.0.1:12345 发出命令:slaveof 127.0.0.1 6379 为demo,进行讲解
1.设置主服务器的地址和端口 :也就是上方的127.0.0.1 6379 从服务器会把信息保存到redisServer{}结构中,slaveof是异步命令,在完成赋值工作之后,从服务器向客户端返回ok,表示从服务器收到了命令,而实际的复制工作将在ok返回之后才真正开始执行。
2.建立套接字连接:slaveof命令执行之后,从服务器会根据命令所设置的ip port创建 连向主服务器的套接字,这个时候从从服务器相对主从模式来说,它是客户端角色,而相对用户来说,它还是服务器,所以它兼职两个角色。此时从服务器可以向主服务器发送命令请求,主服务器返回结果。
3.发送PING命令:当主从服务器连接成功之后,从服务器做的第一件事就是向主服务器发送ping命令,ping命令有两个作用:检查套接字读写是否正常,检查主服务器是否能正常处理命令请求,
主服务器的回复有三种情况:如图,如果不是pong,则判断是否返回错误信息,或者是否响应超时。
4.身份验证:从服务器收到主服务器的 pong 恢复之后,下一步决定是否进行身份验证,如果从服务器设置了masterauth,就需要进行验证,否者不需要。
需要身份验证:从发送一条 auth 命令,参数是从服务器masterauth选项的值,主服务器的对应项是:requirepass,如果两者相同,则密码正确,关于密码的验证,肯定会出现很多种情况,一种是,是否设置参数,另外一种就是密码不匹配。
5.发送端口信息:身份验证成功之后,从服务器执行 replconf listening-port xxx 命令,向主服务器发送从服务器的监听断开号,我们之前通信的时候,发送slaveof 只设置了 主服务器的监听端口号,但是在基本的socket通信中,主服务器返回result,还是能找到从服务器,这里又重写发送是否冗余呢?
主服务收到之后,会将信息保存到redisClient{}结构中,如同redisServer{}。相对称。
6.同步:从服务器发送 sync或者 psync命令,执行同步操作,将自己的数据更新到主服务器的状态。
7.命令传播: 当主从同步完毕之后,进行命令传播节点,主服务器将自己执行的写命令发送给从服务器。
其中工程量最大的是在同步部分,对于旧版本和新版本的同步方式不同,下面详细讲解。
二,旧版复制
1.同步
概念:也称为快照同步,全量复制,当从向主发送slaveof命令的时候,从服务器首先要执行同步操作,将从服务器的数据库状态更新到主服务区的数据库状态,从向主发送SYNC命令完成,
执行步骤:1.从服务器发送sync命令
2.主服务器收到后,执行bgsave生成rdb,同时使用一个缓冲区来存放现在开始的所有 写 命令。将rdb发送给从从服务器
3.从服务器 载入这个rdb。缓冲区的命令也发送给从,从进行执行。
2.缺陷
再次连接的时候,还是使用全量复制,导致:
1.主服务器生成rdb文件时间长
2.主服务器发送rdb文件时间长
3.从服务器收到rdb进行载入的过程中,无法正常工作
三,新版复制
从2.8开始,使用 psync命令代替sync命令,psync具有完整同步和部分同步两种模式,第二次复制就变成了部分复制了,解决旧版本中的性能问题,完整同步在上面已经讲述,这里直接讲解部分同步:
1.部分同步
概念:也称为部分复制,当两个正常连接的节点,出现网络等问题中断,重连之后,会进行同步,为了提高效率,推出部分同步,相比全量复制,成本小得多。部分复制功能由下面三个部分构成:
1.复制偏移量:执行复制的双方,都会分别维护一个复制偏移量,主服务器向从服务传播N个字节时,就将自己的偏移量加上N,此时主服务的偏移量更新。从服务器收到N个字节时,就将自己的复制偏移量+N。通过对比主从服务器的复制偏移量,可以知道主从服务器是否状态一致。
如果在运行期间,从服务器掉线了,重新连接的时候,就会发送自己的偏移量,主服务器就会把偏移量之后的内容,发送给从服务器,就避免了全量复制。
2.复制积压缓冲区:主服务器维护的一个固定长度先进先出的队列,默认大小1MB(redo file 50M),保存的内容是主服务执行的写命令,也就是说,当写命令发送给从服务器的时候,主服务器还需要发送到缓冲区进行保存。
那么如果出现偏移量偏差,主服务器就会找从服务器的偏移量点,如果存在就会读取发送给从服务器。buffer是可以调整的。如果从服务器发送的偏移量已经不存在于 缓冲区中,那么就主服务器将执行全量同步。
3.服务器运行ID:每个redis服务器,都有自己的运行id,当第一次连接的时候,从服务器会请求主服务器的运行唯一ID,并将其保存起来,当下一次连接请求带了Id,说明不是第一次,没有带对应id,说明是第一次连接。(可能集群中有多个主服务器,然后上一个主连接断了,现在连接另外一个)
新版本连接到同步的流程:
2,心态检测
在命令传播阶段,从服务器会每秒一次的频率,向主服务发送命令。有以下三个任务:
1.检测主服务器的网络连接状态:从服务器发送,主服务器接收 replconf ack命令来检查两者之间的连接是否正常,如果主服务器超过1s没有收到,则主服务器判断从服务器网络出现问题,
2.辅助实现min-slaves配置选项:防止主服务器在不安全的情况下,执行写命令。
3.检测命令丢失:在进行心跳检查的过程中,还需要检查两者的偏移量是否同步,如果不同步,则主服务器根据从服务器提交的偏移量,找到缺失的命令,重新发送。
参考:《redis设计与实现》
https://blog.csdn.net/qq_41723615/article/details/104201073
https://www.cnblogs.com/kismetv/p/9236731.html(存在redis 系列)