大数据求索(15): Redis的复制原理详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wen_fei/article/details/85926045

大数据求索(15): Redis的复制原理

一、Redis中的复制

基于Redis的复制,可以非常容易的配置和实现主从复制:从节点成为主节点的精确副本。Redis能够实现在连接断开时,从节点自动尝试连接主节点,并进行部分同步,使和主节点数据保持一致。在主从复制模式下,Master以写为主,Slave以读为主。

Redis中的复制的正常运行主要依赖下面三种机制:

  • 当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave :包括客户端的写入、key 的过期或被逐出等等。
  • 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是master或slave检测到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流,即只同步断开这段时间没有同步的部分。
  • 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。

redis使用默认的异步复制,其特点是高延迟和高性能,是绝大多数 Redis 用例的主要复制模式。但是,从 redis 服务器会异步地确认它从主 redis 服务器周期接收到的数据量。因此,主redis服务器不会每次等待从redis服务器的处理命令。这是可配置的,主redis服务器可以知道从redis服务器已经处理了什么命令。

客户端可以使用 WAIT 命令来请求同步复制某些特定的数据。但是,WAIT 命令只能确保在其他 Redis 实例中有指定数量的已确认的副本,它不会将一组redis服务器实例转换为具有强一致性的CP(参考CAP理论)系统。简单来说,就是无法保证其他从redis服务器也进行了同步。也就意味着在故障转移期间,由于不同原因的故障转移或是由于 Redis 持久性的实际配置,故障转移期间确认的写入操作可能仍然会丢失。

二、Redis复制的重要概念

  • Redis 使用异步复制,slave 和 master 之间异步地同步数据
  • 一个 master 可以拥有多个 slave
  • slave 可以接受其他 slave 的连接。除了多个 slave 可以连接到同一个 master 之外, slave 之间也可以像层叠状的结构(cascading-like structure)连接到其他 slave 。自 Redis 4.0 起,所有的 sub-slave 将会从 master 收到完全一样的复制流
  • Redis 复制在 master 端是非阻塞的。这意味着 master 在一个或多个 slave 进行初次同步或者是部分重同步时,可以继续处理查询请求。
  • 复制在 slave 端大部分也是非阻塞的。当 slave 进行初次同步时,假设在redis.conf中进行了配置,它可以使用旧数据集处理查询请求。否则,可以配置如果复制流断开, Redis slave 会返回一个 error 给客户端。但是,在初次同步之后,旧数据集必须被删除,同时加载新的数据集。 slave 在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自 Redis 4.0 开始,可以配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞 slave 。
  • 复制既可以被用在实现可伸缩性,以便可以有多个 slave 进行只读查询(例如 O(N) 复杂度的慢操作可以被下放到 slave ),或者仅用于保证数据安全实现高可用
  • 可以使用复制来避免 master 将全部数据集写入磁盘造成的开销:一种典型的技术是配置 master Redis.conf 以避免对磁盘进行持久化,然后连接一个 slave ,其配置为不定期保存或是启用 AOF。但是,这个设置必须小心处理,因为重新启动的 master 程序将从一个空数据集开始:如果一个 slave 试图与它同步,那么这个 slave 也会被清空。

三、Redis复制的工作原理

每一个 Redis master 都有一个 replication ID,它是一个较大的伪随机字符串,标记了一个给定的数据集。每个 master 也持有一个偏移量,master 将自己产生的数据流复制发送给 slave 时,发送多少个字节的数据,自身的偏移量就会增加多少。目的是当有新的操作修改自己的数据集时,它可以以此更新 slave 的状态。复制偏移量即使在没有一个 slave 连接到 master 时,也会自增,所以基本上每一对给定的Replication ID, offset都会标识一个 master 数据集的确切版本。

当 slave 连接到 master 时,它们使用 PSYNC命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。通过这种方式, master 能够仅发送 slave 所需的增量部分。但是如果 master 的缓冲区中没有足够的命令积压缓冲记录,或者如果 slave 引用了无法获知的历史记录(replication ID),则会转而进行一个全量重同步:在这种情况下, slave 会得到一个完整的数据集副本,从头开始。

下面是一个全量同步的工作细节:

master 开启一个后台保存进程,以便于生产一个 RDB 文件,同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时, master 将数据集文件传输给 slave, slave将之保存在磁盘上,然后加载文件到内存。再然后 master 会发送所有缓冲的命令给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。

事实上 SYNC 是一个旧协议,在新的 Redis 实例中已经不再被使用,但是其仍然向后兼容:但它不允许部分重同步,所以现在 PSYNC 被用来替代 SYNC。之前说过,当主从之间的连接因为一些原因崩溃之后, slave 能够自动重连。如果 master 收到了多个 slave 要求同步的请求,它会执行一个单独的后台保存,以便于为多个 slave 服务。

无需磁盘参与的复制

正常情况下,一个全量重同步要求在磁盘上创建一个 RDB 文件,然后将它从磁盘加载进内存,然后 slave以此进行数据同步。如果磁盘性能很低的话,这对 master 是一个压力很大的操作。Redis 2.8.18 是第一个支持无磁盘复制的版本。在此设置中,子进程直接发送 RDB 文件给 slave,无需使用磁盘作为中间储存介质。

复制原理总结

  • Slave启动成功连接到master后会发送一个sync命令
  • Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。
  • 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
  • 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
  • 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

四、Redis如何配置使用复制

使用时,一般遵循配从不配主的原则。在redis服务器上使用如下命令

slaveof 主库IP 主库端口

这种配置,每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件

配置文件需要修改的地方:

  • 拷贝多个redis.conf文件
  • 开启daemonize yes
  • 修改Pid文件名字
  • 指定不同的端口
  • 修改Log文件名字
  • 修改Dump.rdb名字

主从模式

一个Master两个Slave,此架构需要三个实例,一个Master两个Slave。配置好配置文件之后,分别启动。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

注意到三个客户端端口是不同的,此时没有指定master和salve,所以三个都是Master。

使用slaveof命令指定master,指定端口为6379的实例为master,在端口为6380和6381的实例客户端中输入

slaveof 127.0.0.1 6379,此时再通过info命令,可以发现只有一个master,另外两个变为了slave。
在这里插入图片描述

在这里插入图片描述

也可以通过日志查看。查看master日志:

在这里插入图片描述

查看slave日志:

在这里插入图片描述

链式传递

上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力。中途变更转向:会清除之前的数据,重新建立拷贝最新的。

停止同步

SLAVEOF no one使当前数据库停止与其他数据库的同步,转成主数据库

五、哨兵模式

slave自动版转为master,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

作用

  1. 监控redis进行状态,包括master和slave
  2. 当master down机,能自动将slave切换成master

在这里插入图片描述

如何使用

  • 三个配置文件

  • /myreids目录下新建sentinel.conf文件,文件名字绝不能错

  • 配置哨兵,填写内容

    sentinel monitor 被监控数据库名字(自己起名字) 127.0.0.1 6379 1

    数字1表示至少有多少个哨兵同意迁移的数量。网络是不可靠的,有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了,当sentinel集群式,解决这个问题的方法就变得很简单,只需要多个sentinel互相沟通来确认某个master是否真的死了。这个Number代表,当集群中有Nunber个sentinel认为master死了时,才能真正认为该master已经不可用了。(sentinel集群中各个sentinel也有互相通信,通过gossip协议)。

  • 启动哨兵

    Redis-sentinel /myredis/sentinel.conf

  • 当master挂掉以后,会投票选出新的master

    在这里插入图片描述

    思考一个问题,如果原来的master重新启动,会和现有的master冲突吗?

    答案是不会。原来的master重新启用以后变为了slave

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

原理

哨兵模式架构如下:

在这里插入图片描述

Sentinel集群对自身和Redis主从复制进行监控。当发现Master节点出现故障时,会经过如下步骤:

  1. Sentinel之间进行选举,在剩余活着的机器里选举出一个leader,由选举出的leader进行failover(故障迁移)
  2. Sentinel leader选取slave节点中的一个slave作为新的Master节点
  3. Sentinel leader会在上一步选举的新master上执行slaveof no one操作,将其提升为master节点
  4. Sentinel leader向其它slave发送命令,让剩余的slave成为新的master节点的slave
  5. Sentinel leader会让原来的master降级为slave,当恢复正常工作
  6. Sentinel leader会发送命令让其从新的master进行复制。上述的failover操作均有sentinel自己独自完成,完全无需人工干预

哨兵按照slave优先级选举leader,选取条件如下:

在这里插入图片描述

优先级在redis.conf中 slave-priority 100

偏移量是指获得原主redis 服务器数据量

每个redis实例启动后都会随机生成一个40位的runid

六、复制的缺点

由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

猜你喜欢

转载自blog.csdn.net/wen_fei/article/details/85926045
今日推荐