Redis-主从复制

分布式系统,涉及到一个非常关键的问题:单点问题

如果某个服务器程序,只有一个节点,就会出现:

  • 可用性问题(这个服务器挂了,服务中断)
  • 性能/支持的并发量有限

引入分布式系统,主要也是为了解决上述的单点问题

在分布式系统中,希望有多个服务器来部署redis服务,从而构成一个redis集群,此时就可以让这个集群给整个分布式系统中其它的服务,提供更稳定/高效的数据存储功能

下面有三种redis的部署方式:

主从模式 主从+哨兵 集群模式

此处来讲解主从模式

1. 配置

参与复制的Redis实例划分为主节点(master)和从节点(slave)。每个从结点只能有⼀个主节点, ⽽⼀个主节点可以同时具有多个从结点。

复制的数据流是单向的,只能由主节点到从节点,改变主节点的内容,同步到从节点

从节点的数据时刻和主节点保持一致,因此其它的客户端从从节点这里读取数据,和从主节点这里读取数据,没有区别

从节点数据只能读取,不允许修改

之前只是单个redis服务器节点,此时这个机器挂了,整个redis就挂了,引入主从结构,就不太可能一锅端了

主从模式,主要如果主节点挂了,无法写数据,只能读,从节点挂了,无影响

主从模式针对"读操作"进行并发量,可用性提高

那可以引入多个主节点嘛?

不可以,一山不容二虎,谁听谁呢

建立复制

此时在一个云服务器主机上,运行多个redis-server进程

让新启动的redis-server使用其它端口

1.在配置⽂件中设定端口

  1. 在redis-server 启动时,通过命令行指定端口 --port选项

下面一个主节点,两个从节点:

按c进行修改,ctrl+c进行退出修改界面,:wq保存退出

表示可以按照后台方式进行运行

当前这几个节点并没有构成主从结构,下面需要进一步配置:

1.在配置⽂件中加⼊slaveof{masterHost}{masterPort}随Redis启动⽣效。

  1. 在redis-server 启动命令时加⼊--slaveof{masterHost}{masterPort}⽣效。

  2. 直接使⽤redis命令:slaveof{masterHost}{masterPort}⽣效

修改之后,重新启动,生效

这种停止redis-server的方式,kii之后,redis-server进程能够自动启动

而如果使用service redis-server start这种方式启动,必须使用service redis-server stop停止

从节点启动之后就会和主节点建立tcp连接.主节点相当于服务器,从节点相当于客户端

此时主节点这里的数据进行修改,从节点能立即感知到:

从节点无法写:

主从节点复制过程

1)查看主节点复制状态信息:

主节点会收到源源不断的修改数据请求,从节点就需要从主节点这里同步这些修改请求

从节点和主节点之间的数据同步,不是瞬间完成的

offset:相当于同步数据的进度

lag:表示延迟,网络有可能延迟情况

master_replid:主节点的身份标识,从节点会记录

repl:积压缓冲区,支持部分同步机制的实现

2)查看从节点复制状态信息:

断开复制

slaveof no one命令

从节点断开主从关系后,就不属于其它节点了,但里面已有的数据不会抛弃

此时让6380作为6381的从节点:

此时,6381看起来是个主节点,但实际上仍然是从节点,不能修改数据

虽然刚才通过slaveof命令修改了主从结构,但是此处的修改是临时性的,重新启动redis服务器,仍然会按照最初在配置文件中设置的内容建立主从关系

安全性

对于数据⽐较重要的节点,主节点会通过设置requirepass参数进⾏密码验证,需要配置从节点的masterauth参数与主节点密码保持⼀致,这样从节点才可以正确地连接到主节点并发起复制流程

只读

从节点不允许修改

传输延迟

主从节点之间通过网络传输(tcp)

TCP内部支持nagle算法(默认开启):

开启,就会增加传输延迟,节省网络带宽

关闭,就会减少传输延迟,增加网络带宽

2. 拓扑

一主一从

如果写数据请求太多,此时会给主节点造成压力

可以通过关闭主节点的AOF,只在从节点开启AOF

但是,这种设定方式,会有一个严重的缺陷:主节点一旦挂了,不能让他自动重启(如果自动重启,没有AOF文件,就会丢失数据,进一步的主从同步,会把从节点的数据也删了)

改进:主节点挂了后,让主节点从从节点获取AOF文件,再启动

一主多从

主节点上的数据发生改变,就会把改变的数据同时同步给所有的从节点,网络延时小

随着从节点个数的增加,同步一条数据,需要传输多次

改进:

树状主从

此时,主节点就不需要那么高的网卡带宽了

但是一旦数据修改了,同步的延时更长

3. 原理

主从节点建⽴复制流程图

数据同步psync

redis提供了psync命名,完成数据同步的过程,分为:全量复制和部分复制

  • 全量复制:⼀般⽤于初次复制场景,Redis早期⽀持的复制功能只有全量复制,它会把主节点全部数据⼀次性发送给从节点,当数据量较⼤时,会对主从节点和⽹络造成很⼤的开销。
  • 部分复制:⽤于处理在主从复制中因⽹络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。因为补发的数据远⼩于全量数据,可以有效避免全量复制的过⾼开销

不需要手动执行,redis服务器会在建立好主从同步关系之后,自动执行

从节点负责执行psync,从节点从主节点这边拉取数据

语法:

psync replicationid offset

①replicationid/replid (复制id)

是主节点启动时生成的

即使是同一个主节点,每次重启生成的replicationid都是不同的

从节点晋升为主节点,也会生成

主从关系建立时,从节点就会从主节点这边获取到replicationid

一般情况下,replid2用不上

举个例子:

有一个主节点A,从节点B

在A和B通信过程中出现了网络抖动

B就可能认为A挂了

B就会自己成为主节点,给自己生成一个repid,此时B也会记得之前旧的replid,即replid2

后续网络稳定了,B还可以根据replid2重新恢复之前的状态

②offset(偏移量)

主节点和从节点都会维护整个偏移量(整数)

主节点的偏移量:主节点会收到很多修改操作的命令,每个命令都要占据几个字节,主节点会把这些命令,每个命令的字节数进行累加

从节点的偏移量:描述了现在从节点这里的数据同步到哪里了

如果从节点的偏移量和主节点一样,就赶上"直播"了

从节点每秒上报自身的复制偏移量给主节点

总结:

replicationid和offset共同描述了一个"数据集合",

如果两个机器的这两个变量都一样,就可以认为这两个redis机器上存储的数据完全一样

psync运行流程

psync可以从主节点获取全量数据,还是获取一部分,主要看offset这里的进度

offset=-1,就是获取全量数据

offset写具体的正整数,则是从当前偏移量位置来进行获取

获取所有数据,是最稳妥的,但是比较低效,如果从节点之前以及把主节点这里复制过一部分数据了,就只需要把没复制的数据搞来就可

当然,不是从节点索要哪部分,主节点就一定给哪部分,主节点会自行判定,看当前是否方便给部分数据,不方便就给全量

全量复制

什么时候全量复制

1.首次和主节点进行数据同步

2.主节点不方便进行部分复制


全量复制的流程

流程描述:

  1. 从节点发送psync命令给主节点进⾏数据同步,由于是第⼀次进⾏复制,从节点没有主节点的运⾏ID和复制偏移量,所以发送psync?-1。
  2. 主节点根据命令,解析出要进⾏全量复制,回复+FULLRESYNC响应。
  3. 从节点接收主节点的运⾏信息进⾏保存。
  4. 主节点执⾏bgsave进⾏RDB⽂件的持久化。
  5. 从节点发送RDB⽂件给从节点,从节点保存RDB数据到本地硬盘。
  6. 主节点将从⽣成RDB到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点保存完RDB⽂件 后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照rdb的⼆进制格式追加写⼊到收 到的rdb⽂件中.保持主从⼀致性。
  7. 从节点清空⾃⾝原有旧数据。
  8. 从节点加载RDB⽂件得到与主节点⼀致的数据。
  9. 如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进⾏bgrewrite操作,得到最近的AOF⽂件。

注意:

  • 在主节点生成rdb文件和传输rdb文件的过程中,还会继续收到很多新的修改操作.新修改的数据,也必须同步给从节点,当从节点收完了主节点发来的rdb之后,主节点就会把这些新修改的操作发送给从节点
  • 如果从节点,已经开启了AOF,在上述的加载数据过程中,从节点就会产生很多的AOF日志,由于当前收到的是大批量的数据,此时产生的AOF日志,整体来说会存在一定的冗余信息,因此要针对AOF日志进行整理

全量复制的无硬盘模式

主节点,进行全量复制的时候,也支持"无硬盘模式":

就是主节点生成的rdb的二进制数据,不直接保存在文件中,而是直接进行网络传输,省下了一系列读硬盘和写硬盘的操作

从节点也是先把收到的rdb数据,写入硬盘中,然后再加载,现在就可以省略这个过程,直接把收到的数据进行加载了

即使引入了无硬盘模式,整个操作仍然比较耗时,网络传输是不能省的,相比于网络传输,读写硬盘是小事

runid和replid

在一个redis服务器上,两者是都存在的,但是不一样

主节点:

info replication:

info server:

从节点:

run_id是每个节点都不相同的

replid则是具有主从关系的节点,是相同的

官方文档上,明确说了此处使用replicationid


部分复制

什么时候部分复制

从节点之前已经从主节点复制过数据,因为网络抖动或者从节点重启了,从节点需要重新同步数据,看看能不能只同步一部分(大部分数据一致)

但网络抖动,一般都是暂时的,恢复后就可以重新建立联系,此时就需要进行数据的同步

部分复制的流程

psync带有具体的replid和offset

主节点就要根据psync的参数进行判定进行什么复制

流程:

  1. 当主从节点之间出现⽹络中断时,如果超过repl-timeout时间,主节点会认为从节点故障并终端复制连接。
  2. 主从连接中断期间主节点依然响应命令,但这些复制命令都因⽹络中断⽆法及时发送给从节点,所 以暂时将这些命令滞留在复制积压缓冲区中。
  3. 当主从节点⽹络恢复后,从节点再次连上主节点。
  4. 从节点将之前保存的replicationId和复制偏移量作为psync的参数发送给主节点,请求进⾏部分复制。
  5. 主节点接到psync请求后,进⾏必要的验证。随后根据offset去复制积压缓冲区查找合适的数据, 并响应+CONTINUE给从节点。
  6. 主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性。

积压缓冲区:

是一个内存中的简单队列,会记录最近一段时间修改的数据,总量有限,随着时间的推移,就会把之前的旧数据删除

主节点看这个进度是否在当前的积压缓冲区之内,如果在,就可以进行部分复制,把最近这段时间的数据复制过去即可

如果已经超出积压缓冲区的范围,就得全量复制了


实时复制

主从节点在建⽴复制连接后,主节点会把⾃⼰收到的修改操作,通过tcp⻓连接的⽅式,源源不断的传 输给从节点.从节点就会根据这些请求来同时修改⾃⾝的数据.从⽽保持和主节点数据的⼀致性.

这样的⻓连接,需要通过⼼跳包的⽅式来维护连接状态

心跳包机制

主节点:默认,每隔10s给从节点发送一个ping命令,从节点收到就返回pong

从节点:默认,每隔1s就给主节点发起一个特定的请求,就会上报当前从节点复制数据的进度offset

如果主节点发现从节点通信延迟超过repl-timeout配置的值(默认60秒),则判定从节点下线,断 开复制客⼾端连接。从节点恢复连接后,⼼跳机制继续进⾏


从节点晋升为主节点的问题

从节点和主节点断开的情况:

1.slave no one 这个时候,可以晋升

2.主节点挂了 这个时候,从节点不会晋升,必须通过人工干预的方式恢复主节点,脱离掌控

可以通过service redis-server stop模拟一下(简,后续再修改):

1.停止之前的redis服务器

2.删除之前工作目录下,已经生成的AOF文件,或者也可以通过chown命令修改AOF文件所属的用户

3.给从节点创建出新的目录,作为从节点的工作目录,并且修改从节点的配置文件,设定为新的目录为工作目录

4.启动服务器

相关推荐
小吴编程之路20 分钟前
MySQL 索引核心特性深度解析:从底层原理到实操应用
数据库·mysql
~莫子31 分钟前
MySQL集群技术
数据库·mysql
凤山老林41 分钟前
SpringBoot 使用 H2 文本数据库构建轻量级应用
java·数据库·spring boot·后端
就不掉头发1 小时前
Linux与数据库进阶
数据库
与衫1 小时前
Gudu SQL Omni 技术深度解析
数据库·sql
咖啡の猫1 小时前
Redis桌面客户端
数据库·redis·缓存
oradh1 小时前
Oracle 11g数据库软件和数据库静默安装
数据库·oracle
what丶k2 小时前
如何保证 Redis 与 MySQL 数据一致性?后端必备实践指南
数据库·redis·mysql
_半夏曲2 小时前
PostgreSQL 13、14、15 区别
数据库·postgresql
把你毕设抢过来2 小时前
基于Spring Boot的社区智慧养老监护管理平台(源码+文档)
数据库·spring boot·后端