redis主从同步原理---原生以及 基于binlog的主从同步不
1. 背景
上半年我们使用RocksDB做存储引擎,实施了Redis数据实时落地的项目,实现了在兼容redis协议的前提下,管理超出内存大小的数据集。
在主从同步方面,我们沿用了Redis原有的方案,该方案在实际运营中应对不良的网络状况显得很无力,因此我们在数据落地的基础上,为Redis开发了一套新的主从同步机制。
数据集的point-in-time的快照;增量数据则从快照完成的瞬间算起。如图(一),

图 (一) Redis原生主从同步机制
slave给master发送sync命令请求同步数据,master收到sync命令后,将内存数据镜像(point-in-time)保存为dump.rdb文件,同时将新进来的写请求保存到client-buffer中;master首先将生成的内存镜像文件dump.rdb同步给slave(全量数据同步),完成后,将client-buffer中累积的写请求同步slave(增量数据同步)。这个机制足够简单,但是在实际运营中会遇到一些问题:
- slave一旦同master断开,重连后如果不能做psync(实际运营中psync基本没有成功过),就要同步master的全量数据
- 实际运营中一般会做多实例部署,一台Z3服务器部署20 - 40 不等的实例数,一旦网络闪断,导致几十个master实例同时fork做bgsave,场面感人; 通常结果就是内存不够,做bgsave的进程被kill掉
- 如果同步全量数据时,master实例上写请求量大,使client-buffer占用内存超限,master会主动断开和slave的连接,这样之前的全量数据就白做了
这里的根本矛盾是Redis本身定位和我们的要求有偏差。Redis所有操作都是基于内存, 数据存在内存,用于断开重连的backlog保存在内存,主从同步时的增量数据保存在内存,可每台服务器内存就那么多,能存储的数据量是有限的;而我们在更多场景下,要求Redis在提供足够性能的前提下,存储尽量多的数据。我们需要在性能和数据量,以及可运营性之间做折中。