主服务器能处理的请求是有限的,所以需要复制出来和主服务器数据库状态一致的从服务器帮助主服务器分担压力。
Redis使用slaveof命令使得一台服务器称为另一台服务器的从服务器。
旧版复制的实现:分为同步和命令传播两个操作
同步是从服务器向主服务器发送sync命令,主服务器开始执行bgsave保存rdb文件,另外在保存期间新执行的写命令写在缓冲区中,然后将rdb文件和缓冲区的命令一同发给从服务器,让从服务器去执行
命令传播是在同步之后,主服务器的数据库状态可能会被新的命令修改,所以造成主从不一致,所以主服务器会把新命令发给从服务器也去执行。
旧版的缺点:
在这种场景中,主从服务器因为某种原因断线了,从服务器会尝试重新连接主服务器,连接成功后,会重发sync命令去同步,乍一看好像没问题,为了恢复同步状态。但是从服务器不同步的东西只是断线这个过程中的命令,断线之前大家都是一致的。所以旧版中主服务器收到sync后会重新生成一个完整的RDB文件传给从服务器,非常耗费资源,而且还效率不高。
新版复制功能:redis2.8以后
同步的新命令PSYNC, 如果是第一次复制,和上面的SYNC没有任何区别,但对于断线重连后的情况,PSYNC就执行部分重同步,即只是将断线这段时间主服务器执行的命令发给从服务器。
具体实现:
执行复制的双方都会维护一个偏移量,代表自己发了或者已经接收了多少字节的数据,在断线重连后,对比两个偏移量之间的区别。然后将相差的那部分数据发给从服务器。相差的数据保存在哪呢,其实主服务器维护着一个复制积压缓冲区,是一个固定大小的先进先出的缓存队列,主服务器会把命令传播过程中的命令除了发给从服务器之外,也会写进这个队列,然后假如遇到了断线重连,就去复制积压缓冲区中查看这部分相差的数据是否还在其中,如果在,就执行部分重同步操作,如果不在,就执行完全重同步操作。
当主从关系的服务器变多了以后,为了方便识别是不是对应的服务器,所以每个服务器都有一个自己的ID。