欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Redis 的主从同步(复制)

程序员文章站 2022-06-13 22:05:17
Redis 的主从同步(复制) Redis 的主从同步(复制) 什么是主从同步(复制) 假设有两个 redis 实例 ⇒ A 和 B B 实例的内容与 A 实例的内容保持同步 那么称 A 实例是主数据库,B 实例是从数据库 这个过程称为主从同步 为什么要使用主从同步(复制) 防止发生单点故障 扩展内 ......

redis 的主从同步(复制)

redis 的主从同步(复制)

什么是主从同步(复制)

假设有两个 redis 实例 → a 和 b

b 实例的内容与 a 实例的内容保持同步

那么称 a 实例是主数据库,b 实例是从数据库

这个过程称为主从同步

为什么要使用主从同步(复制)

  1. 防止发生单点故障
  1. 扩展内存

如何开启/关闭主从同步

开启同步

  • 配置文件中加入
slaveof 主数据库地址 主数据库端口
  • 在命令行中执行上述命令
redis> slaveof 主数据库地址 主数据库端口
  • 在开启从服务器时执行命令
$ reids-server --port 6380 --slaveof 主数据库地址 主数据库端口

关闭同步,并成为主数据库

redis> slaveof no one

原理(实现)

复制分为连接建立,数据同步(sync)和命令传播(command propagate)三个阶段

连接建立这里不说,与复制原理无关

下面主要讲数据同步与命令传播两个阶段

redis 从 2.8 版本之后优化了复制功能,咱们先从旧版本的复制说起:

旧版复制过程

步骤 主服务器 从服务器
   
  向主服务器发送 sync 命令
收到 sync 命令,执行 bgsave 生成 rdb 文件  
使用缓冲区记录从现在的写命令  
将生成的 rdb 文件发送给从服务器  
将缓冲区内的写命令发给从服务器 接收并载入 rdb 文件
  接收并执行主服务器发送来的写命令
   
发送客户端发过来的写命令  
  执行主服务器发送过来的写命令
与同步流程一致 与同步流程一致

经过上述步骤之后主从服务器的状态可以始终保持一致。

细心的读者已经发现了旧版复制的一些问题:

断线重连需要重新走一次同步的流程,而同步流程中的主服务器生成 rdb 文件和从服务器执行 rdb 文件都是特别密集的 io 操作,这会让断线重连的成本很高

于是从 2.8 版本之后,redis 使用了新的技术来防止重新执行同步流程

新版复制过程

步骤 主服务器 从服务器
   
  向主服务器发送 psync 命令
收到 psync 命令,执行 bgsave 生成 rdb 文件  
使用缓冲区记录从现在的写命令  
  接收并执行主服务器发送来的写命令
将缓冲区内的写命令发给从服务器 接收并载入 rdb 文件
将生成的 rdb 文件发送给从服务器  
   
发送客户端发过来的写命令  
  执行主服务器发送过来的写命令
   
  发送 psync 命令
向从服务器发送断线过程中的写命令  
  执行写命令

新版复制经过上述步骤,也可以实现主从数据库状态的一致。

在断线重连过程中,只需要重新执行断线过程中未同步的命令即可,这样就比旧版的复制节省了很多 io 操作

那么这个断线重连的是怎么实现的呢?

部分重同步(断线重连)的实现

redis 的部分重同步借助了4个变量:

  1. 服务器的运行 id (run id)
    • 当实例重启时,会生成40个随机的十六进制字符
  1. 主服务器的复制积压缓冲区(replication backlog)
    • 主服务器每将一个命令传送给从数据库,都会将命令放到一个积压队列(固定长度的循环队列)中
  1. 主服务器的复制偏移量(replication offset)
    • 主服务器将命令放到积压队列中时,会记录下当前命令的偏移量,并发送给从服务器
  1. 从服务器的复制偏移量
    • 从服务器接收到主服务器发送过来的命令与偏移量

 

也许将这4个变量列出来之后,有读者就可以直接想象出来是怎么实现的了,对,没错,就是这么实现的

过程:

部分重同步流程

步骤 主服务器 从服务器
  发送命令 psync 主数据库的运行id 断开前最新的命令偏移量
  判断 1. 运行id是否能够对应 2. 断开前最新的命令偏移量是否在队列中 满足上述条件可以执行部分重同步,否则执行完全同步  
发送给从数据库偏移量之后的命令  
  执行命令

总结

redis 在很多细节上优化了性能,主从同步(复制)的优化只是其中的一方面。