主要研究一个参数:repl-backlog-size,通过调整该参数以充分利用部分重新同步的优势来实现更好的主从复制性能。
实验步骤:
切断主从之间的网络连接,在网络连接断开期间,在主实例生成一些测试数据,然后恢复网络连接,这时候观察两个Redis实例的日志
结论
在上面的实验步骤中可以发现,不同大小的测试数据会引发不用类型的数据重新同步。当数据量较小时采用的部分重新同步,而数据量较大的时候采用的完全重新同步。发生这种情况的原因是,在Redis主实例与从实例网络断开期间,主实例的一段内存(一个环形缓冲区)会跟踪最近所有的写入命令。这个缓冲区实际是一个固定长度的列表。
在Redis中,这个缓冲区称为replication backlog。Redis使用这个backlog缓冲区来决定究竟进行完全重新同步还是部分重新同步。在发出SLAVEOF命令后,从实例使用最后一个offset和最后一个主实例ID(master_replid)向主实例发送一个部分重新同步请求。当主实例和从实例之间建立连接后,主实例会检查请求中的master_replid是否与它自己的master_replid一致。然后主实例会检查请求中的offset能否从backlog缓冲区中获取。如果offset位于backlog的范围内,那么就可从中获得连接断开期间的所有写入命令,这时候就会进行部分重新同步,否则,如果主实例在连接断开期间接收到了写入命令的数据量超过了backlog缓冲区的容量,那么部分重新同步请求会被拒绝,此时,完全重新同步就会被启动。
默认情况下,backlog缓冲区的大小为1MB,这个容量在连接断开期间只能容纳少量的写入命令。
在主实例与从实例之间网络连接断开时,backlog缓冲区默认大小并不能应对高写入流量的情况,在多数情况下,我们需要把这个参数进行调整为更高的值满足需求。可以通过峰值期间使用INFO命令计算master_repl_offset的变化量,可以估算backlog缓冲区的合适大小:
t*(master_repl_offset2-master_repl_offset1)/(t2-t1)
我们也可以使用这个公式来估算主实例和从实例之间的网络流量。
一般来说,这个值设置为比RDB快照大小还大的值是毫无意义的。
有关backlog的另一个参数repl-backlog-ttl。该参数的含义是:如果所有的从实例与主实例的连接全部断开后,那么主实例等待多久释放backlog占用的内存。该参数的默认值为:3600s。一般这个数字不会有什么问题,因为与Redis实例占用的内存相比backlog缓冲区是非常小的。
处理backlog的大小之外,还有一些其他的配置在某些情况下进行调优以获得更好的性能,从网络传输的角度看,我们可以通过设置参数repl-disable-tcp-nodelay设置为yes来减少宽带的使用,如果设置为yes,Redis会将几个小包合成一个包,这个在主实例和从实例位置相距较远的情况下有些作用,但是需要注意的是,这个选项可能造成约40毫秒的复制延迟。