redis的主从复制原理
1. 前言
和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis主从复制可以根据是否是全量分为全量同步和增量同步。
2. 旧版复制功能实现
redis复制功能分为同步和命令传播两种操作:
(1)同步操作负责将从数据库的状态更新为和主数据库状态一致
(2)命令传播操作则用于当主服务器状态修改时,让从服务器状态重新回到一致
2.1 同步
同步操作由sync操作完成:
(1)从服务器向主服务器发送sync命令
(2)收到sync命令的主服务器执行BGSAVE命令,生成RDB文件,并使用一个缓冲区缓存生成RDB期间所有的写命令
(3)RDB生成完成时,发送RDB给从服务器,从服务器载入RDB,状态和主服务器一致
(4)然后主服务器将缓冲区中的写命令全部传给从服务器,状态一致
2.2 命令传播
同步操作完成后,主从状态一致,但是每当客户端向主服务器执行写命令时,主服务器会修改,和从服务器状态不一致,为了让主从状态重新回到一致,主服务器会发送写命令给从服务器,让从服务器回到和主服务器一致的状态。
2.3 旧版复制功能的不足之处
在redis2.8之前,主从服务器的复制会分为两种:
(1)初次复制:从服务器以前从没复制过其他主服务器,或者从服务器的主服务器换了
(2)断线后复制:处于命令传播阶段的主从服务器,发生了断线,重新连上后,从服务器继续复制主服务器
为什么说效率低呢?因为在旧版复制中,断线重新连接后进行的复制,是通过sync命令实现的,而之前说了sync命令实现是主服务器重新生成RDB文件,发送给从服务器,重新生成RDB是很低效的,而且主服务器生成RDB时是阻塞状态的,所以旧版复制是低效率的。
3. 新版复制功能实现
为了解决旧版复制低效问题,新版复制采用了psync命令来代替sync命令,psync命令具有完全重同步和部分重同步:
(1)完全重同步:和上面的sync一样
(2)部分重同步:专门用于负责处理断线后重连,通过重连后只执行断线期间的写命令而不是全同步来达到高效
3.1 部分重同步实现
部分重同步实现由以下三部分构成:
(1)主服务器的复制偏移量和从服务器的复制偏移量
(2)主服务器的复制积压缓冲区
(3)服务器运行ID
3.1.1 复制偏移量
主从服务器都会维持一个复制偏移量:
- 主服务器每次向从服务器发送n个字节的命令,就在自己复制偏移量加n
- 从服务器每次接收到n个字节数据,就在自己复制偏移量加n
例如,主从服务器当前偏移是100,主向从服务器发送33个字节命令,那么主从此时的复制偏移量都是133,所以判断主从当前状态是否一致,可以通过复制偏移量来判断:复制偏移量如果一样,就代表状态一致,否则不一致。如果断线时,从服务器因为收不到命令,而主服务器一直发送命令,这时的偏移量肯定不一样,所以状态不一致,那么如果让中间漏掉的命令重新传给从服务器呢,这和积压缓冲区有关。
3.1.2 复制积压缓冲区
复制积压缓冲区是一个主服务器维护的固定长度的先进先出队列。每当主服务器进行命令传播时,它不仅将命令传给从服务器,还会将命令写入到缓冲区:

如上图所示,就是一个积压缓冲区的现状,当从服务器重连后,向主服务器发送一个psycn命令,同时会将从服务器当前的复制偏移量(offset)带过去,主服务器会根据从服务器的offset,来决定是全同步还是部分同步:
(1)如果从服务器的offset是10086,那么此时要复制的偏移量应该是从10087开始,在缓冲区存在,将从10087开始往后所有数据都发送给从服务器,所以执行的是部分重同步
(2)相反的,如果不存在,就需要进行全同步了!
如下图:如果进行部分重同步,就向从服务器发送一个CONTINUE回复。

3.1.3 服务器运行ID
除了复制偏移量和复制积压缓冲区之外,实现部分重同步还需要用到服务器运行ID(run ID):
- 每个Redis服务器,不论主服务器还是从服务,都会有自己的运行ID;
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,而从服务器则会将这个运行ID保存起来(注意哦,是从服务器保存了主服务器的ID)。
当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:
- 如果从服务器保存的运行ID和当前连接的主服务器的运行ID相同,那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部分重同步操作;
- 相反地,如果从服务器保存的运行ID和当前连接的主服务器的运行ID并不相同,那么说明从服务器断线之前复制的主服务器并不是当前连接的这个主服务器,主服务器将对从服务器执行完整重同步操作。
4. 心跳机制
在命令传播阶段时,从服务器每隔一秒都会向主服务器发送命令:REPLCONF ACK <replication_offset>,每发送一次这个命令从服务器都会向主服务器报告一次自己的复制偏移量,如果超过一秒,就代表主从连接出了问题。那此时尽管主服务器发送给从服务器的SET key value丢失了。也无所谓,主服务器马上就知道了,但是要注意,这时的偏移量不一致,并不是断线导致的,而是以为主服务器传给从服务器的命令丢失了,连接情况还是正常的,这种称之为命令丢失。
redis的主从复制原理的更多相关文章
- 5.如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?
作者:中华石杉 面试题 如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么? 面试官心理分析 其实问这个问题,主要是考考你,redis ...
- Redis 主从复制原理及雪崩 穿透问题
定义: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMw ...
- Redis主从复制原理总结
和Mysql主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况.为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redi ...
- 【*】深入理解redis主从复制原理
1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制. 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 ...
- 深入Redis 主从复制原理
原文:深入Redis 主从复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveo ...
- redis之(十四)redis的主从复制的原理
一:redis主从复制的原理,步骤. 第一步:复制初始化 --->从redis启动后,会根据配置,向主redis发送SYNC命令.2.8版本以后,发送PSYNC命令. --->主red ...
- Redis面试篇 -- Redis主从复制原理
Redis一般是用来支撑读高并发的,为了分担读压力,Redis支持主从复制.架构是主从架构,一主多从, 主负责写,并且将数据复制到其它的 slave 节点,从节点负责读. 所有的读请求全部走从 ...
- Redis主从复制以及主从复制原理
Redis 是一个开源的使用 ANSI C 语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库,并提供多种语言的 API.从 2010年 3 月 15 日起,Redis 的开 ...
- 彻底搞懂Redis主从复制原理及实战
欢迎关注公众号:「码农富哥」,致力于分享后端技术 (高并发架构,分布式集群系统,消息队列中间件,网络,微服务,Linux, TCP/IP, HTTP, MySQL, Redis), Python 等 ...
随机推荐
- css文本超出隐藏 显示三个点
文本超出显示三个点一般分两种情况 一,单行文本超出隐藏 overflow:hidden; text-overflow:ellipsis; white-space:nowrap; 二,多行文本超出隐藏 ...
- 关于一些JS的运算符
首先呢,什么是JavaScript:JavaScript是一种脚本语言,也是一种解释型语言,更是一种由数据值决定变量类型的弱类型语言 JavaScript主要由三部分组成 ECMAScript 这个 ...
- 7.JSP技术
JSP和Servlet一样,都是用于开发动态web资源的技术 JSP的两个特性:1.写JSP代码就像是在写HTML代码,但JSP技术允许在页面中编写java代码(理解为一种特殊的HTML) 2.JSP ...
- JPA的入门案例
1.1 需求介绍 本章节我们是实现的功能是保存一个客户到数据库的客户表中. 1.2 开发包介绍 由于JPA是sun公司制定的API规范,所以我们不需要导入额外的JPA相关的jar包,只需要 ...
- linux——目录说明
1) bin -> usr/bin : 这个目录存放最经常使用的命令 2) boot : 这个目录存放启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件 3) dev: de ...
- List去重比较
import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; import java.ut ...
- RxJava事件流变换者--操作符
对于Rxjava来说,操作符是它的一个非常重要的概念,如官网: 而上节上也贴了一下都有哪些操作符,其实还不少,所以有必要仔细学习一下关于操作符这块的东东,那操作符在Rxjava中扮演着什么样的角色呢, ...
- 少有人知的 GitHub 使用技巧
GitHub 大家常上吧?可是使用 GitHub 的各种小窍门你就不一定知道了.本文将各种使用 GitHub 的小窍门分享给大家. diff时忽略空格 有些修改只是增减了空格,在URL中添加?w=1就 ...
- MyBatis-13-缓存
13.缓存(了解) 13.1.简介 查询 : 连接数据库,耗资源! 一次查询的结果,给他暂存在一个可以直接取到的地方!--->内存 : 缓存 我们再次查询相同数据的时候,直接走缓存,就不用走数据 ...
- 正整数n拆分成几个不同的平方数——DFS&&打表
考虑将正整数n拆分成几个不同的平方数之和,比如30=1^2 + 2^2 + 5^2=1^2 + 2^2 + 3^2 + 4^2,而8不存在这样的拆分. #include<bits/stdc++. ...