目录

旧版复制功能的实现

同步

命令传播

缺陷

新版复制功能

部分重同步的实现

复制偏移量

复制积压缓冲区

服务器运行ID

PSYNC命令

复制的实现

心跳检测

检测主从服务器网络连接状态

辅助实现min-slaves选项

检测命令丢失


在Redis中,用户可以通过执行SLAVEOF 命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,被复制的服务器为主服务器(master),进行复制的服务器为从服务器(slave)。

SlaveOf 127.0.0.1 6379

旧版复制功能的实现

Redis 的复制功能分为同步(sync)和命令传播(command propagate)两个操作:

  • 其中, 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。--即初始化从服务器
  • 而命令传播操作则用于在主服务器的数据库状态被修改, 导致主从服务器的数据库状态出现不一致时, 让主从服务器的数据库重新回到一致状态。--即同步变更

同步

当客户端向从服务器发送 SLAVEOF 命令, 要求从服务器复制主服务器时, 从服务器首先需要执行同步操作, 也即是, 将从服务器的数据库状态更新至主服务器当前所处的数据库状态。

从服务器对主服务器的同步操作需要通过向主服务器发送 SYNC 命令来完成, 以下是 SYNC 命令的执行步骤:

  1. 从服务器向主服务器发送 SYNC 命令。
  2. 收到 SYNC 命令的主服务器执行 BGSAVE 命令, 在后台生成一个 RDB 文件, 并使用一个缓冲区记录(记录变更增量)从现在开始执行的所有写命令。
  3. 当主服务器的 BGSAVE 命令执行完毕时, 主服务器会将 BGSAVE 命令生成的 RDB 文件发送给从服务器, 从服务器接收并载入这个 RDB 文件, 将自己的数据库状态更新至主服务器执行 BGSAVE 命令时的数据库状态。
  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器, 从服务器执行这些写命令, 将自己的数据库状态更新至主服务器数据库当前所处的状态。

注意

1、从服务器在同步时,会清空所有数据,服务器在与主服务器进行初连接时,数据库中的所有数据都将丢失,替换成主服务器发送的数据。

2、Redis不支持主主复制

3、主从复制不会阻塞master(不会阻塞master处理客户端请求),相反slave在初次同步数据时会阻塞不能处理客户端请求。

4、当多个从服务器尝试连接同一个主服务器的时候,就会出现以下两种情况:

  • 一是:步骤3还未执行,所有从服务器都会接收到相同的快照文件和相同缓冲区写命令。
  • 二是:步骤3正在执行或者已经执行完毕,当主服务器与较早的从服务器完成以上全部步骤之后,主服务器会新连接的从服务器重新依次执行1-5步骤。

5、在大部分情况下,Redis会尽可能去减少复制所需要的工作,但是从服务器连接的时机不凑巧的话,只好多做一些外额外工作。
多个从服务器连接主服务器时候,同步数据可能会占用很大一部分的带宽,可能会导致其他请求难以到达主服务器。

命令传播

在同步操作执行完毕之后, 主从服务器两者的数据库将达到一致状态, 但这种一致并不是一成不变的 —— 每当主服务器执行客户端发送的写命令时, 主服务器的数据库就有可能会被修改, 并导致主从服务器状态不再一致。

为了让从服务器再次回到一致状态, 主服务器需要对从服务器执行命令传播操作: 主服务器会将自己执行的写命令 —— 也即是造成主从服务器不一致的那条写命令 —— 发送给从服务器执行, 当从服务器执行了相同的写命令之后, 主从服务器将再次回到一致状态。

缺陷

主要是主从服务器断线后重复制,即处于命令传播阶段的主从服务器由于网络断开,从服务器一直尝试连接主服务器连接成功后,继续复制主服务器。

从服务器连接后发送SYNC命令,重新进行了“全量”复制过程,RDB文件中包含全部的键。此操作效率特别低。

SYNC命令非常消耗资源,原因有三点:

  1. 主服务器执行BGSAVE命令生成RDB文件,这个生成过程会大量消耗主服务器资源(CPU、内存和磁盘I/O资源)
  2. 主服务器需要将自己生成的RBD文件发送给从从服务器,这个发送操作会消耗主从服务器大量的网络资源(带宽与流量)
  3. 接收到RDB文件你的从服务器需要载入RDB文件,载入期间从服务器会因为阻塞而导致没办法处理命令请求。

新版复制功能

为了解决旧版本中断线情况下SYNC低效问题,在Redis 2.8之后使用PSYNC命令代替SYNC命令执行复制同步操作,自然PSYNC具备完整重同步(full resynchronization)和部分重同步模式(partial resynchronization)

  • 完整重同步:跟旧版复制基本是一致的,可以理解为“全量”复制。
  • 部分重同步:在命令传播阶段,断线重复制只需要发送主服务器在断开期间执行的写命令给从服务器即可,可以理解为“增量”复制

部分重同步的实现

部分重同步功能由以下3个部分组成:

  • 主服务的复制偏移量(replication offset) 和 从服务器的复制偏移量
  • 主服务器的复制积压缓冲区(replication backlog)
  • 服务器的运行ID

复制偏移量

执行复制的主服务器、从服务器会分别维护一个复制偏移量:

  • 这个偏移量记录了执行命令的字节数。主服务器每次向从服务器传播N个字节时就会将自己的复制偏移量+N
  • 从服务在接收到主服务器传送来的N个字节的命令时,就将自己的复制偏移量+N。

通过对比复制偏移量,可以知道主从服务器是否一致:

  • 2者相同,主从一致。
  • 不相同,主从不一致。

复制积压缓冲区

复制积压缓冲区是一个由主服务器维护的固定长度的先进先出队列,默认大小为1M,可调整(repl-backlog-size)。

当从服务器重新连上主服务器时,通过PSYNC发送复制偏移量(offset),主服务器根据其值决定如果操作:

  • offset之后的数据仍在复制积压缓冲区,则主服务器对从服务器执行部分重同步操作。
  • 不在,执行完整重同步。

Redis复制积压缓冲区的大小可以设置,一般将其设置为 second * write_size_per_second * 2的大小

服务器运行ID

每个Redis 服务器无论主服务器还是从服务器都有自己的运行ID

运行ID在服务器启动时生成,由40个随机的十六进制字符组成

当从服务器对主服务器进行初次复制时,主服务器会将自身的运行ID回传给从服务器,从服务器会将这个运行ID保存下来。

当从服务器断线重连主服务器时,会将这个运行ID发送个主服务器,主服务器会检查这个运行ID是否为自己的运行ID,如果不是则会直接执行完整重同步,如果是自己的运行ID,则根据具体情况来决定是采用部分重同步还是完整重同步。

PSYNC命令

PSYNC命令调用方法有2种:

  • 请求完整重同步: PSYNC ? -1
  • 请求重连接同步:PSYNC <master runid> <offset>

主服务器返回结果:

  • 执行完整重同步:+FULLRESYNC <master runid> <offset>
  • 部分从同步:+CONTINUE
  • 不识别命令:-ERR

复制的实现

1.设置主服务器的地址和端口

SLAVEOF 127.0.0.7 6379

2.建立套接字连接
3.发送PING命令,检查是否可以连通主服务器。(返回PONG表示连通)

4.身份验证
从服务器向主服务器发送一条AUTH命令,将密码带给主服务器。

masterauth   用于设置从服务器是否进行身份验证,AUTH命令的参数为此值。

requirepass 用于设置主服务器是否需要密码验证。

结果:

  • 主服务没有requirepass,从服务器没有masterauth。复制继续进行。
  • requirepass与masterauth相同。复制继续进行。不同返回:invalid password。
  • 主有requirepass,从没有masterauth。返回:NOAUTH
  • 主没有requirepass,从有masterauth。返回:no password is set

5.发送端口信息
执行命令

REPLCONF listening-port <port-number>

向主服务器发送从服务器监听端口
6.同步
7.命令传播

心跳检测

在命令传播阶段,从服务器默认会以每秒一次的频率发送命令:

REPLCONF ACK <replication_offset>

其中replication_offset是从服务器当前的偏移量
这个命令主要有三个作用:

  • 检测主从服务器的连接状态
  • 辅助实现min-slaves选项
  • 检测命令丢失

检测主从服务器网络连接状态

执行如下命令:

127.0.0.1:9001> INFO replication
# Replication
role:master
connected_slaves:1
# lag值表示1s前发送过REPLCONF ACK
slave0:ip=127.0.0.1,port=9004,state=online,offset=293566,lag=1
master_replid:1bb39e63541f367d670879f7be07f49855d96aad
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:293580
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:293580

一般情况下lag值应该在0秒或1秒之间跳动,如果超过了1秒那么说明主从服务器之间连接出了问题

辅助实现min-slaves选项

Redis的min-slaves-to-writemin-slaves-max-lag 这两个选项可以防止主服务器在不安全的情况下执行写命令。
例如我们进行如下配置:

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

那么在从服务器数量少于3个

或者三个从服务器的延迟(lag)值都大于或等于10时,主服务器将拒绝执行写命令。

检测命令丢失

如果因为网络故障,主服务器传播给从服务器的写命令丢失,那么当从服务器向
主服务器发送REPLCONF ACK <replication_offset>命令时,主服务器会发现从服务器当前的复制偏移量少于自己的复制偏移量,然后主服务就会根据从服务器提交的复制偏移量在复制积压缓冲区中找到从服务器中缺少的数据,并将这些数据重新发送给从服务器。

redis(15)--复制相关推荐

  1. Redis:复制,第2部分——主从复制和Redis哨兵

    目录 介绍 基本主从复制 Redis主机配置 Redis从机配置 改变从=>主角色 Redis哨兵 运行哨兵 Redis 哨兵自动故障转移 相关链接 第一部分-- Redis:复制,第1部分-- ...

  2. Redis的复制详解

    复制基础概念 Redis的主从复制特点 一个master可以有多个slave 可以用级联复制功能 master是以非阻塞的方式来同步数据给slave 其实redis的复制和mysql的主从复制很相似, ...

  3. Redis:复制,第3部分——redis-py和Python中的Redi哨兵一起使用

    目录 redis-py和Redis redis-py和Redis 哨兵 主机改变和哨兵故障转移 关于Redis复制和Redis哨兵的主题仍然是--使用Python的redis-py库的几个例子. 以前 ...

  4. Redis(八):Redis的复制(Master/Slave)

    Redis的复制(Master/Slave)目录导航: 是什么 能干嘛 怎么玩 复制原理 哨兵模式(sentinel) 复制的缺点 是什么 官网 行话:也就是我们所说的主从复制,主机数据更新后根据配置 ...

  5. Redis的复制(Master/Slave)

    Redis的复制:就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 从库配置:slaveof 主库IP 主 ...

  6. Redis(二)——复制

    前边的Redis持久化解决了,单机故障能够重启恢复备份数据的功能.而在分布式系统中,为了解决单点问题,达到高可用的目的,需要进行redis数据分布式,进行多台机器实时备份,从而满足更高效的故障恢复和负 ...

  7. redis之复制之谜(二)

    redis的复制第三版(异步复制之replica异步) redis在2.2.0版本中引入了replica异步接收数据 replica连接上master,经过密码认证通过后(新加的密码认证过程,auth ...

  8. redis主从复制,复制功能是高可用Redis的基础,为满足故障恢复和负载均衡等需求把Redis数据复制多个副本部署到其他机器;如何实现redis的主从复制模式以及主从复制模式下常见的运维问题;

    目录 一.如何使用redis主从复制模式 1.建立复制 2.断开复制 3.安全性 4.只读模式 5.传输延迟 二.Redis的复制拓扑结构 1.一主一从结构 2.一主多从结构 3.树状主从结构 三.主 ...

  9. 《redis设计与实现 》15复制-源码部分

    一 序 上一篇整理了redis复制的概念性流程  ,本篇结合复制的实现来看下源码. 复制的建立方法有三种: 在redis.conf文件中配置slaveof <masterip> <m ...

  10. redis——新版复制

    sync虽然解决了数据同步问题,但是在数据量比较大情况下,从库断线从来依然采用全量复制机制,无论是从数据恢复.宽带占用来说,sync所带来的问题还是很多的.于是redis从2.8开始,引入新的命令ps ...

最新文章

  1. Linux第五次作业
  2. PHP 5.4 的新特性
  3. 线程安全且高效的单例
  4. android音频开发6,Android 音视频开发(一) : 通过三种方式绘制图片
  5. Docker之Linux Cgroups
  6. 【转】ABP源码分析三十二:ABP.SignalR
  7. android真机调试看不到logcat信息
  8. broker druid 查询_即时查询工具| Druid
  9. 无线通信基础(一):无线网络演进
  10. 计算机专业毕业答辩ppt优秀范例,毕业论文答辩PPT模板优秀范例课件.ppt
  11. 通过url获取域名和协议,一级域名,二级域名 python
  12. MATLAB雾霾天气下运动目标检测
  13. 金仓数据库 KingbaseES 插件参考手册(23. dbms_utility)
  14. 高速电路设计实践学习笔记(一)电阻 电容 电感 磁珠
  15. Cairo-基本概念
  16. Spark面试题(二)
  17. matlab最基础教程(四):常用的系统自带函数,符号变量与字符串篇
  18. 我的houdini无法查看节点属性WindowsError 234
  19. mac m1上esc键失灵不能退出vi解决方法
  20. Java标识符的命名规则有哪些

热门文章

  1. 当我谈跑步时我谈些什么——村上春树
  2. 系统功能的可配置性设想
  3. Docker学习——Dockerfile 指令详解(五)
  4. jsp页面根据json数据动态生成table
  5. vue从入门到进阶:自定义指令directive,插件的封装以及混合mixins(七)
  6. linux实例大全学习笔记1
  7. 通过组策略实现客户端注册证书
  8. 输出枚举类型的值(seqmentation fault)
  9. 08-Windows Server 2012 R2 会话远程桌面-标准部署-使用PowerShell进行部署2-1
  10. 寻找GridView中模板列中的控件