多机数据库的实现
《十五章:复制->主从复制》
用户可以通过执行slaveof命名或者设置slaveof选项,让一个服务器去复制replicate另一个服务器,被复制的服务器为主服务器master。对主服务器进行复制的服务器叫从服务器。
127.0.0.1:6379 和 127.0.0.2:6379两台服务器,如果127.0.0.2:6379向127.0.0.1:6379发送命令:slaveof 127.0.0.1:6379 ,那么127.0.0.1:6379将成为127.0.0.2:6379的主服务器。
命令:slaveof 127.0.0.1 6379
旧版复制功能对实现: | redis的复制功能分为同步sync和命令传播command propagate两个操作 |
1.同步操作 | 用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。 |
2.命令传播 | 用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致时,让主从服务器的数据库重新回到一致状态。 |
主从同步到步骤:
1.从服务器向主服务器发送同步sync命令 |
2.收到同步sync命令的主服务器执行bgsave命令,在后台生成一个rdb文件,并使用一个缓冲区记录从现在开始执行的所有写命令 |
3.当主服务器的bgsave命令执行完毕后,主服务器会将bgsave命令生成的rdb文件发送给从服务器,从服务器接收并载入这个rdb文件,将自己的数据库状态更新至主服务器执行bgsave命令时的数据库状态。 |
4.主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新到主服务器数据库当前所处的状态。 |
旧版复制功能多缺陷主从复制分两种情况:
1.初次复制: | 从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同。 |
2.断线后重新复制 | 处于命令传播阶段的主从服务器因为网络原因而中断了复制,从服务器通过自动重新连接上了主服务器,并继续复制主服务器。 |
总结: | 对于初次复制,旧版复制功能可以很好的完成功能,但对于断线后重新复制来说,旧版复制功能虽然也能让主从一致,但效率很低。 |
新版复制功能的实现:为了解决旧版复制功能在处理短线重复的情况时低效率的问题,新版redis 使用psync命令代替sync命令来执行复制时的同步操作。
1.其中完整重同步用于处理初次复制情况: | 完整重同步的步骤和sync 命令的执行步骤一样,他们都是通过让主服务器创建并发送rdb文件,以及向从服务器发送保存在缓冲区里面的写命令进行同步 |
2.部分同步用于处理短线后的重复: | 当从服务器在短线后重连,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接受并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。 |
部分重同步三个步骤:
1.主服务器的复制偏移量和从服务器的复制偏移量 |
2.主服务器的复制积压缓冲区 |
3.服务器的运行id |
复制偏移量: | 执行复制的双方,主从服务器会分别维护一个复制偏移量。通过对比主从服务器的复制偏移量,可以知道主从服务器是否处于一致状态。 |
复制积压缓冲区: | 复制积压缓冲区是由主服务器维护的一个固定长度fixed-size 先进先出FIFO队列,默认大小为1MB。 |
当从服务器重连主服务器,从服务器会通过psync命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行哪种同步操作:
1.如果offset偏移量之后的数据仍然存在复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作。 |
2.如果offset偏移量之后的数据不存在复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作。 |
服务器运行id:复制偏移量和复制积压缓冲区之外,实现部分重同步还需要用到服务器运行id(run id):
1.每个redis服务器,不论主从,都有自己的运行id |
2.运行id 在服务器启动时自动生成,由40个随机的十六进制字符组成。 |
当从服务器对主服务器进行初次复制时,主服务器会将自己的run id 传送给从服务器,而从服务器则会将这个run id 保存起来。当从服务器短线并重连,从服务器将向主服务器发送之前保存的run id:
1.如果从服务器保存的run id和当前连接的主服务器run id相同,那么说明从服务器端之前复制的就是当前连接的主服务器,主服务器可以继续尝试执行部分重同步操作。 |
2.如果run id 不同,那么说明从服务器不是连的当前主服务器,主服务器将对从服务器执行完整重同步操作。 |
psync命令的实现:
1.如果从服务器以前没有复制过任何主服务器,或者之前执行过slaveof no one 命令,那么从服务器在开始一次新的复制时将向主服务器发送psync ? -1 命令,主动请求主服务器进行完整同步。 |
2.如果从服务器已经复制过某个服务器,那么从服务器在开始一次新的复制时将向主服务器发送psync runid offset 命令:其中 runid 是上一次复制的主服务器的run id,offset 是从服务器当前的复制偏移量,接受到这个命令的主服务器会通过这两个参数来判断应该对服务器执行哪种同步操作。 |
接收到psync命令到主服务器会向从服务器返回以下信息:
1.如果主服务器返回fullresync runid offset 回复,那么表示主服务器将与从服务器执行完整同步操作:其中runid 是这个主服务器的run id,从服务器会将这个run id保存起来,在下一次发送psync命令时使用;而offset则是主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量。 |
2.如果主服务器返回 continue 回复,那么表示主服务器将与从服务器执行部分重同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了。 |
3.如果主服务器返回 -err 回复,那么表示主服务器的版本低于redis2.8,它识别不了psync命令,从服务器向主服务器发送sync命令,并与主服务器执行完整同步操作。 |
复制的实现步骤:
1.设置主服务器的地址和端口:slaveof 127.0.0.1 6379 |
2.建立套接字连接 |