全量复制
对于一个存储了很多数据的 master(主节点),slave(从节点)去做一个复制,想要的想过是把 master 的数据全部同步过来,在同步过程中 master 写入的新数据也需要同步过来,这样才可以达到数据完整同步的效果。
全量复制可以完成上述功能,首先将当前的 RDB 文件同步给 slave,写入命令单独记录;当 RDB 文件加载完后,通过偏移量的对比将这期间产生写入的值同步给 slave。
全量复制过程如下:
- 首次同步时 slave 不知道 master 的 runid 和 偏移量,slave将发送 psync ? -1 (psync是同步命令,2.8版之前是sync;可实现全量和部分,有两个参数 runid 和 offset(偏移量) ;?表示 runid,-1表示offset)来同步数据;
- master 将执行一个全量复制,同时返回自己的 runid 和 offset 给slave;
- slave 保存 master 的基本信息;
- master 执行 bgsave 命令做一个 RDB 的生成,在生成 RDB 和 RDB 传输过程中写入的新命令将被推入 repl_back_buffer(复制缓冲区) ;
- master 将 RDB 文件传给 slave;
- master 将 repl_back_buffer(复制缓冲区) 传给 slave;
- slave 清除旧的数据;
- slave 根据 RDB 文件和 repl_back_buffer(复制缓冲区) 加载新的数据。
全量复制的开销
- bgsave 耗费的时间;
- RDB 文件网络传输耗费的时间;
- 从节点清空数据耗费时间(根据从节点的数据规模来定);
- 从节点加载 RDB 的耗费时间;
- 可能的 AOF 重写耗费时间;
部分复制
全量复制的问题
除了上述的开销以外还存在一个问题;
假如说 master 和 slave 之间的网络发生了抖动,那么一段时间内这些数据就会进行一个丢失,这段时间内 master 更新的数据 slave 是不知道的,最简单的方法是再做一次全量复制来拉取最新的数据。
这样将大大的提升了设备性能的消耗,所以2.8版以后 Redis 提供了部分复制的功能。
部分复制过程如下:
- 因为网络抖动导致 master 和 slave 断开连接;
- master 写命令时会向 repl_back_buffer(复制缓冲区) 写一份‘’;
- 网络抖动结束,slave 再次成功连上 master;
- slave 向 master 发送 pysnc {offset} {runid} 命令,把自己当前的 offset (偏移量)和 runid 传给 master;
- 当 slave 传输的 offset 在 master 的 buffer (buffer默认大小是1MB)的范围内(即在偏移量队列中),master 返回 contiune;
- master 返回 buffer 中的数据给 slave;