Redis主从复制的配置和实现原理

Redis的持久化功能在一定程度上保证了数据的安全性,即便是服务器宕机的情况下,也可以保证数据的丢失非常少。通常,为了避免服务的单点故障,会把数据复制到多个副本放在不同的服务器上,且这些拥有数据副本的服务器可以用于处理客户端的读请求,扩展整体的性能

下面会介绍Redis的主从复制配置和实现原理,后续还会有Redis的高可用方案:哨兵机制(Sentinel)、分区集群(Cluster)

什么是主从复制

我们可以通过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.21192.168.249.21,端口号都为6379,具体的配置如下

主服务器并不需要额外多配置什么,这里我们先把三台服务器的都需要改的地方列一下

 

复制代码

# 设置为后台运行 daemonize yes # 保存pid的文件,如果是在一台机器搭建主从,需要区分一下 pidfile /var/run/redis_6379.pid # 绑定的主机地址,这里注释掉,开放ip连接 #bind 127.0.0.1 # 指定日志文件 logfile "6379.log"

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

 

复制代码

# replicaof <masterip> <masterport> replicaof 192.168.249.20 6379

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

 

复制代码

192.168.249.20:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.249.22,port=6379,state=online,offset=700,lag=0 slave1:ip=192.168.249.21,port=6379,state=online,offset=700,lag=0 master_replid:b80a4720c0001efb62940f5ad6abaf9cdaf7a813 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:700 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:700 192.168.249.21:6379> info replication # Replication role:slave master_host:192.168.249.20 master_port:6379 master_link_status:up master_last_io_seconds_ago:3 master_sync_in_progress:0 slave_repl_offset:854 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:b80a4720c0001efb62940f5ad6abaf9cdaf7a813 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:854 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:57 repl_backlog_histlen:798 192.168.249.22:6379> info replication # Replication role:slave master_host:192.168.249.20 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_repl_offset:854 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:b80a4720c0001efb62940f5ad6abaf9cdaf7a813 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:854 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:854

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

 

复制代码

192.168.249.20:6379> set test 'Hello World' OK 192.168.249.21:6379> get test "Hello World" 192.168.249.22:6379> get test "Hello World"

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

 

复制代码

192.168.249.21:6379> set test2 hello (error) READONLY You can't write against a read only replica.

如果我们需要slave对master的复制进行验证,可以在master中配置requirepass <password>选项设置密码

那么需要在从服务器中使用该密码,可以使用命令config set masterauth <password>,或者在配置文件中设置masterauth <password>

主从复制的实现原理

主从复制的配置还是比较简单的,下面来了解下主从复制的实现原理

Redis的主从复制过程大体上分3个阶段:建立连接数据同步命令传播

建立连接

这个阶段主要是从服务器发出slaveof命令之后,与主服务器如何建立连接,为数据同步做准备的过程。

1)在slaveof命令执行之后,从服务器根据设置的master的ip地址和端口,创建连向主服务器的socket套接字连接,连接成功后,从服务器会为这个套接字关联一个专门的处理器,用于处理后续的复制工作

2)建立连接之后,从服务器会向主服务器发送ping命令,确认主服务器是否可用,以及当前是否可用接受处理命令。如果收到主服务器的pong回复说明是可用的,否则有可能是网络超时或主服务器阻塞,从服务器会断开连接发起重连

3)身份验证。如果主服务器设置了requirepass选项,那么从服务器必须配置masterauth选项,且保证密码一致才能通过验证

4)身份验证完成之后,从服务器会发送自己的监听端口,主服务器会保存下来

 

复制代码

192.168.249.20:6379> info replication ... slave0:ip=192.168.249.22,port=6379,state=online,offset=700,lag=0 slave1:ip=192.168.249.21,port=6379,state=online,offset=700,lag=0 ...

数据同步

在主从服务器建立连接确认各自身份之后,就开始数据同步,从服务器向主服务器发送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增加N
  • replication 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选项
  • 检测命令丢失

关闭持久化时,复制的安全性

关于关闭持久化时,复制的安全性问题,我这里摘入官网的一段描述www.redis.cn/topics/repl…

在使用Redis复制功能时的设置中,强烈建议在master和在slave中启用持久化。当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重置后自动重启

为了更好地理解为什么关闭了持久化并配置了自动重启的 master 是危险的,检查以下故障模式,这些故障模式中数据会从 master 和所有 slave 中被删除:

  1. 我们设置节点 A 为 master 并关闭它的持久化设置,节点 B 和 C 从 节点 A 复制数据。
  2. 节点 A 崩溃,但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了,节点重启后其数据集合为空。
  3. 节点 B 和 节点 C 会从节点 A 复制数据,但是节点 A 的数据集是空的,因此复制的结果是它们会销毁自身之前的数据副本。

当 Redis Sentinel 被用于高可用并且 master 关闭持久化,这时如果允许自动重启进程也是很危险的。例如, master 可以重启的足够快以致于 Sentinel 没有探测到故障,因此上述的故障模式也会发生。

任何时候数据安全性都是很重要的,所以如果 master 使用复制功能的同时未配置持久化,那么自动重启进程这项应该被禁用

参考:《Redis设计与实现》、redis replication

作者:TurboSnail
链接:https://juejin.cn/post/6844903943764443149
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/231967.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode—290.单词规律【简单】

2023每日刷题&#xff08;五十一&#xff09; Leetcode—290.单词规律 实现代码 class Solution { public:bool wordPattern(string pattern, string s) {unordered_map<char, string> m1;unordered_map<string, char> m2;stringstream stro(s);string tmp;for(a…

配电室无人值守改造

配电室无人值守改造是通过运用先进的技术和设备&#xff0c;将传统的需要人工值守的配电室改造成可以远程监控和管理的智能化配电室&#xff0c;从而实现无人值守。这种改造可以提高配电室的安全性、可靠性和效率&#xff0c;降低运维成本。 建立智能监控系统&#xff1a;通过安…

luceda ipkiss教程 44:在PyCharm 中设置Template text

通过设置Template text&#xff0c;可以提升写代码的速度和版图设计效率。 设置了Template text&#xff0c;在PyCharm 命令窗口输入i3后按enter建&#xff0c;就可以快速输入 from ipkiss3 import all as i3 这一段代码&#xff0c;使用起来也是非常方便&#xff1a; 设置过程…

Ubuntu上svn基本使用(gitee提交下载)

目录 环境准备 1. 获取代码到本地 直接获取 获取代码时加入用户名密码 指定版本更新 2. 提交代码 3. 展示代码列表 4. 添加代码文件(目录) 5. 删除gitee仓库中的文件 参考文档链接 环境准备 当前操作系统为Ubuntu22.04LTS gitee 创建仓库时 需要打开svn的支持 sudo…

电脑软件:TileIconifier开始菜单美化工具介绍

目录 一、 软件介绍 二、软件功能 三、使用说明 四、软件下载 一、 软件介绍 TileIconifier是一款简单易用的win10开始菜单美化软件&#xff0c;该程序具备了简单直观的操作界面&#xff0c;打开软件后&#xff0c;您可以在快捷方式列表下选择要美化的快捷方式&#xff0c;…

Billu_b0x

信息收集 #正常进行信息收集就好Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-18 22:07 CST Nmap scan report for 192.168.182.142 (192.168.182.142) Host is up (0.00073s latency).PORT STATE SERVICE 22/tcp open ssh 80/tcp open http | http-cookie-flags:…

哈希表的几种实现方式与比较

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 哈希表概述 哈希表&#xff08;Hash Table&#xff09;是一种常用的数据结构&#xff0c;用于实现键值对的映射关系。它通过哈希函数将键映射到一个特定的索引位置&#xf…

解决 Cannot read properties of undefined (reading ‘getUserMedia‘) 报错

[TOC](解决 Cannot read properties of undefined (reading ‘getUserMedia’) 报错) 0. 背景 使用浏览器输入语音时&#xff0c;浏览器的控制台里面有下面错误信息。 Cannot read properties of undefined (reading getUserMedia)1. 解决方法 在浏览器中访问 chrome://fla…

在AWS Lambda上部署EC2编译的FFmpeg工具——自定义层的方案

大纲 1 确定Lambda运行时环境1.1 Lambda系统、镜像、内核版本1.2 运行时1.2.1 Python1.2.2 Java 2 环境准备2.1 创建EC2实例 3 编译FFmpeg3.1 连接EC2 4 编译5 上传S3存储桶5.1 创建S3桶5.2 创建IAM策略5.3 创建IAM角色5.4 EC2关联角色5.5 修改桶策略5.6 打包并上传 6 创建Lamb…

SAP 标准成本估算基础知识 - 了解成本设置流程 - Part1

原文地址&#xff1a;Basics of SAP Standard Cost estimate- Understanding the flow of cost settings-Part 1 SCN 中有很多关于标准成本计算的论坛问题解答和内容 注意 - 这是初学者的基本指南&#xff0c;用于了解成本估算及其背后的各种设置。 本文件旨在解释标准成本…

Mybatis环境搭建

1、开发环境 IDE&#xff1a;IntelliJ IDEA 2022.2.1 (Ultimate Edition) 构建工具&#xff1a;maven 3.6.1 MySQL版本&#xff1a;MySQL 5.7 MyBatis版本&#xff1a;MyBatis 3.5.14 2、工程创建 创建一个Maven工程giser-java-mybatis-demo 基础依赖如下&#xff1a; &…

关于Stm32CubeIDE的printf打印浮点数的问题的一点看法

由于重新巩固一下18B20 的使用&#xff0c;重新琢磨了一下&#xff0c;本想printf温度这个浮点数的&#xff0c;后面发现有问题&#xff0c;打印后程序卡死了。 还发现了一个问题&#xff0c;打开这个打印浮点数功能&#xff0c;程序会大很多&#xff1a; 打开的方法是菜单》Pr…

HBuilderX

HBuilderX.3.98.2023112510 HBuilderX-高效极客技巧 HBuilderX的项目结构&#xff1a; vue-cli的项目结构&#xff1a; HBuilderX的项目要脱离该工具用vue-cli启动的话&#xff0c;要把源代码拷贝到src里面&#xff0c;把项目结构修改后才可以启动完成。【知道我为什么很讨厌维…

2023最新八股文前端面试题

第一章 Css 1.说一下CSS的盒模型。 在HTML页面中的所有元素都可以看成是一个盒子盒子的组成:内容content、内边距padding、边框border、外边距margin盒模型的类型: 标准盒模型 margin border padding content IE盒模型 margin content(border padding) 控制盒模型的模式…

Python Reflex框架全攻略:手把手教你打造个性化全栈应用!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Reflex框架是一款专注于全栈开发的现代 JavaScript 框架&#xff0c;它强调响应式编程和简化复杂性&#xff0c;为开发者提供了构建动态且高效的全栈应用的工具。 Reflex框架是为了解决传统全栈开发中的一些挑战…

关于linux开机自启动

1、系统启动流程 2、 init、 inittab、 init.d、 rcx.d /etc/inittab是Linux系统中的一个配置文件&#xff0c;用于定义系统的运行级别和相应的操作。其语法格式如下&#xff1a; 标签&#xff1a;运行级别&#xff1a;操作&#xff1a;进程 label:runlevel:action:process下面…

C# 任务并行类库Parallel调用示例

写在前面 Task Parallel Library 是微软.NET框架基础类库&#xff08;BCL&#xff09;中的一个&#xff0c;主要目的是为了简化并行编程&#xff0c;可以实现在不同的处理器上并行处理不同任务&#xff0c;以提升运行效率。Parallel常用的方法有For/ForEach/Invoke三个静态方法…

Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.

报错&#xff1a; OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performan…

SpringSecurity6 | 自定义认证规则

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

docker-compose安装教程

1.确认docker-compose是否安装 docker-compose -v如上图所示表示未安装&#xff0c;需要安装。 如上图所示表示已经安装&#xff0c;不需要再安装&#xff0c;如果觉得版本低想升级&#xff0c;也可以继续安装。 2.离线安装 下载docker-compose安装包&#xff0c;上传到服务…