一 概念
主从数据同步是指一个redis实例(主节点)将数据复制给一个或者多个reids实例(从节点)的过程,从而保证主从数据的一致性。
二 原因以及目的
因为主从模式的读写是分离的,写操作只能在主节点进行,读操作可以在主从节点进行,由于从节点不能进行写操作,所以只能通过与主节点进行数据同步来保证数据的一致性。
追问:为什么写操作不能在从节点进行?
如果同一个份数据有多次写操作,但是分布在不同节点上,当客户端进行读操作时,可能会读到旧值;如果在多节点上进行写操作,要让各节点上的同一份数据保持一致,需要通过加锁等操作来协调各个节点,带来巨大的开销,拉低了性能。
三 过程
- 从节点向主节点发送psync命令建立连接;psync 携带的参数是主节点的runid,以及当前从节点的复制进度offset,由于是第一次复制,所以此时主节点id用?表示,offset的值是-1,第一次复制是全量复制;
- 建立连接之后,直接点发送fullresync命令,携带主节点的runid以及当前的复制进度offset进度,从节点将该信息保存下来;
- 主节点执行bgsave命令,生成RDB数据快照,并将RDB文件发送给从节点,从节点接受到RDB之后,会先清除自己的数据,再加载RDB文件;
- 在生成RDB文件以及发送RDB文件给从节点这个过程中,主节点还是会响应客户端的操作,此时写操作会存进replication buffer缓存;(replication buffer是主节点为每个从节点开辟的独立缓存)
- 等待从节点RDB文件接收完毕,将replication buffer的写操作发送给从节点;从节点执行完写操作之后,第一次全量复制完成
- 此后主节点与从节点会保持一个长连接,主节点将接收到的数据陆续发送给从节点,进行数据同步,即长连接复制,避免频繁建立连接的开销。
四 网络断连怎么办
当主从连接断开之后,主从会采用增量复制的方式进行数据同步(redis2.8之前是全量复制,2.8之后是增量复制)主节点利用repl_backlog_buffer缓冲区进行增量复制,repl_backlog_buffer缓冲区是个环形缓冲区,默认大小为1M,它是所有从节点共享的缓存,主节点会记录自己写到的位置,各个从节点也会记录自己读到的位置。
过程
- 当主从库断连后,主库会把断连期间收到的写操作,写入replication buffer,同时也会把这些操作命令也写入repl_backlog_buffer缓冲区;
- 重新连接之后,从节点向主节点发送psync runid offset 命令,主节点判断接收的runid与自己的runid是否一致,且offset是否在repl_backlog_buffer中,若在则将offset之后的数据发送给从节点,完成增量同步;
- 若offset不在repl_backlog_buffer中,将进行全量复制。
追问:为什么offset会不在repl_backlog_buffer中
因为repl_backlog_buffer缓冲区是环形缓冲区,正常情况下主节点的写记录进度与从节点的读记录进度会基本保持一致,但断连时间过长,写记录进度“追上”读记录进度,即数据出现覆盖,这种情况就会发生全量复制。 为保证断连后少触发全量复制,在硬件允许的条件下,可以通过repl_backlog_size参数来调整缓冲区大小,尽可能缓存更多的数据。
五 启发
-
如果不可避免的会发生全量复制,一个主节点实例不要那么大,保持在几个GB就可以,这样可以避免RDB生成、传输、重新加载的开销;
-
就是上文提到的,可以通过repl_backlog_size参数来调整缓冲区大小尽可能缓存更多的数据,尽量减少在主从长时间断连而触发全量复制。