前言

只有光头才能变强

好的,今天我们要上铂金段位了,如果还没经历过青铜和白银和黄金阶段的,可以先去蹭蹭经验再回来:

这篇文章主要讲的是Redis主从复制。因为Redis集群的知识点有点多,所以铂金上分得要好几篇~

文本力求简单讲清每个知识点,希望大家看完能有所收获

一、主从架构

1.1为什么要主从架构

Redis也跟关系型数据(MySQL)一样,如果有过多请求还是撑不住的。

因为Redis如果只有一台服务器的话,那随着请求越来越多:

  • Redis的内存是有限的,可能放不下那么多的数据
  • 单台Redis支持的并发量也是有限的
  • 万一这台Redis挂了,所有的请求全走关系数据库了,那就更炸了。

显然,出现的上述问题是因为一台Redis服务器不够,所以多搞几台Redis服务器就可以了

为了实现我们服务的高可用性,可以将这几台Redis服务器做成是主从来进行管理

tip:Redis作者已将Master/Slave架构改名为Master/Replica

1.2主从架构的特点

下面我们来看看Redis的主从架构特点:

  • 服务器负责接收请求
  • 服务器负责接收请求
  • 从服务器的数据由主服务器复制过去。主从服务器的数据是一致

主从架构的好处

  • 读写分离(主服务器负责写,从服务器负责读)
  • 高可用(某一台从服务器挂了,其他从服务器还能继续接收请求,不影响服务)
  • 处理更多的并发量(每台从服务器都可以接收读请求,读QPS就上去了)

主从架构除了上面的形式,也有下面这种的(只不过用得比较少):

二、复制功能

主从架构的特点之一:主服务器和从服务器的数据是一致的。

因为主服务器是能接收写请求的,主服务器处理完写请求,会做什么来保证主从数据的一致性呢?如果主从服务器断开了,过一阵子才重连,又会怎么处理呢?下面将会了解到这些细节~

在Redis中,用户可以通过执行SALVEOF命令或者设置salveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(salve)

2.1复制功能的具体实现

复制功能分为两个操作:

  • 同步(sync)

    • 将从服务器的数据库状态更新至主服务器的数据库状态
  • 命令传播(command propagate)
    • 主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致,让主从服务器的数据库状态重新回到一致状态

从服务器对主服务器的同步又可以分为两种情况

  • 初次同步:从服务器没有复制过任何的主服务器,或者从服务器要复制的主服务器跟上次复制的主服务器不一样
  • 断线后同步:处于命令传播阶段的主从服务器因为网络原因中断了复制,从服务器通过自动重连重新连接主服务器,并继续复制主服务器

在Redis2.8以前,断线后复制这部分其实缺少的只是部分的数据,但是要让主从服务器重新执行SYNC命令,这样的做法是非常低效的。(因为执行SYNC命令是把所有的数据再次同步,而不是只同步丢失的数据)

接下来我们来详细看看Redis2.8以后复制功能是怎么实现的:

2.1.1复制的前置工作

首先我们来看一下前置的工作

  • 从服务器设置主服务器的IP和端口
  • 建立与主服务器的Socket连接
  • 发送PING命令(检测Socket读写是否正常与主服务器的通信状况)
  • 身份验证(看有没有设置对应的验证配置)
  • 从服务器给主服务器发送端口的信息,主服务器记录监听的端口

前面也提到了,Redis2.8之前,断线后同步会重新执行SYNC命令,这是非常低效的。下面我们来看一下Redis2.8之后是怎么进行同步的。

Redis从2.8版本开始,使用PSYNC命令来替代SYNC命令执行复制时同步的操作。

PSYNC命令具有完整重同步和部分重同步两种模式(其实就跟上面所说的初次复制和断线后复制差不多个意思)。

2.1.2完整重同步

下面先来看看完整重同步是怎么实现的:

  • 从服务器向主服务器发送PSYNC命令
  • 收到PSYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件。并用一个缓冲区来记录从现在开始执行的所有写命令
  • 当主服务器的BGSAVE命令执行完后,将生成的RDB文件发送给从服务器,从服务器接收和载入RBD文件。将自己的数据库状态更新至与主服务器执行BGSAVE命令时的状态。
  • 主服务器将所有缓冲区的写命令发送给从服务器,从服务器执行这些写命令,达到数据最终一致性。

2.1.2部分重同步

接下来我们来看看部分重同步,部分重同步可以让我们断线后重连只需要同步缺失的数据(而不是Redis2.8之前的同步全部数据),这是符合逻辑的!

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

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

首先我们来解释一下上面的名词:

复制偏移量:执行复制的双方都会分别维护一个复制偏移量

  • 主服务器每次传播N个字节,就将自己的复制偏移量加上N
  • 从服务器每次收到主服务器的N个字节,就将自己的复制偏移量加上N

通过对比主从复制的偏移量,就很容易知道主从服务器的数据是否处于一致性的状态!

那断线重连以后,从服务器向主服务器发送PSYNC命令,报告现在的偏移量是36,那么主服务器该对从服务器执行完整重同步还是部分重同步呢??这就交由复制积压缓冲区来决定。

当主服务器进行命令传播时,不仅仅会将写命令发送给所有的从服务器,还会将写命令入队到复制积压缓冲区里面(这个大小可以调的)。如果复制积压缓冲区存在丢失的偏移量的数据,那就执行部分重同步,否则执行完整重同步。

服务器运行的ID(run ID)实际上就是用来比对ID是否相同。如果不相同,则说明从服务器断线之前复制的主服务器和当前连接的主服务器是两台服务器,这就会进行完整重同步。

所以流程大概如此:

2.1.3命令传播

当完成了同步之后,主从服务器就会进入命令传播阶段。这时主服务器只要将自己的写命令发送给从服务器,而从服务器接收并执行主服务器发送过来的写命令,就可以保证主从服务器一直保持数据一致了!

在命令传播阶段,从服务器默认会以每秒一次的频率,向服务器发送命令REPLCONF ACK <replication_offset> 其中replication_offset是从服务器当前的复制偏移量

发送这个命令主要有三个作用:

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

五、最后

画了好久好久的图,终于写完啦。

抛个问题:如果从服务器挂了,没关系,我们一般会有多个从服务器,其他的请求可以交由没有挂的从服务器继续处理。如果主服务器挂了,怎么办?因为我们的写请求由主服务器处理,只有一台主服务器,那就无法处理写请求了?

问题留到下篇解决~~

参考资料:

  • 《Redis设计与实现》
  • 《Redis实战》

如果你觉得我写得还不错,了解一下:

从零单排学Redis【铂金一】的更多相关文章

  1. 从零单排学Redis【铂金二】

    前言 只有光头才能变强 好的,今天我们要上[铂金二]了,如果还没有上铂金的,赶紧先去蹭蹭经验再回来(不然不带你上分了): 从零单排学Redis[青铜] 从零单排学Redis[白银] 从零单排学Redi ...

  2. 从零单排学Redis【黄金】

    前言 只有光头才能变强 好的,今天我们要上黄金段位了,如果还没经历过青铜和白银阶段的,可以先去蹭蹭经验再回来: 从零单排学Redis[青铜] 从零单排学Redis[白银] 看过相关Redis基础的同学 ...

  3. 从零单排学Redis【白银】

    前言 只有光头才能变强 今天继续来学习Redis,上一篇从零单排学Redis[青铜]已经将Redis常用的数据结构过了一遍了.如果还没看的同学可以先去看一遍再回来~ 这篇主要讲的内容有: Redis服 ...

  4. 【3y】从零单排学Redis【青铜】

    前言 只有光头才能变强 最近在学Redis,我相信只要是接触过Java开发的都会听过Redis这么一个技术.面试也是非常高频的一个知识点,之前一直都是处于了解阶段.秋招过后这段时间是没有什么压力的,所 ...

  5. 零基础学redis

    第一个阶段:redis基本知识了解: 1. redis的百度百科解释: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...

  6. 从零单排学JavaWeb

    之前是一个asp爱好者,感觉前途渺茫,特此转向Powerful的Java阵型,寻求心灵上的慰藉. 把自己遇到的问题记录下来,同时也分享给大家.  环境-下载 1 JDK http://dlsw.bai ...

  7. JAVA从零单排之前因

    本人,男,21岁,普通院校本科,计算机专业.大学之前对计算机编程没有一点涉及.大学学计算机专业也是个偶然.因为当初高考的成绩不好,结果都是我父亲帮我报的学校和专业. 上了大学之后,大一都是在新奇中度过 ...

  8. Unity3D游戏开发从零单排(四) - 制作一个iOS游戏

    提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...

  9. (1)风色从零单排《C++ Primer》 一个简单的c++程序

    从零单排<C++ Primer> --(1)一个简单的c++程序 本次学习收获 0.写在前面 风色以前上过C++的课程,然而当时并没有认真去学,基本不能使用c++来作项目开发. 这次又一次 ...

随机推荐

  1. Elasticsearch java api 常用查询方法QueryBuilder构造举例

    转载:http://m.blog.csdn.net/u012546526/article/details/74184769 Elasticsearch java api 常用查询方法QueryBuil ...

  2. Beta项目总结

    Beta冲刺成员名单和工作量比例 姓名 学号 负责内容 工作量比例 张梨贤 170327109 负责企业人员的委托/收回授权.第三方机构的委托授权管理.分级统计展示.分级列表展示 26% 黄腾飞 17 ...

  3. linux下svn(subversion)服务端添加工程及配置权限

    linux下svn(subversion)服务端添加工程及配置权限 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/9010507.html 此篇我只是将所做过的 ...

  4. python 面向对象进阶之元类metaclass

    一:知识储备 exec exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定,默认为globals() 参数三:局部作用域(字典形式),如果不指定,默认为local ...

  5. 高通调试 SPI 屏的 bug

    1. spi调试问题: 问题描述: spi屏幕lk启动的时候正常出现小企鹅,到kernel启动的过程黑屏并且花屏才到开机动画: 2. 黑屏的三个阶段: 参照:黑屏分析 分析开机过程黑屏,首先需要定位黑 ...

  6. PAT1031:Hello World for U

    1031. Hello World for U (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Giv ...

  7. python函数调用的四种方式 --基础重点

    第一种:参数按顺序从第一个参数往后排#标准调用 # -*- coding: UTF-8 -*- def normal_invoke(x, y): print "--normal_invoke ...

  8. jquery的$.extend和$.fn.extend作用及区别/用span实现进度条/腾讯云IIS端口号修改

    jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(); jQuery.extend(); 虽然 javascript 没有明确的类的概念,但是用类来理解它,会更方便. ...

  9. 一次完整的HTTP网络请求过程详解

    0.  前言 从我们在浏览器的地址栏输入http://blog.csdn.net/seu_calvin后回车,到我们看到该博客的主页,这中间经历了什么呢?简单地回答这个问题,大概是经历了域名解析.TC ...

  10. CSS技术实例1-使用CSS计数器实现数值计算小游戏实例页面

    一 实例要达到的要求如图所示: 二 分析 1.7个圆角矩形标签(或按钮) 2. 点击触发并开始运算,最后一个标签显示结果 3.计算成功后弹出"万岁"字眼 三 代码实现 关键CSS代 ...