首页 > 数据库 >Redis中的主从复制

Redis中的主从复制

时间:2024-06-08 18:58:46浏览次数:17  
标签:主从复制 Redis 复制 全量 offset 数据 节点

分布式系统中的几种Redis部署方式

为了解决一个程序只部署在一个服务器上的单点问题:

  1. 可用性问题,如果这个机器挂了,就意味着服务就中断了

  2. 一个程序只部署在一台机器上,它的性能/支持的并发量也是有限的

所以,就引入了分布式系统。在分布式系统中,往往希望有多个服务器来部署Redis服务,从而构成一个Redis集群,这样就可以让这个集群给整个分布式系统中的其他服务,提供更稳定/更高效的数据存储功能。

主从模式

在一个集群中,有的是主节点,有的是从节点。从节点的数据要跟随主节点变化,从节点的数据要和主节点保持一致。

本来,在主节点上保存的所有数据,在引入从节点之后,就要把主节点上的数据复制出来,放在从节点中,后续,主节点对于数据有任何的修改,都会把这样的修改同步到从节点上。

从节点就是主节点的副本。

Redis主从模式中,从节点上的数据,不允许修改,只能读取!

对于客户端发来的读取数据的操作,可以在主从节点中的任意一个节点中获取数据;对于写操作,则需要从主节点操作,或者从节点告知主节点进行操作,这样也就提高了性能和并发量。

对于之前的单个Redis服务器节点,如果机器挂了,整个Redis就挂了。但现在可以有多个节点,也可以把这些节点放在不同的机房中,这样就不会出现所有节点同时挂掉的情况。如果挂掉的是某一个从节点,不影响读写操作,如果挂掉的是主节点,则只能进行读操作。一定程度上提高了可用性。

更准确的说,主从模式,主要是针对读操作进行并发量和可用性的提高;对于写操作,无论是可用性还是并发,都非常依赖主节点,而且主节点只能有一个。好在实际业务场景中,读操作往往比写操作更频繁。

主节点上会收到源源不断的修改数据的请求,从节点需要从主节点这里同步这些修改请求。但是,从节点和主节点之间的数据同步,不是瞬间完成的。

每一个从节点中都会有一个offset字段,用来记录同步数据的进度

主从复制中的拓扑结构(若干节点之间,按照什么样的方式进行组织连接):

一主一从

一个主节点连接一个从节点,主节点和从节点都可以处理读数据请求,只有主节点可以处理写数据请求。

如果写数据请求太多,也会给主节点造成压力,这时可以关闭主节点的AOF,只在从节点上开启AOF,让主节点只操作内存中的数据,减少IO操作。

缺点在于,这种模式下,主节点一旦挂了,就不能让他自动重启,因为没有AOF文件,如果自动重启,就会丢失数据,进一步的主从同步,会把从节点的数据也删除掉。

改进办法:主节点挂了之后,让其从从节点获取到AOF文件,再启动。

一主多从

因为实际的开发中,读请求往往远远超过写请求,所以应该适量增加从节点的数量以提高效率

主节点上的数据发生改变,会把改变的数据同时同步给所有从节点。

但是,随着从节点的数量增多,主节点要同步一条数据就需要传输多次,所以往往需要增加主节点的网络带宽,增大了成本。

树形结构

这种结构,不要求主节点有太高的网络带宽,从节点也可以帮助数据同步,但是进行数据修改时,同步的延时更长了。

主从复制流程

数据同步的方法

Redis提供了psync命令,可以完成数据同步的过程。

这个命令不需要手动执行,Redis服务器会在建立好主从同步关系之后,自动执行psync(从节点执行psync,从节点从主节点拉取数据)。

进行数据复制,需要从节点在与主节点建立好复制关系之后,从主节点获取到replication id(复制ID)。这个ID是主节点启动时自动生成的,每个主节点每次重启得到的ID都是不同的。根据这个ID就可以知道当前从节点是从哪个主节点复制的数据(在集群中会有多个主节点)。

每一个节点中都还会有一个offset值,对于主节点,每次有新的修改数据的操作时,都会在这个值原来的基础上增加;对于从节点,每同步一部分主节点中的数据,这个值也会增加,当从节点中的offset值跟主节点中的offset值相等时,就证明数据同步完成。

replication id 和 offset 共同描述了一个“数据集合”

如果有两个机器,replication id 一样,offset 也一样,就可以认为这两个 redis 机器上存储的数据是完全一样的。

psync运行流程:

  1. 从节点发送 psync 命令给主节点,replid 和 offset 的默认值分别是?和-1.

  2. 主节点根据 psync 参数和自身数据情况决定响应结果:

  • 如果回复 +FULLRESYNC replid offset,则从节点需要进行全量复制流程

  • 如果回复 +CONTINUE,从节点进行部分复制流程

  • 如果回复 -ERR,说明Redis主节点版本过低,不支持 psync 命令,从节点可以使用 sync 命令进行全量复制

psync 可以从主节点获取全量数据,也可以获取一部分数据,具体区别于 offset 的进度。

如果 offset 为-1,则获取全量数据;如果是具体的整数,则从当前偏移量位置进行获取部分数据。

复制全量数据会有比较大的消耗,所以一般还是部分数据复制更好,但是如果主节点本身并不适合部分复制,就会仍然给从节点进行全量复制。

较老的版本的Redis不支持psync,可以用sync代替,不过后者会阻塞其他操作,所以不建议使用。

一般什么时候会进行部分复制?

从节点之前已经从主节点上复制过数据了,但因为网络抖动导致从节点重启了,这时需要重新行主节点同步数据,在大部分数据已经同步的情况下,希望只同步一小部分未复制的数据。

全量复制流程

  1. 从节点发送 psync 命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的运行 ID 和复制偏移量,所以发送 psync ? -1。

  2. 主节点根据命令,解析出要进行全量复制,回复 +FULLRESYNC 响应。

  3. 从节点接收主节点的运行信息进行保存。

  4. 主节点执行 bgsave 进行 RDB 文件的持久化。

  5. 主节点发送 RDB 文件给从节点,从节点保存 RDB 数据到本地硬盘。

  6. 主节点将从生成 RDB 到接收完成期间执行的写命令,写入缓冲区中,等从节点保存完 RDB 文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照 RDB 的二进制格式追加写入到收到的 RDB 文件中,保持主从一致性。

  7. 从节点清空自身原有数据。

  8. 从节点加载 RDB 文件得到与主节点一致的数据。

  9. 如果从节点加载 RDB 完成之后,并且开启了 AOF 持久化功能,它会进行 bgrewrite 操作,得到最近的 AOF 文件。

第四步中,使用 RDB 是因为二进制节省空间,不能使用已有的 RDB 文件,而要重新生成,是因为已有的文件和当前的最新数据可能存在较大差异。

上述由主节点向从节点传送数据使用的是 RDB 文件,要写入文件就要有IO操作,效率就会降低。所以,为了保证效率,Redis 主节点进行全量复制的时候,也支持“无硬盘模式”(diskless),也就是主节点生成的 RDB 的二进制数据,不再直接保存到文件中,而是直接进行网络传输。同样的,从节点也不需要先把接收到的数据写入硬盘,然后再加载,而是直接把收到的数据写入内存。

但是,即使引入了无硬盘模式,整个操作仍然是比较重量级的,比较耗时的,网络传输是无法省去的,所以效率也并没有提升很多。

关于 replication id 和 runid

具有主从关系的节点之间的 replication id 是相同的,但是每个节点的 runid 都是不同的。

runid 主要用于支撑实现 Redis 哨兵的功能,和主从复制没什么关系。而 replication id 在上文中也表明,它主要是用于主从复制。

部分复制流程

  1. 当主从节点之间出现网络中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并中断复制连接。

  2. 主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区(一个基于数组实现的环形队列)中。

  3. 当主从节点网络恢复后,从节点再次连接上主节点。

  4. 从节点将之前保存的 replication 和 offset 作为 psync 的参数发送给主节点,请求进行部分复制。

  5. 主节点接到 psync 请求后,进行必要的验证,随后根据 offset 去复制积压缓冲区查找合适的数据,并响应 +CONTINUE 给从节点。

  6. 主节点将需要从节点同步的数据发送给从节点,最终完成一致性。

上文中提到的“主节点有时候会判定适不适合进行部分复制,不适合的话就进行全量复制”,其实指的是,从节点虽然之前进行过数据复制,但是后续需要复制的数据已经超出积压缓冲区中的数据了,这时只把积压缓冲区中的数据发送给从节点是不够的,所以只能进行全量复制。

实时复制

  • 全量复制:从节点刚连上主节点之后,进行的数据初始化工作。

  • 部分复制:全量复制的特殊情况,优化手段,目的和全量复制一样。

  • 实时复制:从节点已经和主节点同步好了数据,但是之后主节点会源源不断地收到新的修改数据的请求,主节点上的数据就会随之改变,这些数据也同样需要同步给从节点。

实时复制需要主从节点之间建立 TCP 长连接,随后主节点把自己收到的修改数据的请求发送给从节点,从节点再根据这些修改请求修改内存中的数据。

在进行实时复制时,需要保证连接处于可用状态,所采用的是“心跳包”机制。

  • 主节点:默认每隔10秒给从节点发送一个 ping 命令,从节点收到就返回 pong

  • 从节点:默认每隔1秒给主节点发起一个特定的请求,上报当前从节点复制数据的进度(offset)

标签:主从复制,Redis,复制,全量,offset,数据,节点
From: https://blog.csdn.net/m0_62618590/article/details/139549938

相关文章

  • Redis-10-分布式锁.md
    参考:分布式锁介绍1.概念额,为什么的话,建议先了解下我这篇文章。Java-并发-并发的基本概念我们在并发场景下,区分一个场景是否有并发问题,个人理解,锁的场景需要考虑:共享:是否共享某个资源竞态:如何构建竞态关系首先,我们得拎清楚它到底会不会共享,不是说多线程它就必然要有并发......
  • Redis持久化机制:RDB与AOF的原理和最佳实践
    简介A.Redis持久化概念简介 Redis,作为一个高性能的内存键值数据库,其默认操作都是在内存中进行的,这意味着数据的读写速度非常快。然而,由于Redis是基于内存的,所以在服务器宕机或重启的情况下,未经特殊处理的数据将会丢失。为了解决这一问题,Redis提供了持久化功能,以允许数......
  • redis zset源码
    zset底层是由hash字典和跳表实现的,字典存储member->分数的映射关系,这样根据membe查询score的时间复杂度O为1跳表可以理解为多个层级的有序链表,每个节点可能在不同层级上,通过在不同层级的跳跃查找,把查询时间复杂度降低到Olgn1.随机层数,只有0.25的概率升级层数,最多64层50%概率......
  • 使用Redis计算两点经纬度距离
    Redis的GEO特性允许您存储地理位置信息并执行地理空间查询。这其中包括了计算两个地理位置之间的距离。以下是如何使用Redis中的相关命令来执行这项任务的详细解释。案例:步骤1:添加地理位置数据使用GEOADD命令向Redis添加地理位置数据。例如,我们添加两个城市的经纬度:GEOAD......
  • 基于SpringBoot+Mybatis+Redis的问答社交网站项目(免费提供全部源码)
    下载地址如下:基于SpringBoot+Mybatis+Redis的问答社交网站项目(免费提供全部源码)资源-CSDN文库项目介绍项目背景随着互联网的普及和社交媒体的快速发展,用户对于在线交流和信息分享的需求不断增加。问答社交网站作为一种新型的社交平台,为用户提供了一个交流知识、解决问题和......
  • 【Redis】Redis主从复制(一)————主从搭建
    目录背景主从复制主从复制的工作流程主从复制的优点配置redis主从结构复制配置文件,修改配置主从结构启动redis服务备注查看复制状态背景单节点服务器的问题问题:可用性:如果这个机器挂了,意味着服务就中断了.性能:支持的并发量也是比较有限的.解决思路:引入分布......
  • 头歌初识redis答案
    头歌初识Redis的答案可以从多个方面进行归纳和总结。以下是根据参考文章提供的信息,按照清晰、分点表示和归纳的方式给出的答案:一、Redis基础知识Redis有16个数据库,默认使用第0个数据库,可以用select命令进行切换。Redis是基于内存操作的,其性能瓶颈不是CPU,而是机器的内存和......
  • Redis实战——创建账户及连接数据库
    一、创建一个新账户要创建一个带有免费数据库的新账户,请按照以下步骤操作:前往RedisCloud的注册页面。有两种开始使用RedisCloud的选项:在表单中输入您的信息,然后选择“GetStarted”(开始使用)。使用Google或Github账户进行注册。  3.在您输入信息后,您应该会收......
  • Java (Redis)
    前沿让我们来学习下Redis吧 官网下载客户端https://app.redislabs.com/#/rlec-downloads  什么是Redis?Redis(RemoteDictionaryServer)是一个开源的、高性能的、基于内存的键值存储系统。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。由于其基于......
  • 福州大学苏立超老师《大数据库系统》第三章复习提纲“redis”
    第三章(考点:3.3-3.7数据类型与操作(会写会熟练使用)消息订阅持久化主从复制运维和哨兵怎么配,作用)一.通用命令设置setkeyvalue查询keyskey(*)支持模糊查询*任意多个字符;[]括号内某个字符;?单个字符randomkey随机keyexistskey判断是否存在typekey返回类型delke......