部分重同步功能由以下三个部分构成:
a.主服务器的复制偏移量和从服务器的复制偏移量
b.主服务器的复制积压缓冲区
c.服务器的运行ID
typedef struct redisClient {
// 复制状态
int replstate; /* replication state if this is a slave */
// 用于保存主服务器传来的 RDB 文件的文件描述符
int repldbfd; /* replication DB file descriptor */
// 读取主服务器传来的 RDB 文件的偏移量
off_t repldboff; /* replication DB file offset */
// 主服务器传来的 RDB 文件的大小
off_t repldbsize; /* replication DB file size */
sds replpreamble; /* replication DB preamble. */
// 主服务器的复制偏移量
long long reploff; /* replication offset if this is our master */
// 从服务器最后一次发送 REPLCONF ACK 时的偏移量
long long repl_ack_off; /* replication ack offset, if this is a slave */
// 从服务器最后一次发送 REPLCONF ACK 的时间
long long repl_ack_time;/* replication ack time, if this is a slave */
// 主服务器的 master run ID
// 保存在客户端,用于执行部分重同步
char replrunid[REDIS_RUN_ID_SIZE+1]; /* master run id if this is a master */
// 从服务器的监听端口号
int slave_listening_port; /* As configured with: SLAVECONF listening-port */
// 最后被写入的全局复制偏移量
long long woff; /* Last write global replication offset. */
} redisClient;
下面我们对上面三个部分一一解释一下:
复制偏移量
执行复制的双方---主从服务器都会维护一个复制偏移量。
主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N。
从服务器每次接收到主服务器传播来的N个字节的数据时,就将自己的复制偏移量加上N。
通过对比主从服务器的复制偏移量,程序很容易知道主从服务器是否处于一致状态。
主从状态一致:
主从状态不一致:
假如从服务器A在断线后就立即重新连接主服务器,并且成功,那么接下来,从服务器将向主服务器发送PSYNC命令,报告从服务器A当前的复制偏移量为10086,那么这时,主服务器应该对从服务器执行完全重同步还是部分重同步?如果执行部分重同步的话,主服务器又如何补偿从服务器A在断线期间丢失的那部分数据呢?
复制积压区
复制积压区是由主服务器维护的一个固定长度的队列,默认大小为1M。
当主服务器进行命令传播时,它不仅将写命令发送给所有从服务器,还会将写命令入列到复制积压区缓冲区里面。如下图:
因此,主服务器的复制积压区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。