详解Redis复制原理


Posted in Redis onJune 04, 2021

前言

本文主要介绍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.9/.bottle/etc/redis.conf

再起一个端口为6380的Redis实例,作为6379的从节点:

redis-server /usr/local/Cellar/redis/4.0.9/.bottle/etc/redis-slave.conf

用客户端连到从节点,使用slaveof命令,slaveof配置都是在从节点发起的。

127.0.0.1:6380> slaveof 127.0.0.1 6379

OK

从节点日志:

75585:S 06 May 16:27:50.389 * Connecting to MASTER 127.0.0.1:6379

75585:S 06 May 16:27:50.389 * MASTER <-> SLAVE sync started

75585:S 06 May 16:27:50.390 * Non blocking connect for SYNC fired the event.

75585:S 06 May 16:27:50.390 * Master replied to PING, replication can continue...

75585:S 06 May 16:27:50.390 * Trying a partial resynchronization (request 47770067272eb8101489fe7c00c8e838125c3aa3:1).

75585:S 06 May 16:27:50.392 * Full resync from master: e91e683b1e13332f97ecb9fa90ecdace460ab4ca:0

75585:S 06 May 16:27:50.392 * Discarding previously cached master state.

75585:S 06 May 16:27:50.491 * MASTER <-> SLAVE sync: receiving 215 bytes from master

75585:S 06 May 16:27:50.492 * MASTER <-> SLAVE sync: Flushing old data

75585:S 06 May 16:27:50.492 * MASTER <-> SLAVE sync: Loading DB in memory

75585:S 06 May 16:27:50.492 * MASTER <-> SLAVE sync: Finished with success

主节点日志:

75553:M 06 May 16:27:50.391 * Slave 127.0.0.1:6380 asks for synchronization

75553:M 06 May 16:27:50.391 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '47770067272eb8101489fe7c00c8e838125c3aa3', my replication IDs are '160af1c75f86edc50186e3e4a4dc6ecb5e3fa586' and '0000000000000000000000000000000000000000')

75553:M 06 May 16:27:50.391 * Starting BGSAVE for SYNC with target: disk

75553:M 06 May 16:27:50.391 * Background saving started by pid 75675

75675:C 06 May 16:27:50.395 * DB saved on disk

75553:M 06 May 16:27:50.490 * Background saving terminated with success

75553:M 06 May 16:27:50.491 * Synchronization with slave 127.0.0.1:6380 succeeded

可以看到,第一次建立复制关系的时候,主节点和从节点进行了一次全量复制,见图:

详解Redis复制原理

当完成复制的建立之后,接下来主节点会持续的把写命令发送给从节点,保证主从数据一致。

在主实例上添加新的key:

127.0.0.1:6379> set Lin 112131

OK

在从实例查看刚刚添加的key:

127.0.0.1:6380> get Lin

"112131"

只读

由于复制只能从主节点到从节点,对于从节点的数据修改主节点无法感知,为了避免主从实例之间的数据不一致。从节点默认配置为只读模式:

slave-read-only yes

二.工作原理

我们先讲3个比较关键的参数:master_replid、master_repl_offset和slave_repl_offset。我们分别在master6379和slave6380上执行info replication

127.0.0.1:6379> info replication

# Replication

role:master

connected_slaves:1

slave0:ip=127.0.0.1,port=6380,state=online,offset=1093,lag=1

master_replid:e91e683b1e13332f97ecb9fa90ecdace460ab4ca

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:1093

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:1093

 

 

127.0.0.1:6380> info replication

# Replication

role:slave

master_host:127.0.0.1

master_port:6379

master_link_status:up

master_last_io_seconds_ago:9

master_sync_in_progress:0

slave_repl_offset:1107

slave_priority:100

slave_read_only:1

connected_slaves:0

master_replid:e91e683b1e13332f97ecb9fa90ecdace460ab4ca

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:1107

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:1107

master_replid是master启动时生成的随机字符串,用来标识主实例

master_repl_offset是复制流中的一个偏移量,master处理完写入命令后,会把命令的字节长度做累加记录,统计在该字段。该字段也是实现部分复制的关键字段。

slave_repl_offset同样也是一个偏移量,从节点收到主节点发送的命令后,累加自身的偏移量,通过比较主从节点的复制偏移量可以判断主从节点数据是否一致。

当从实例连接到主实例时,从实例会发送master_replid和master_repl_offset(标识与主实例同步的最后一个快照)请求部分复制。如果主实例接收部分复制的话则从最后一个偏移量开始增量进行部分复制,否则将进行全量复制。如图:

详解Redis复制原理

三.数据同步

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

意思是如果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复制原理的详细内容,更多关于Redis复制原理的资料请关注三水点靠木其它相关文章!

Redis 相关文章推荐
详解Redis实现限流的三种方式
Apr 27 Redis
redis 查看所有的key方式
May 07 Redis
redis通过6379端口无法连接服务器(redis-server.exe闪退)
May 08 Redis
Redis延迟队列和分布式延迟队列的简答实现
May 13 Redis
浅谈Redis主从复制以及主从复制原理
May 29 Redis
详解Redis基本命令与使用场景
Jun 01 Redis
解析redis hash应用场景和常用命令
Aug 04 Redis
redis中lua脚本使用教程
Nov 01 Redis
关于使用Redisson订阅数问题
Jan 18 Redis
redis复制有可能碰到的问题汇总
Apr 03 Redis
浅谈Redis缓冲区机制
Jun 05 Redis
Redis实战之Lettuce的使用技巧详解
Dec 24 Redis
Windows下redis下载、redis安装及使用教程
深入理解redis中multi与pipeline
Jun 02 #Redis
SpringBoot 集成Redis 过程
Jun 02 #Redis
详解Redis基本命令与使用场景
Django使用redis配置缓存的方法
Jun 01 #Redis
详解Redis集群搭建的三种方式
May 31 #Redis
浅谈Redis主从复制以及主从复制原理
You might like
基于PHP输出缓存(output_buffering)的深入理解
2013/06/13 PHP
关于PHP通用返回值设置方法
2017/03/31 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
PHP实现微信提现功能(微信商城)
2019/11/21 PHP
TP5框架实现的数据库备份功能示例
2020/04/05 PHP
破解Session cookie的方法
2006/07/28 Javascript
JS实现根据当前文字选择返回被选中的文字
2014/05/21 Javascript
Jquery解析Json格式数据过程代码
2014/10/17 Javascript
javascript实现PC网页里的拖拽效果
2016/03/14 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
jQuery简单获取DIV和A标签元素位置的方法
2017/02/07 Javascript
[js高手之路]单例模式实现模态框的示例
2017/09/01 Javascript
vue2.0之多页面的开发的示例
2018/01/30 Javascript
vue实现百度下拉列表交互操作示例
2019/03/12 Javascript
node.js文件操作系统实例详解
2019/11/05 Javascript
es6函数中的作用域实例分析
2020/04/18 Javascript
[02:56]DOTA2上海特锦赛小组赛解说FreeAgain采访花絮
2016/02/27 DOTA
python开发之for循环操作实例详解
2015/11/12 Python
CentOS中升级Python版本的方法详解
2017/07/10 Python
说说如何遍历Python列表的方法示例
2019/02/11 Python
Python使用PyQt5/PySide2编写一个极简的音乐播放器功能
2020/02/07 Python
Python 创建TCP服务器的方法
2020/07/28 Python
python爬虫工具例举说明
2020/11/30 Python
Coach澳大利亚官方网站:美国著名时尚奢侈品牌
2017/05/24 全球购物
法国一家芭蕾舞鞋公司:Repetto
2018/11/12 全球购物
加拿大时装零售商:Influence U
2018/12/22 全球购物
材料物理专业个人求职信
2013/12/15 职场文书
留学推荐信写作指南
2014/01/25 职场文书
《只有一个地球》教学反思
2014/02/14 职场文书
员工自我评价范文
2015/03/11 职场文书
2015年学校教务处工作总结
2015/05/11 职场文书
小学英语教学随笔
2015/08/14 职场文书
2016年党支部公开承诺书
2016/03/25 职场文书
有关保护环境的宣传标语100条
2019/08/07 职场文书
使用 MybatisPlus 连接 SqlServer 数据库解决 OFFSET 分页问题
2022/04/22 SQL Server
HTML5页面打开微信小程序功能实现
2022/09/23 HTML / CSS