搞懂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 ...
随机推荐
- SRS之SrsServer::cycle()
1. SrsServer 相关类定义 1.1 SrsServer 类定义 /** * SRS RTMP server, initialize and listen, * start connectio ...
- FastAdmin 在 CRUD 时出现 exec() has been disabled for security reasons 处理方法
然后在看看 禁用函数列表(php.ini)disable_functions = proc_open, popen, exec, system, shell_exec, passthru 这里要把 e ...
- 石川es6课程---11、json
石川es6课程---11.json 一.总结 一句话总结: ` 感觉更方便了一点,增加了一些简写 ` key-value 一样时可以简写:console.log({ a,b}}) ` 里面函数可以简写 ...
- AndroidManifest.xml中的<uses-feature>以及和<uses-permission>之间的联系
概述:<uses-feature>用来声明应用中需要用的硬件和软件的功能. 硬件特性:表明您的应用需要用的硬件功能. 功能类型 特征描述 描述 音频 android.hardware.au ...
- Flask中session实现原理
前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活 ...
- AIxoder插件安装及使用
参考:https://www.aixcoder.com/#/Download 右边有快捷导航,查看对应需要的问题 1.下载AIxcoder 2.安装并注册打开 3.给IDE安装 4.验证是否安装成 ...
- for循环使用
cat > a.sh <<EOF #!/bin/bash export NODE_NAMES=(kube-test1 kube-test2 kube-test3 kube-test4 ...
- python配置主机名
.准备hosts模板 mkdir -p /k8s/profile cat >/k8s/profile/hosts<<EOF 192.168.0.91 test1 192.168.0. ...
- Ubuntu 16.04 安装 google 输入法
Ubuntu 16.04 安装 google 输入法 在命令行中运行:’sudo apt install fcitx-googlepinyin’ 在 system setting > Langu ...
- XCTF (app2)
打开app,有两个输入框和一个按钮.点击按钮会跳转到新的页面显示Waiting for you. 打开JEB反编译. 如果两个输入框的长度都不为0,那么获取这两个值到v0和v1中,Log记录日志. 创 ...