# 数据同步：主从库如何实现数据一致？

![](https://z3.ax1x.com/2021/07/31/WvPtQU.png)

# 核心知识提炼

## 1、Redis 的高可靠性

- 数据尽量少丢失：AOF 和 RDB。
- 服务尽量少中断：增加冗余备份。

## 2、为什么有主从模式？

保证数据副本一致。

## 3、主持模式背后是什么？

**读操作：**主库、从库都可以接受。

**写操作：**首先到主库执行，然后，主库将写操作同步给从库。

为什么要采用读写分离？

- 所有数据的修改只会在主库上进行，不用协调其它实例。
- 主库有了最新的数据之后就会同步给主库，这样主从库的数据就是一致的。

## 4、主从库如何进行第一次同步？

- 第一阶段：建立连接，协商同步。
- 第二阶段：主库同步数据给从库。
- 第三阶段：主库发送新写命令给从库。

## 5、主从级联模式分担全量复制的主库压力

如果从库比较多，都要和主库进行全量复制的话，就会导致主库忙于 fork 子进程生成 RDB 文件，进行数据全量同步。

fork 操作会阻塞主线程处理正常请求。从而导致主库响应应用程序的请求速度变慢。

因此，有一种 “主-从-主” 模式来分担主库压力。

以级联的方式分散到从库上。

![](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/redis0603.png)

## 6、如果主从库网络断了怎么办？

Redis 提供了增量复制。

从 Redis 2.8 开始，网络断了之后，主从库会采用增量复制的方式继续同步。

听名字大概就可以猜到它和全量复制的不同：全量复制是同步所有数据，而增量复制只会把主从库网 络断连期间主库收到的命令，同步给从库。

这里的奥妙就在于 repl_backlog_buffer 这个缓冲区。

> 当主从库断连后，主库会把断连期间收到的写操作命令，写入 replication buffer，同时也会把这些操作命令也写入 repl_backlog_buffer 这个缓冲区。 
>
> repl_backlog_buffer 是一个环形缓冲区，主库会记录自己写到的位置，从库则会记录自己 已经读到的位置。

![](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/redis0604.png)

![](https://cdn.jsdelivr.net/gh/rongweihe/ImageHost01/redis0605.png)

# 总结

Redis 的主从库同步的基本原理，总结来说，有三种模式：

- 全量 复制
- 基于长连接的命令传播
- 以及增量复制。

全量复制虽然耗时，但是对于从库来说，如果是第一次同步，全量复制是无法避免的。

所以，注意生产线上，一个 Redis 实例的数据库不要太大，一个实例大小在几 GB 级别 比较合适，这样可以减少 RDB 文件生成、传输和重新加载的开销。

另外，为了避免多个从库同时和主库进行全量复制，给主库过大的同步压力，我们也可以采用“主 - 从 - 从”这 一级联模式，来缓解主库的压力。

长连接复制是主从库正常运行后的常规同步阶段。在这个阶段中，主从库之间通过命令传 播实现同步。不过，这期间如果遇到了网络断连，增量复制就派上用场了。

增量复制中有一个参数特别需要注意：repl_backlog_size 这个配置参数。如果它配置得过小，在增量复制阶段，可能 会导致从库的复制进度赶不上主库，进而导致从库重新进行全量复制。

所以，通过调大这个参数，可以减少从库在网络断连时全量复制的风险。

参考：《极客时间-Redis核心技术和实战》