搞懂Redis复制原理
前言
与大多数db一样,Redis也提供了复制机制,以满足故障恢复和负载均衡等需求。复制也是Redis高可用的基础,哨兵和集群都是建立在复制基础上实现高可用的。复制不仅提高了整个系统的容错能力,还可以水平扩展,实现在一个重读取的应用中,通过增加多个Redis只读从实例来减轻主实例的压力。
本文主要介绍Redis复制机制

一.配置与实践
配置
Redis实例分为主节点(master)和从节点(slave),默认情况下都是主节点。每一个从节点只能有一个主节点,但是每一个主节点可以有多个从节点(注意数量,多个从节点会导致主节点写命令多次发送从而过度消耗网络带宽,可用树状结构降低主节点负载)。复制是单向的,只能从主节点复制到从节点。配置复制的方式由以下3种:
- 在redis-slave.conf配置文件中加入slaveof {masterHost} {masterPort}
- 在redis-server启动命令后加入 --slaveof {masterHost} {masterPort}
- 启动后直接使用命令slaveof {masterHost} {masterPort}
综上,Redis支持在启动之前配置,也支持运行中动态配置。
实践
我们用动态配置的方法来配置,先起一个端口为6379的Redis实例,作为主节点:
redis-server /usr/local/Cellar/redis/4.0./.bottle/etc/redis.conf
再起一个端口为6380的Redis实例,作为6379的从节点:
redis-server /usr/local/Cellar/redis/4.0./.bottle/etc/redis-slave.conf
用客户端连到从节点,使用slaveof命令,slaveof配置都是在从节点发起的。
127.0.0.1:> slaveof 127.0.0.1
OK
从节点日志:
:S May ::50.389 * Connecting to MASTER 127.0.0.1:
:S May ::50.389 * MASTER <-> SLAVE sync started
:S May ::50.390 * Non blocking connect for SYNC fired the event.
:S May ::50.390 * Master replied to PING, replication can continue...
:S May ::50.390 * Trying a partial resynchronization (request 47770067272eb8101489fe7c00c8e838125c3aa3:).
:S May ::50.392 * Full resync from master: e91e683b1e13332f97ecb9fa90ecdace460ab4ca:
:S May ::50.392 * Discarding previously cached master state.
:S May ::50.491 * MASTER <-> SLAVE sync: receiving bytes from master
:S May ::50.492 * MASTER <-> SLAVE sync: Flushing old data
:S May ::50.492 * MASTER <-> SLAVE sync: Loading DB in memory
:S May ::50.492 * MASTER <-> SLAVE sync: Finished with success
主节点日志:
:M May ::50.391 * Slave 127.0.0.1: asks for synchronization
:M May ::50.391 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '47770067272eb8101489fe7c00c8e838125c3aa3', my replication IDs are '160af1c75f86edc50186e3e4a4dc6ecb5e3fa586' and '')
:M May ::50.391 * Starting BGSAVE for SYNC with target: disk
:M May ::50.391 * Background saving started by pid
:C May ::50.395 * DB saved on disk
:M May ::50.490 * Background saving terminated with success
:M May ::50.491 * Synchronization with slave 127.0.0.1: succeeded
可以看到,第一次建立复制关系的时候,主节点和从节点进行了一次全量复制,见图:

当完成复制的建立之后,接下来主节点会持续的把写命令发送给从节点,保证主从数据一致。
在主实例上添加新的key:
127.0.0.1:> set Lin
OK
在从实例查看刚刚添加的key:
127.0.0.1:> get Lin
""
只读
由于复制只能从主节点到从节点,对于从节点的数据修改主节点无法感知,为了避免主从实例之间的数据不一致。从节点默认配置为只读模式:
slave-read-only yes
二.工作原理
我们先讲3个比较关键的参数:master_replid、master_repl_offset和slave_repl_offset。我们分别在master6379和slave6380上执行info replication
127.0.0.1:> info replication
# Replication
role:master
connected_slaves:
slave0:ip=127.0.0.1,port=,state=online,offset=,lag=
master_replid:e91e683b1e13332f97ecb9fa90ecdace460ab4ca
master_replid2:
master_repl_offset:1093
second_repl_offset:-
repl_backlog_active:
repl_backlog_size:
repl_backlog_first_byte_offset:
repl_backlog_histlen: 127.0.0.1:> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:
master_link_status:up
master_last_io_seconds_ago:
master_sync_in_progress:
slave_repl_offset:1107
slave_priority:
slave_read_only:
connected_slaves:
master_replid:e91e683b1e13332f97ecb9fa90ecdace460ab4ca
master_replid2:
master_repl_offset:1107
second_repl_offset:-
repl_backlog_active:
repl_backlog_size:
repl_backlog_first_byte_offset:
repl_backlog_histlen:
- master_replid是master启动时生成的随机字符串,用来标识主实例
- master_repl_offset是复制流中的一个偏移量,master处理完写入命令后,会把命令的字节长度做累加记录,统计在该字段。该字段也是实现部分复制的关键字段。
- slave_repl_offset同样也是一个偏移量,从节点收到主节点发送的命令后,累加自身的偏移量,通过比较主从节点的复制偏移量可以判断主从节点数据是否一致。
当从实例连接到主实例时,从实例会发送master_replid和master_repl_offset(标识与主实例同步的最后一个快照)请求部分复制。如果主实例接收部分复制的话则从最后一个偏移量开始增量进行部分复制,否则将进行全量复制。如图:

三.数据同步
Redis在2.8之前使用sync命令完成主从数据同步,Redis在2.8及以上使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制
全量复制
全量复制是Redis最早支持的复制方式,也是主从第一次建立复制的时候必须经历的。它会把主节点全部数据一次性发送给从节点,当数据量较大的时候,会对主从节点和网络造成很大开销。主节点执行bgsave保存RDB文件,然后将这个文件发送给从节点,从节点收到RDB文件后,会先将内存中的所有数据清除,然后再将RDB文件中的数据导入。
主实例在复制过程中是完全异步的,因此不会阻塞主节点的请求。在这一期间内主节点的所有写入命令数据都保存在从客户端缓冲区(slave client buffer)内,在从节点加载完RDB文件后,主节点会将这个缓冲区的内容发送给从节点。
从客户端缓冲区默认大小限制为:
client-output-buffer-limit slave 256mb 64mb
意思是如果60秒内缓冲区消耗持续大于64MB或者直接超过256MB时,主节点将直接关闭复制客户端连接,造成全量同步失败。
部分复制
在高版本的Redis实现中,master_replid和offset存储在RDB文件中。当从实例在复制过程中,因网络闪断等原因造成的数据丢失场景,Redis能够从rdb文件中重新加载master_replid和offset,从而使部分重新同步成为可能。因为补发的数据远小于全量数据,所以可以有效的避免全量复制带来的负载和消耗。
之前说过,从节点连接主节点之后,会使用master_replid和master_repl_offset请求主节点,首先判断master_replid是否和自己的master_replid一致,然后检查请求中的master_repl_offset是否能从缓冲区(replication backlog)中获取,如果偏移量在backlog范围内,那么可以进行部分复制。如果在断开连接期间主节点收到的写入命令的数量超过了backlog缓冲区的容量,那么会进行全量复制。默认情况下backlog为1MB。
参考
基本和redis篇第一个帖子一样:
https://www.cnblogs.com/GrimMjx/p/10662254.html
搞懂Redis复制原理的更多相关文章
- 彻底搞懂Redis主从复制原理及实战
欢迎关注公众号:「码农富哥」,致力于分享后端技术 (高并发架构,分布式集群系统,消息队列中间件,网络,微服务,Linux, TCP/IP, HTTP, MySQL, Redis), Python 等 ...
- 深入理解redis复制原理
原文:深入理解redis复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof ...
- Redis 复制原理及特性
摘要 早期的RDBMS被设计为运行在单个CPU之上,读写操作都由经单个数据库实例完成,复制技术使得数据库的读写操作可以分散在运行于不同CPU之上的独立服务器上,Redis作为一个开源的.优秀的key- ...
- 一文搞懂vim复制粘贴
转载自本人独立博客https://liushiming.cn/2020/01/18/copy-and-paste-in-vim/ 概述 复制粘贴是文本编辑最常用的功能,但是在vim中复制粘贴还是有点麻 ...
- Redis从出门到高可用--Redis复制原理与优化
Redis从出门到高可用–Redis复制原理与优化 单机有什么问题? 1.单机故障; 2.单机容量有瓶颈 3.单机有QPS瓶颈 主从复制:主机数据更新后根据配置和策略,自动同步到备机的master/s ...
- redis复制原理和应用
1.前言 说到分布式高可用,必然少不了复制,一来是为了做个冗余备份防止数据丢失,二来还可以达到分流来提高性能的目的.基本架构: 下面用M表示Master(主服务器),S表示Slave(从服务器),话不 ...
- 一文搞定 Redis 复制(全会的举个手看看)
阅读本文大概需要 5 分钟. 本文大纲 复制过程 数据间的同步 全量复制 部分复制 心跳 异步复制 总结 一.复制过程 Step 1:从节点执行 slaveof 命令. Step 2:从节点只是保存了 ...
- 一篇文章彻底搞懂base64编码原理
开始 在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇文章带领大家了解一下Base64的底层实现. base64是什么东东呢? Base64 ...
- 搞懂MySQL GTID原理
从MySQL 5.6.5 开始新增了一种基于 GTID 的复制方式.通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID.这种方式强化了数据库的主备一致性,故障恢复以及容错能力. GT ...
随机推荐
- JavaWeb_(SSH论坛)_一、项目入门
基于SSH框架的小型论坛项目 一.项目入门 传送门 二.框架整合 传送门 三.用户模块 传送门 四.页面显示 传送门 五.帖子模块 传送门 六.点赞模块 传送门 七.辅助模块 传送门 项目已上传至gi ...
- 在CentOS 7上搭建WordPress
环境(ECS阿里云服务器) 服务器操作系统:CentOS 7.3 : 博客部署服务器:Apache HTTP: 数据库:MySql: 框架:WordPress: 步骤 一.安装 Apache HTTP ...
- 修复Long类型太长转为JSON格式的时候出错的问题
这边项目要求ID是自动生成的20位Long型数字 但是实际中应用的时候回发生一种问题就是,查询的时候debug的时候数据都正常,但是返回前端的时候就会发现,数据错误了. 大体就是类似于下面的这种情况. ...
- 【面试】SSH 框架原理
SSH 框架原理: 1.通过 Configuration().configure();读取并解析 hibernate.cfg.xml 配置文件2.由 hibernate.cfg.xml中的<ma ...
- 一、基础篇--1.2Java集合-HashMap和HashSet的区别
HashMap和HashSet的区别 1.HashMap实现的是Map接口,HashSet实现的是Set接口 2.结构不一样,一个存储的是键值对,一个存储的是对象 3.HashMap存储的值可能相同 ...
- Note 1 for <Pratical Programming : An Introduction to Computer Science Using Python 3>
Book Imformation : <Pratical Programming : An Introduction to Computer Science Using Python 3> ...
- leetcode-hard-array-128. Longest Consecutive Sequence
mycode 92.62% class Solution(object): def longestConsecutive(self, nums): """ :type ...
- AutoItLibrary测试Windows GUI
AutoItLibrary库关键字 AutoItLibrary 的对象操作大体上有几大主要部分,Window 操作.Control 操作.Mouse 操作.Process操作.Run 操作.Reg 操 ...
- RESTful 介绍
什么是RESTful?一种软件架构风格.设计风格,而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务端交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. ...
- LCTF (easyeasy-200)
首先安装,看看app是什么样的. 有点奇怪,没有点击确定的按钮.然后拖到JEB反编译. 要求输入的字符串的长度要在35-39之间(包括边界值),然后会调用Format().form函数.如下图. 可以 ...