百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis(四):主从同步(redis主从一致)

mhr18 2024-10-25 12:40 22 浏览 0 评论

前三篇详细分析了redis的特性和核心原理,从本篇开始将对redis的部署结构和运行模式进行分析解读。真正生产环境当中我们基本不会使用单节点的redis来提供服务,至少是主从结构的哨兵或者集群模式,以保障redis服务的可靠性。本篇就来详细解读下redis的主从同步机制。

一、Redis主从有两种结构模型:


1.1 主从复制

一主N从的这种复制结构复制关系只有一级,也是使用最多的形式,通常搭建哨兵或者集群结构的redis都是采用的这种复制结构,能够通过一级从节点的复制关系很好的保证服务的可用性,做到异常情况主从切换。

1.2 级联复制

级联复制结构的复制关系可以有多级,一个主节点的从节点可以是下属从节点的主节点。级联复制结构的应用相对比较少,这种结构能够在有多个从节点的结构下一定程度上缓解主节点的复制压力。

二、Redis主从关系的建立

redis的主从同步始于命令SLAVEOF host port,通过这个命令能够建立主从关系,SLAVEOF 命令用于在 Redis 运行时动态地修改复制功能的行为。

通过执行 SLAVEOF host port 命令,可以将当前服务器转变为指定服务器的从属服务器(slave server)。如果当前服务器已经是某个主服务器(master server)的从属服务器,那么执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。

另外,对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。利用 SLAVEOF NO ONE 不会丢弃同步所得数据集这个特性,在没有搭建哨兵和集群的情况下,可以在主服务器失败的时候,将从属服务器用作新的主服务器,从而实现无间断运行。

下图为主从关系建立流程:

注意:

根据上执行流程这里有一个需要注意点,当我们对一个已有主从关系的节点执行slaveof命令时,会结束掉现有的主从关系并清空节点下的所以数据,在生成环境当中这是比较威胁的操作。有没有更安全的方式了?

上面介绍slavelof命令的时候提到可以传递NO ONE参数,也就是执行SLAVEOF NO ONE命令,这个命令是只会结束主从复制关系不会清空数据的,相对安全很多。

三、数据同步

建立好主从关系后就要进入主从数据同步的过程了,这里主要分三种情况,刚建立主从关系后的数据全量同步;初始化同步完成后的命令传播阶段;主从关系异常中断重连后的同步方式选择,这里会有全量和增量同步两种场景。

3.1 全量同步

  1. 当slave节点启动后或断开重连后(重连不满足增量同步条件),会向master数据库发送SYNC命令。
  2. master节点收到SYNC命令后会开始在后台保存快照(即RDB持久化,在主从复制时,会无条件触发RDB),并将保存快照期间接收到的命令缓存起来。
  3. master节点执行RDB持久化完成后,向所有slave节点发送快照RDB文件,并在发送快照期间继续记录被执行的写命令。
  4. slave节点收到快照文件后丢弃所有旧数据(会清空所有数据),载入收到的快照。
  5. master节点快照发送完毕、slave节点载入快照完毕后,master节点开始向slave节点发送缓冲区中的写命令。
  6. slave节点完成对快照的载入,开始接收命令请求,并执行来自主数据库缓冲区的写命令。(从数据库初始化完成)
  7. master节点每执行一个写命令就会向slave节点发送相同的写命令,slave节点接收并执行收到的写命令。(命令传播操作,slave节点初始化完成后的操作)

全量同步流程如下图:


在redis2.8之前,从节点无论是初始化还是断线重连后都是采用全量同步的方式,在2.8之后版本,引入PSYNC命令,在从节点断线重连后会判断是否采用增量同步。

3.2 增量同步

PSYNC具备了数据全量重同步和增量同步模式。

  1. 全量重同步:跟旧版复制基本是一致的,可以理解为“全量”复制。
  2. 部分重同步:salve断开又重新连时,在命令传播阶段,只需要发送与master断开这段时间执行的写命给slave即可,可以理解为“增量”复制。

PSYNC执行过程中比较重要的概念有3个:runid、offset(复制偏移量)以及复制积压缓冲区。

1.runid

每个Redis服务器都会有一个表明自己身份的ID。在PSYNC中发送的这个ID是指之前连接的Master的ID,如果没保存这个ID,PSYNC的命令会使用”PSYNC ? -1” 这种形式发送给Master,表示需要全量复制。

2.offset(复制偏移量)

在主从复制的Master和Slave双方都会各自维持一个offset。Master成功发送N个字节的命令后会将Master里的offset加上N,Slave在接收到N个字节命令后同样会将Slave里的offset增加N。

Master和Slave如果状态是一致的那么它的的offset也应该是一致的。

3.复制积压缓冲区

复制积压缓冲区是由Master维护的一个固定长度环形积压队列(FIFO队列),它的作用是缓存已经传播出去的命令。当Master进行命令传播时,不仅将命令发送给所有Slave,还会将命令写入到复制积压缓冲区里面。

PSYNC执行过程和SYNC的区别在于:salve连接时,判断是否需要全量同步,全量同步的逻辑过程和SYNC一样。PSYNC执行步骤如下:

  1. 客户端向服务器发送SLAVEOF命令,即salve向master发起连接请求时,slave根据自己是否保存Master runid来判断是否是第一次连接。
  2. 如果是第一次同步则向Master发送 PSYNC ? -1 命令来进行完整同步;如果是重连接,会向Master发送PSYNC runid offset命令(runid是master的身份ID,offset是从节点同步命令的全局迁移量)。
  3. Master接收到PSYNC 命令后,首先判断runid是否和本机的id一致,如果一致则会再次判断offset偏移量和本机的偏移量相差有没有超过复制积压缓冲区大小,如果没有那么就给Slave发送CONTINUE,此时Slave只需要等待Master传回失去连接期间丢失的命令。如果runid和本机id不一致或者offset差距超过了复制积压缓冲区大小,那么就会返回FULLRESYNC runid offset,Slave将runid保存起来,并进行全量同步。

主节点在命令传播时,主数据库会将每一个写命令传递给从数据库的同时,都会将写命令存放到积压队列,并记录当前积压队列中存放命令的全局偏移量offset。当salve重连接时,master会根据从节点传的offset在环形积压队列中找到断开这段时间执行的命令,并同步给salve节点,达到增量同步结果。

PSYNC执行流程如下图:

从以上PSYNC的执行流程可以看出当slave节点断线重连以后判断是否采用增量同步的核心是slave的offset偏移量和master的偏移量相差有没有超过复制积压缓冲区大小,那么这个大小是由以下参数来配置的。

复制积压缓冲区本质上是一个固定长度的循环队列,默认情况下积压队列的大小为1MB,可以通过配置文件设置队列大小:

设置复制积压缓冲区大小,积压队列越大,允许主从数据库断线的时间就越长

repl-backlog-size 1mb

Redis同时也提供了当没有slave需要同步的时候,多久可以释放环形队列,默认一小时,没有salve连接时,多久释放一次复制积压缓冲区

repl-backlog-ttl 3600


四、主从复制策略

Redis采用了乐观复制的策略,也就是在一定程度内容忍主从数据库的内容不一致,但是保持主从数据库数据的最终一致性。具体来说,Redis在主从复制的过程中,本身就是异步的,在主从数据库执行完客户端请求后会立即将结果返回给客户端,并异步的将命令同步给从数据库,但是这里并不会等待从数据库完全同步之后,再返回客户端。

这一特性虽然保证了主从复制期间性能不受影响,但是也会产生一个数据不一致的时间窗口,如果在这个时间窗口期间网络突然断开连接,就会导致两者数据不一致。如果不在配置文件中添加其他策略,那就默认会采用这种方式。为了防止主从不一致不可控,redis提供了以下两个参数来做约束:

min-slaves-to-write 3
min-slaves-max-lag 10

当slave数量小于min-slaves-to-write,且延迟小于等于min-slaves-max-lag时,master停止写入操作。

还有一个参数也会影响主从之间的延时:

repl-disable-tcp-nodelay:

设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟,造成master与slave数据不一致。

设置成no,则redis master会立即发送同步数据,几乎没有延迟。

Redis的主从同步无论那种场景可以抽象为以下七个步骤:

1.建立socket连接

从服务器根据设置的套接字创建连向主服务器的套接字连接,主服务器接收从服务器的套接字连接之后,为该套接字创建响应的客户端状态,并将此时的从服务器看做是主服务器的客户端,也就是该从服务器同时具备服务器与客户端两个身份。

2.发送PING命令

PING命令主要有两种作用:虽然建立了套接字连接,但是还未使用过,通过发送PING命令检查套接字的读写状态是否正常;通过发送PING命令检查主服务器能否正常处理命令请求,能处理主服务器回复PONG。

3.身份验证

从服务器接收到主服务器返回的“PONG”回复,接下来就需要考虑身份验证的事。如果从服务器设置了masterauth选项,那么进行身份验证,如果从服务器没有设置masterauth选项,那么不进行身份验证。

4.发送端口信息

在身份验证步骤之后,从服务器将执行命令REPLCONF listening-port <port>,向主服务器发送从服务器的监听端口号。

5.数据同步

从服务器向主服务器发送SYNC命令、PSYNC命令,执行同步操作。

6.命令传播

主从服务器就会进入命令传播阶段,主服务器只要将自己执行的写命令发送给从服务器,而从服务器只要一直执行并接收主服务器发来的写命令。

五、告一段落

本篇详细介绍了redis主从同步机制,不同场景下同步策略的选择,这也是redis高可用的基石。在此基础上,下一篇将对redis高可用的实现来进行分析讲解。


更多文章:


Redis(一):单线程为何还能这么快?

Redis(二):内存模型及回收算法

Redis(三):持久化

Elasticsearch(一):概述

Elasticsearch(二):核心

Elasticsearch(三):实战

RocketMQ—NameServer总结及核心源码剖析

RocketMQ—Producer(一)启动流程解密

关注IT巅峰技术,私信作者,获取以下2021全球架构师峰会PDF资料。



相关推荐

使用 Docker 部署 Java 项目(通俗易懂)

前言:搜索镜像的网站(推荐):DockerDocs1、下载与配置Docker1.1docker下载(这里使用的是Ubuntu,Centos命令可能有不同)以下命令,默认不是root用户操作,...

Spring Boot 3.3.5 + CRaC:从冷启动到秒级响应的架构实践与踩坑实录

去年,我们团队负责的电商订单系统因扩容需求需在10分钟内启动200个Pod实例。当运维组按下扩容按钮时,传统SpringBoot应用的冷启动耗时(平均8.7秒)直接导致流量洪峰期出现30%的请求超时...

《github精选系列》——SpringBoot 全家桶

1简单总结1SpringBoot全家桶简介2项目简介3子项目列表4环境5运行6后续计划7问题反馈gitee地址:https://gitee.com/yidao620/springbo...

Nacos简介—1.Nacos使用简介

大纲1.Nacos的在服务注册中心+配置中心中的应用2.Nacos2.x最新版本下载与目录结构3.Nacos2.x的数据库存储与日志存储4.Nacos2.x服务端的startup.sh启动脚...

spring-ai ollama小试牛刀

序本文主要展示下spring-aiollama的使用示例pom.xml<dependency><groupId>org.springframework.ai<...

SpringCloud系列——10Spring Cloud Gateway网关

学习目标Gateway是什么?它有什么作用?Gateway中的断言使用Gateway中的过滤器使用Gateway中的路由使用第1章网关1.1网关的概念简单来说,网关就是一个网络连接到另外一个网络的...

Spring Boot 自动装配原理剖析

前言在这瞬息万变的技术领域,比了解技术的使用方法更重要的是了解其原理及应用背景。以往我们使用SpringMVC来构建一个项目需要很多基础操作:添加很多jar,配置web.xml,配置Spr...

疯了!Spring 再官宣惊天大漏洞

Spring官宣高危漏洞大家好,我是栈长。前几天爆出来的Spring漏洞,刚修复完又来?今天愚人节来了,这是和大家开玩笑吗?不是的,我也是猝不及防!这个玩笑也开的太大了!!你之前看到的这个漏洞已...

「架构师必备」基于SpringCloud的SaaS型微服务脚手架

简介基于SpringCloud(Hoxton.SR1)+SpringBoot(2.2.4.RELEASE)的SaaS型微服务脚手架,具备用户管理、资源权限管理、网关统一鉴权、Xss防跨站攻击、...

SpringCloud分布式框架&amp;分布式事务&amp;分布式锁

总结本文承接上一篇SpringCloud分布式框架实践之后,进一步实践分布式事务与分布式锁,其中分布式事务主要是基于Seata的AT模式进行强一致性,基于RocketMQ事务消息进行最终一致性,分布式...

SpringBoot全家桶:23篇博客加23个可运行项目让你对它了如指掌

SpringBoot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通...

开发好物推荐12之分布式锁redisson-sb

前言springboot开发现在基本都是分布式环境,分布式环境下分布式锁的使用必不可少,主流分布式锁主要包括数据库锁,redis锁,还有zookepper实现的分布式锁,其中最实用的还是Redis分...

拥抱Kubernetes,再见了Spring Cloud

相信很多开发者在熟悉微服务工作后,才发现:以为用SpringCloud已经成功打造了微服务架构帝国,殊不知引入了k8s后,却和CloudNative的生态发展脱轨。从2013年的...

Zabbix/J监控框架和Spring框架的整合方法

Zabbix/J是一个Java版本的系统监控框架,它可以完美地兼容于Zabbix监控系统,使得开发、运维等技术人员能够对整个业务系统的基础设施、应用软件/中间件和业务逻辑进行全方位的分层监控。Spri...

SpringBoot+JWT+Shiro+Mybatis实现Restful快速开发后端脚手架

作者:lywJee来源:cnblogs.com/lywJ/p/11252064.html一、背景前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础。SpringBoot使编码配置...

取消回复欢迎 发表评论: