Redis的主从复制

Redis的主从复制

主从复制的作用

我们在刚开时使用Redis时都是单机测试的,但是生产环境中却不是这样子的,如果我们生产环境中单机部署了,就会遇到下面问题。

  • 1 机器故障:如果机器故障了,我们Redis是不是直接就挂了,数据将会丢失。
  • 2 容量瓶颈:如果Redis容量满了的话,Redis也是相当于挂了。

这时Redis给我们提供了一种主从复制的机制,我们可以部署多个Redis,这多个Redis共享同样的数据,这样就算一个Redis挂了,我们还有多台备份。

下面给出一个示例来表明这个关系。
Redis的主从复制
可以看到 master 是我们的主节点,slave 是从节点。我们在主节点执行上面两条命令,从节点去获取同样能获取得到数据。当然这里一个master可以有多个从节点,slave也可以有自己的从节点且同时共享一份数据。

这里需要注意的是:
一个master节点可以有多个slave
一个slave只能有一个master
数据流是单项的,只能从master到slave(数据拷贝)

如何实现
  • 1使用命令实现
    slaveof 命令:
    Redis的主从复制
    上图意思是 从节点6380 客户端向 节点6379发起成为从节点的请求,之后从节点就会向 节点6379发起文件拷贝。
    如果之后从节点要脱离主节点则可以使用slaveof no one
    Redis的主从复制
    在从节点断开之后原来从主节点复制过来的数据不会立刻得到清除,而是等到该从节点从新绑定主节点的时候才会进行一次清除。

  • 2 修改配置

    slaveof ip port # ipport 是需要绑定主节点的ip地址和端口
    slave-read-only yes #设置从节点是只读的
    这里设置从节点只读的目的是确保数据的一致性,因为数据是单向的,如果从节点插入数据了,那么主节点就不会知道。

  • 3 两者比较

    方式 使用命令 使用配置
    优点 无需重启 统一配置
    缺点 不便于管理 需要重启
全量复制和部分复制

这里先介绍变量
run_id:每个Redis在启动时都会有一个这样的id,我们的主从复制依赖与这个标实,当Redis重启时run_id会改变。
master-repl-offset:这个表示现在数据的偏移量,主从通过这个值是否相同来了解数据是否同步。

全量复制

在节点最开始进行从节点申请时就会默认执行一次全量复制。我们知道复制时从节点还不知道主节点的run_id,这时从节点会发出psync ? -1的命令去获取主节点的run_id,获取到之后就开始执行复制。具体的过程看下图。

psync ? -1 # ? 的意思是我第一次获取同步不知道run_id多少 -1是我当前文件偏移量
Redis的主从复制

解释下过程

  • 1 上面说了
  • 2 主节点发送run_id和偏移量给从节点。
  • 3 从节点保存主节点的信息。
  • 4 主节点开始异步RDB文件生成。(上章说明RDB文件的隐式触发)
  • 5 主节点发送RDB文件。
  • 6 在传送RDB文件时,可能还有数据记录,这时主节点会把记录存在repl_back_buffer中,后面在发送一次。
  • 7 从节点这时开始清除以前的数据,拥抱新主。
  • 8 加载RDB文件。

我们来分析下全量复制的开销

  • 1 bgsave时间,我们上一章节说了生成RDB文件是很消耗资源的。
  • 2 RDB文件的网络传输时间:RDB文件是很大的,这将占用很大一部分网络资源
  • 3 从节点清除数据时间:如果从节点上一个主的数据太多(很正常),这就要等待清除了。
  • 4 从节点加载RDB文件。
  • 5 在加载RDB文件后可能会执行AOF从写。
部分复制

我们知道全量复制的开销是很大的,如果有一种情况就是从节点和主节点因为网络关系断开了,这时从节点丢失了主节点的数据,那么我们还要进行一次全量复制吗?这就是部分复制出现的目的,在一些情况中把开销降到最低。

我们看看原理图
Redis的主从复制
解释下流程

  • 1 连接断开。
  • 2 主节点继续接收数据,并把数据存到repl_back_buffer
  • 3 当恢复时从节点请求从新连接主节点。
  • 4 连上之后从节点会发送此时的偏移量和run_id
  • 5 如果从节点和主节点偏移量的相差返回在repl_back_buffer之内,主节点将会执行第6步,如果超出这个范围,很遗憾就只能做全量复制了。
  • 6 主节点将缓存数据发送给从节点。
最后

文章开头讲了如何确保数据能够备份,但是出现问题如果我们手动去执行命令的话还是相当麻烦的。不过Redis也提供了一个机制帮我们去解决,就是当我们一个Redis发送故障了,它就会帮我们用其他的Redis顶上,这样少了手动操作的麻烦,又确保数据完整,是不是很棒,这就是我们下章学习的sentinel