Redis 主从同步
本文将介绍 Redis 中主从模式时主机和从机之间进行数据同步的做法。
一、初次同步
1. 说明
当从机被指派 “附属于” 主机时,两个节点之间需要进行初次数据同步。
2. 具体流程
第一阶段:主从库建立连接、协商同步
从库给主库发送
psync ? -1
命令,表示要进行数据同步1
psync runID offset
- runID:每个 Redis 实例启动时自动生成的唯一 ID,用于唯一标识实例
- offset:写入位置
由于从库并不知道主库的 runID,因此设为 ?;
offset 设为 -1,表示第一次复制
主库收到 psync 命令后,会用 FULLRESYNC 命令将主库 runID 和 offset 发送给从库
从库接收 FULLRESYNC 命令,保存主节点信息
第二阶段:主库发送所有数据,从库接收数据并加载
- 主库执行 bgsave 命令,生成 RDB 文件,将其发送给从库
- 从库接收文件,清空当前数据库,加载 RDB 文件
第三阶段:主库发送新写命令给从库
- 在主库生成 RDB 文件的过程中,可能有新的写操作被执行,主库会在内存中用专门的 replication buffer 记录此过程中的所有写操作,并将其发送给从库
- 从库接收修改操作后执行,从而实现了主从库的同步
3. 性能消耗
在主从库的初次同步中,对于主库而言,有这两个影响性能的操作:
- 生成 RDB 文件:
fork()
操作会堵塞主线程,影响正常请求的处理 - 传输 RDB 文件:文件的传输会占用网络带宽
如果从库很多,并且都要和主库进行初次同步,这将给主库带来非常大的性能压力。
可以通过 “主 - 从 - 从” 模式解决这一问题,即从库不再都和主库连接,而是和其它从库连接。
二、持续同步
一旦主从库完成了初次同步,他们之间便会一直维护一个网络连接,主库会将后续的写命令同步给从库,这个过程也被称为 “基于长连接的命令传播”,
三、常见问题
1. 为什么初次同步不使用 AOF?
RDB 文件是经过压缩的二进制数据,相对更小;
而 AOF 文件是对写操作命令的记录,相对更大
在从库加载文件时,RDB 文件可以直接解析还原,速度更快;
AOF 文件需要依次重放每个命令,这个过程需要冗长的处理
2. 网络断连会怎么样?
如果网络断连,主从库之间的长连接将会断开,从库的数据自然也就没有办法和从库保持一致,这时候应该如何解决?
在 Redis 2.8 之前,主从库需要重新同步,开销非常大
在 Redis 2.8 之后,支持增量同步,主库可以在连接重新建立后将断连期间的命令发给从库同步,避免了重新同步
主库会维护一个 repl_backlog_buffer 环形缓冲区,将所有的命令存储于以循环队列中。主库会记录自己的写入位置,从库会记录自己的读入位置。
具体做法是:
- 当主从库连接恢复之后,从库会首先给主库发送 psync 命令,说明自己的写入位置(offset)
- 主库接收到 psync 命令后,会判断读入位置是否存在于循环队列,
- 如果不存在(读入位置已经被循环队列覆盖),则执行初次同步
- 如果存在,则执行持续同步
3. 为什么主机应该开启持久化?
假如主机未开启持久化且开启了自动重启,当主机崩溃以后,它将自动重启且因为没有初始化而数据清空,此时主从同步将导致从机上的数据也被清空。
参考
- Redis
- Redis 教程 | 菜鸟教程
- Redis数据库学习教程(快速入门版)
- Redis 核心技术与实战