redis(二十):Redis 架构模式实现(主从复制)
什么是主从复制
我们可以通过slaveof <host> <port>命令,或者通过配置slaveof选项,来使当前的服务器(slave)复制指定服务器(master)的内容,被复制的服务器称为主服务器(master),对主服务器进行复制操作的为从服务器(slave)
主服务器master可以进行读写操作,当主服务器的数据发生变化,master会发出命令流来保持对salve的更新,而从服务器slave通常是只读的(可以通过slave-read-only指定),在主从复制模式下,即便master宕机了,slave是不能变为主服务器进行写操作的
一个master可以有多个slave,即一主多从;而slave也可以接受其他slave的连接,形成“主从链”层叠状结构(cascading-like structure),自 Redis 4.0 起,所有的sub-slave也会从master收到完全一样的复制流。如下图

主从复制的好处:
数据冗余,实现数据的热备份故障恢复,避免单点故障带来的服务不可用读写分离,负载均衡。主节点负载读写,从节点负责读,提高服务器并发量高可用基础,是哨兵机制和集群实现的基础主从复制的配置
使用和配置主从复制是比较简单的,在从服务器slave的配置文件中设置slaveof选项,或者直接使用slaveof <masterip> <masterport>命令
这里我使用3台虚拟机来搭建一下,主服务器的ip为192.168.249.20,两个从服务器的ip分别为192.168.249.21和192.168.249.21,端口号都为6379,具体的配置如下主服务器并不需要额外多配置什么,这里我们先把三台服务器的都需要改的地方列一下

在从服务器中添加配置slaveof <masterport> <masterport>选项,在5.0版本中使用了replicaof代替了slaveof。
slaveof还可以继续使用,不过建议使用replicaof。如果是使用命令行来复制的话,重启之后会无效

配置好redis.conf之后,我们分别启动3台服务器,可以用户命令info replication查看复制信息



接下来我们可以在主服务器中写入数据,然后可以在其他的从服务器中读取数据

然后我们试着在从服务器中写入数据,会提示不能在只读的从服务器中写入数据

如果我们需要slave对master的复制进行验证,可以在master中配置requirepass选项设置密码那么需要在从服务器中使用该密码,可以使用命令config set masterauth,或者在配置文件中设置masterauth
主从复制的实现原理
主从复制的配置还是比较简单的,下面来了解下主从复制的实现原理
Redis的主从复制过程大体上分3个阶段:建立连接、数据同步、命令传播
建立连接
这个阶段主要是从服务器发出slaveof命令之后,与主服务器如何建立连接,为数据同步做准备的过程。
1)在slaveof命令执行之后,从服务器根据设置的master的ip地址和端口,创建连向主服务器的socket套接字连接,连接成功后,从服务器会为这个套接字关联一个专门的处理器,用于处理后续的复制工作
2)建立连接之后,从服务器会向主服务器发送ping命令,确认主服务器是否可用,以及当前是否可用接受处理命令。如果收到主服务器的pong回复说明是可用的,否则有可能是网络超时或主服务器阻塞,从服务器会断开连接发起重连
3)身份验证。如果主服务器设置了requirepass选项,那么从服务器必须配置masterauth选项,且保证密码一致才能通过验证
4)身份验证完成之后,从服务器会发送自己的监听端口,主服务器会保存下来

数据同步
在主从服务器建立连接确认各自身份之后,就开始数据同步,从服务器向主服务器发送PSYNC命令,执行同步操作,并把自己的数据库状态更新至主服务器的数据库状态
Redis的主从同步分为:完整重同步(full resynchronization)和部分重同步(partial resynchronization)
完整重同步
有两种情况下是完整重同步,一是slave连接上master第一次复制的时候;二是如果当主从断线,重新连接复制的时候有可能是完整重同步,这个在后面说
下面是完整重同步的步骤

从服务器连接主服务器,发送SYNC命令主服务器接收到SYNC命名后,开始执行bgsave命令生成RDB文件并使用缓冲区记录此后执行的所有写命令主服务器basave执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令从服务器收到快照文件后丢弃所有旧数据,载入收到的快照主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令部分重同步
部分重同步是用于处理断线后重复制的情况,先介绍几个用于部分重同步的部分
runid(replication ID),主服务器运行id,Redis实例在启动时,随机生成一个长度40的唯一字符串来标识当前节点offset,复制偏移量。主服务器和从服务器各自维护一个复制偏移量,记录传输的字节数。当主节点向从节点发送N个字节数据时,主节点的offset增加N,从节点收到主节点传来的N个字节数据时,从节点的offset增加Nreplication backlog buffer,复制积压缓冲区。是一个固定长度的FIFO队列,大小由配置参数repl-backlog-size指定,默认大小1MB。需要注意的是该缓冲区由master维护并且有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据当slave连接到master,会执行PSYNC <runid> <offset>发送记录旧的master的runid(replication ID)和偏移量offset,这样master能够只发送slave所缺的增量部分。但是如果master的复制积压缓存区没有足够的命令记录,或者slave传的runid(replication ID)不对,就会进行完整重同步,即slave会获得一个完整的数据集副本

PSYNC命令执行完整重同步和部分重同步的流程图

命令传播
当完成数据同步之后,主从服务器的数据暂时达到一致状态,当主服务器执行了客户端的写命令之后,主从的数据便不再一致。为了能够使主从服务器的数据保持一致性,主服务器会对从服务器执行命令传播操作,即每执行一个写命令就会向从服务器发送同样的写命令
在命令传播阶段,从服务器会默认以每秒一次的频率向主服务器发送心跳检测REPLCONF ACK <replication_offset>其中replication_offset是当前从服务器的复制偏移量,该命令的作用有三个
检测主从服务器的网络连接状态辅助实现min-slaves选项检测命令丢失关闭持久化时,复制的安全性
关于关闭持久化时,复制的安全性问题,可以参考官网的描述。
在使用Redis复制功能时的设置中,强烈建议在master和在slave中启用持久化。当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重置后自动重启。
为了更好地理解为什么关闭了持久化并配置了自动重启的 master 是危险的,检查以下故障模式,这些故障模式中数据会从 master 和所有 slave 中被删除:
我们设置节点 A 为 master 并关闭它的持久化设置,节点 B 和 C 从 节点 A 复制数据。节点 A 崩溃,但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了,节点重启后其数据集合为空。节点 B 和 节点 C 会从节点 A 复制数据,但是节点 A 的数据集是空的,因此复制的结果是它们会销毁自身之前的数据副本。当 Redis Sentinel 被用于高可用并且 master 关闭持久化,这时如果允许自动重启进程也是很危险的。例如, master 可以重启的足够快以致于 Sentinel 没有探测到故障,因此上述的故障模式也会发生。
任何时候数据安全性都是很重要的,所以如果 master 使用复制功能的同时未配置持久化,那么自动重启进程这项应该被禁用
redis(二十):Redis 架构模式实现(主从复制)的更多相关文章
- SpringBoot开发二十-Redis入门以及Spring整合Redis
安装 Redis,熟悉 Redis 的命令以及整合Redis,在Spring 中使用Redis. 代码实现 Redis 内置了 16 个库,索引是 0-15 ,默认选择第 0 个 Redis 的常用命 ...
- Java 设计模式系列(二十)状态模式
Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...
- Redis进阶实践之二十 Redis的配置文件使用详解
一.引言 写完上一篇有关redis使用lua脚本的文章,就有意结束Redis这个系列的文章了,当然了,这里的结束只是我这个系列的结束,但是要学的东西还有很多.但是,好多天过去了,总是感觉好像还缺点什么 ...
- C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例子吧,理解起来可能更 ...
- Redis(二十):Redis数据过期和淘汰策略详解(转)
原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...
- Redis(二)、Redis持久化RDB和AOF
一.Redis两种持久化方式 对Redis而言,其数据是保存在内存中的,一旦机器宕机,内存中的数据会丢失,因此需要将数据异步持久化到硬盘中保存.这样,即使机器宕机,数据能从硬盘中恢复. 常见的数据持久 ...
- Java进阶专题(二十) 消息中间件架构体系(2)-- RabbitMQ研究
前言 接上文,这个继续介绍RabbitMQ,并理解其底层原理. 介绍 RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的 ...
- Selenium系列(二十) - PageObject模式的详细介绍
如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...
- JavaWeb学习记录(二十)——Model1模式(javaBean+jsp)实现简单计算器案例
¨JSP技术提供了三个关于JavaBean组件的动作元素,即JSP标签,它们分别为: ¨<jsp:useBean>标签:用于在JSP页面中查找或实例化一个JavaBean组件. ¨< ...
- 设计模式(二十)Flyweight模式
当使用new关键字生成类的实例时,需要给其分配足够的内存空间.当程序中需要大量对象时,如果都是用new关键字来分配内存,将会消耗大量内存空间.Flyweight模式就是尽量避免new出实例,而是通过尽 ...
随机推荐
- [转] Git caret(^) and tilde(~)
点击阅读原文 I spent a little bit of time playing with Git today, specifically the way that the ^ (caret) ...
- 【loj - 6516】「雅礼集训 2018 Day11」进攻!
目录 description solution accepted code details description 你将向敌方发起进攻!敌方的防御阵地可以用一个 \(N\times M\) 的 \(0 ...
- mysql日期和时间类型
TIME 类型 TIME 类型用于只需要时间信息的值,在存储时需要 3 个字节.格式为 HH:MM:SS.HH 表示小时,MM 表示分钟,SS 表示秒. TIME 类型的取值范围为 -838:59:5 ...
- MySQL 性能优化细节
服务器层面优化(了解) 将数据保存在内存中,保证从内存读取数据 设置足够大的innodb_buffer_pool_size,将数据读取到内存中. 建议innodb_buffer_pool_size设置 ...
- 【JMeter_19】JMeter逻辑控制器__简单控制器<Simple Controller>
简单控制器<Simple Controller> 业务逻辑: 就像他的名字一样,简单,可以理解为一个文件夹,就是分组用的,没有其他特殊功能,但相比不添加简单控制器,区别在于简单控制器可以被 ...
- 浅谈RegExp 对象的方法
JavaScript RegExp 对象有 3 个方法:test().exec() 和 compile().(1) test() 方法用来检测一个字符串是否匹配某个正则表达式,如果匹配成功,返回 tr ...
- ubuntu 显示桌面快捷键
ubuntu 显示桌面快捷键 快速显示桌面的快捷键是 ctrl + win + d win:就是窗口键,在键盘左侧ctrl与Alt之间的那个建.
- GIT本地库基本操作-命令行
GIT本地库操作基本原理 GIT作为分布式版本库软件,每个机器上都是一个版本库. git初始化后,有三个区,分别是 工作区,暂存区,本地库: 工作区是我们编辑代码的区别,包括新增,修改,删除代码操作, ...
- Mac OS 生成 icon 和 ico 文件
[本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 1. 生成 IC ...
- Spring事务深入剖析--spring事务失效的原因
之前我们讲的分布式事务的调用都是在一个service中的事务方法,去调用另外一个service中的业务方法, 如果在一个sevice中存在两个分布式事务方法,在一个seivice中两个事务方法相互嵌套 ...