侧边栏壁纸
  • 累计撰写 247 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Redis 主从同步底层实现原理和架构演进

kaixindeken
2021-07-28 / 0 评论 / 0 点赞 / 94 阅读 / 1,354 字

主从同步底层原理

对于主库和从库的第一次同步,需要经过三个阶段完成。

在第一阶段,需要建立主库和从库的连接并协商同步的起始位置,为下一步全量同步做准备。具体实现是在从库执行 psync 命令表示需要进行主从同步,并在参数中指定主库的 runID 和偏移位置 offset:

  • runID:每个 Redis 实例启动时都会自动生成一个随机 ID,用来唯一标记这个实例。当从库和主库第一次同步时,因为不知道主库的 runID,所以将其设置为 ?;
  • offset:第一次同步设置为 -1。
    主库收到从库发送的 psync 命令后,会通过 FULLRESYNC 响应命令带上两个返回参数:主库的 runID 和主库目前的复制进度 offset,从库收到主库响应后,会记录下这两个参数。

这里的 FULLRESYNC 表示要进行一次全量同步,也就是基于 RDB 日志的快照同步。全量同步是一个非常消耗系统资源的操作,因为主库会基于当前数据执行 bgsave 进行一次 RDB 快照,再将快照文件的内容同步给从库(操作指令,而非数据),从库接收完所有快照内容后,先清空原来的数据库,然后进行一次全量加载(执行所有快照指令),这就是主从同步第二阶段要做的事情。

从库完成全量加载后,会通知主库进行增量同步,因为第二阶段无论是主库进行 RDB 快照,还是从库进行全量加载,都不会阻塞主库继续处理客户端请求,这就可能会产生一些增量更新指令,为了确保主从数据的最终一致性,Redis 专门提供了一个 replication buffer 来保存这些操作指令。

在主从同步的第三阶段,也就是主库收到从库全量同步完成的通知后,会把 replication buffer 中存放的指令同步给从库,进行增量同步,完成主从数据的一致性。

replication buffer

需要注意的是,和 MySQL 的 Buffer Pool 和 Redo Log Buffer 类似,存储在内存中的 replication buffer 大小也是有限制的,不过 MySQL 除了内存之外,还会借助磁盘进行存储,所以超出限制后可以采用刷新算法将缓冲数据刷新到磁盘,Redis 则不然,除了持久化必须借助磁盘外,其他操作基本都是在内存中完成的,因为在 Redis 里面,性能是第一考量因素。

为此,Redis 将 replication buffer 数据结构设计成了定长环形数组:

1.jpeg

如果数组内容满了,就会从头开始覆盖前面的内容,所以需要合理的设置这个 buffer 的大小。

如对于普通客户端(normal),配置值为 0,表示不做限制;对于从库客户端(replica),大小限制是 256 MB,如果持续 60s 超过 64 MB,则关闭客户端连接;对于发布订阅客户端(pubsub,如广播),大小限制是 32 MB,如果持续 60s 超过 8 MB,则关闭客户端连接。

主从同步架构优化

可以看到,对于主从同步而言,最耗时的莫过于全量同步这一环节了,因为无论是 RDB 快照生成还是传输,都是在主库完成的,如果从库数量很多,则主库就疲于应付 RDB 快照的生成和传输了,这会影响到 Redis 主库处理客户端写操作的性能,为了分担主库压力,Redis 提供了对「主-从-从」架构的支持,即将主库的从库与下一级从库建立主从同步关系:

1.jpeg

当然,这并不意味这从库变成主库了,它只是承担了主从同步这一职责而已,所有的写操作还是在真正的主库执行的:

1.jpeg

0

评论区