前言:
你认为的主从关系:
实际上的主从关系:
哈哈~以上图片大家图一乐~ 你以为主从关系之间就是主在指导着全部,但是其实不是。在redis主从关系中,主从相辅相成。今天小面就和大家一起来唠一下redis主从复制的原理
正文:
什么情况下需要redis主从复制?
其实现在生产上,我们对于redis肯定是需要高可用的,为了防止一台机器挂掉,或者是网络崩了。比如主从复制,哨兵,集群。我们今天的主题就是主从复制,主从复制就是得到了数据备份和读写分离两个功能。
实现主从复制
假设我们有俩redis,A(master)与B(Slave) 我们使用SLAVEOF 去实现主从复制
Aip:6379>SLAVEOF Bip 6379
此时主从关系就已经建立
Aip:6379>SET a "abc" OK Bip:6379>GET a "abc"
从节点只能读,但是不能写会报错 READONLY 如果是想要取消主从复制,使用SLAVEOF NO ONE 命令
主从复制实现(Redis2.8之前的版本)
执行SLAVEOF命令后,
- 从 会向 主发送SYNC命令
2.从发送给主后,主收到了该命令就会去执行BGSAVE命令,BGSAVE命令执行后默认会在我们磁盘上回生成一个RDB文件,同时也会在缓冲区把之后的所有的命令都给保存下来。
3.主 讲rdb文件发给从,从 加载rdb文件。
4.主 将缓冲区的命令发送给从,从去执行这些命令 。
这就是redis2.8之前的同步操作,主有数据之后,主就会把自己执行过的命令集合发送给从服务器,从服务器接受到了这些命令后就会去执行,这样主和从就相同了。
缺点:如果说从因为网络等一些问题断线重连,每次都要去执行一次SYNC全量复制(SYNC命令是比较消耗资源的,要生成rdb文件,又要传输去从,从要再加载文件)
主从复制实现(Redis2.8之后的版本)
为了解决上述缺点,新版本的主从复制就可以解决。初次复制和原来的全量复制是一样的。断线后的复制,只需要把断线后主执行过的命令发送给从就可以了。
那么要怎么实现呢?那我们需要了解几个知识点,第一个知识点是复制积压缓冲区,顾名思义就是一个暂时存放的地方。第二个是复制偏移量。第三个是runId。主每次执行命令,主的偏移量就会去加向从传输的字节大小。从收到数据后执行后,从的偏移量就会加上传输的字节大小。
给大家举个例子 A是主,BC是从 原先ABC的偏移量都是10000,A传输了33字节的数据,B断开,C正常 此时A和C的偏移量都是10033,而B重连之后还是10000。
那么B该怎么获取数据?这就会涉及到了复制积压缓冲区,简单来说在A传输数据的时候,他会把命令往缓冲区去存入。不过我们也需要考虑一下情况,我们把复制积压缓冲区想象成一个圆形。初始的主从偏移量全部都在12点方向,主接受了一定量的数据,顺时针跑到了6点。那么此时 从断开重连后, 就是要去执行增量同步。如果主偏移量从12点顺时针跑了一圈又到了12点,再多跑了一点,有一部分数据已经被重新覆盖了,增量同步将不起作用,这部分被覆盖的数据就永远获取不到,所以此时就要做全量同步。
那么比如再重新选主的场景,我怎么知道我是不是复制的还是原来的主呢?这就涉及到runId,第一次全量复制的时候,主会把runId给从,从在做psync的时候会去携带runId,如果runid不一致,就直接全量同步
总结