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

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

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

我们可以通过 slaveof <host> <port></port></host>命令,或者通过配置 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></masterport></masterip>命令

这里我使用3台虚拟机来搭建一下,主服务器的ip为 192.168.249.20,两个从服务器的ip分别为 192.168.249.21192.168.249.21,端口号都为 6379,具体的配置如下

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

&#x8BBE;&#x7F6E;&#x4E3A;&#x540E;&#x53F0;&#x8FD0;&#x884C;
daemonize yes
&#x4FDD;&#x5B58;pid&#x7684;&#x6587;&#x4EF6;&#xFF0C;&#x5982;&#x679C;&#x662F;&#x5728;&#x4E00;&#x53F0;&#x673A;&#x5668;&#x642D;&#x5EFA;&#x4E3B;&#x4ECE;&#xFF0C;&#x9700;&#x8981;&#x533A;&#x5206;&#x4E00;&#x4E0B;
pidfile /var/run/redis_6379.pid
&#x7ED1;&#x5B9A;&#x7684;&#x4E3B;&#x673A;&#x5730;&#x5740;&#xFF0C;&#x8FD9;&#x91CC;&#x6CE8;&#x91CA;&#x6389;&#xFF0C;&#x5F00;&#x653E;ip&#x8FDE;&#x63A5;
#bind 127.0.0.1
&#x6307;&#x5B9A;&#x65E5;&#x5FD7;&#x6587;&#x4EF6;
logfile "6379.log"
<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span>

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

replicaof <masterip> <masterport>
replicaof 192.168.249.20 6379
<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span></masterport></masterip>

配置好 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
<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span>

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

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"
<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span>

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

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

<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span>

如果我们需要slave对master的复制进行验证,可以在master中配置 requirepass <password></password>选项设置密码
那么需要在从服务器中使用该密码,可以使用命令 config set masterauth <password></password>,或者在配置文件中设置 masterauth <password></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
...

<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span>

数据同步

在主从服务器建立连接确认各自身份之后,就开始数据同步,从服务器向主服务器发送 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></offset></runid>发送记录旧的master的 runid(replication ID)和偏移量 offset,这样master能够只发送slave所缺的增量部分。但是如果master的复制积压缓存区没有足够的命令记录,或者slave传的 runid(replication ID)不对,就会进行 完整重同步,即slave会获得一个完整的数据集副本

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

命令传播

当完成数据同步之后,主从服务器的数据暂时达到一致状态,当主服务器执行了客户端的写命令之后,主从的数据便不再一致。为了能够使主从服务器的数据保持一致性,主服务器会对从服务器执行命令传播操作,即每执行一个写命令就会向从服务器发送同样的写命令

在命令传播阶段,从服务器会默认以每秒一次的频率向主服务器发送 心跳检测

REPLCONF ACK <replication_offset>
<span class="copy-code-btn">&#x590D;&#x5236;&#x4EE3;&#x7801;</span></replication_offset>

其中 replication_offset是当前从服务器的复制偏移量,该命令的作用有三个

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

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

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

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

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

Original: https://www.cnblogs.com/wangmo/p/15192886.html
Author: wangmo
Title: Redis主从复制的配置和实现原理

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529166/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • LVS负载均衡

    LVS负载均衡 LVS负载均衡 一、LVS是什么 二、LVS的作用 三、lvs的三种工作模式 1.基于NAT的LVS模式负载均衡 2.基于TUN模式的LVS负载均衡 3.LVS(D…

    Linux 2023年6月6日
    089
  • 我叫Mongo,收了「查询基础篇」,值得你拥有

    这是mongo第二篇「查询基础篇」,后续会连续更新6篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流。 …

    Linux 2023年6月14日
    0114
  • Ansible简介

    Ansible 是一种常用的自动运维化工具,基于 python 开发,分布式,无需客户端,轻量级,配置语言采用 YAML。 模块化:调用特定的模块,完成特殊的任务。 2.Param…

    Linux 2023年6月6日
    092
  • boot issue

    Q:生产过程中不小心把 boot文件删除了 ,或者升级kenerl时发现版本不兼容,需要回退,此时没有快照备份情况如何操作? A:boot 主要文件是内核和grub引导文件 1.进…

    Linux 2023年6月6日
    0109
  • Kubenertes-实战入门

    实战入门 Namespace Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现 多套环境的资源隔离。 默认情况下,kubernetes集群中…

    Linux 2023年6月13日
    089
  • nginx-openresty通过location调用显示upstream信息

    背景 有时候查看nginx的upstream配置得知配置后端的ip地址和端口,但从日志里面发现提示后端不存在,想知道nginx的内存里面是否存在upstream的加载信息,判断后端…

    Linux 2023年6月6日
    0121
  • Centos7 找回root密码

    在开机界面,按”e”进入编辑界面 按”e”进图下图界面后,找到开头为”linux16″行,在行后面加入 &#…

    Linux 2023年5月27日
    0139
  • oracle 怎么查看用户对应的表空间

    oracle 怎么查看用户对应的表空间? 查询用户: 查看数据库里面所有用户,前提是你是有 dba 权限的帐号,如 sys,system: select * from dba_us…

    Linux 2023年6月6日
    0105
  • apparmor 源码分析

    这里不对apparmor做介绍,记录一下源码分析过程。 static int __init apparmor_init(void) -> security_add_hooks…

    Linux 2023年6月13日
    073
  • docker-compose安装redis-sentinel集群(1主+2副+2哨兵)

    前提:本试验环境已经提前安装了docker和docker-compose 说明:本次部署是单机伪集群,想要部署真正的集群,需要将秒个主件拆分到各个机器上去部署,只修改ip地址 1、…

    Linux 2023年5月28日
    090
  • LVM 逻辑卷管理 Logical Volume Management

    管理磁盘、使用磁盘的一种方式的称呼 优势: 1、在不影响数据的情况下, 扩容、缩容 2、支持快照功能, 方便数据备份 LVM工作流程: 磁盘/分区 —> pv(物…

    Linux 2023年6月7日
    0119
  • mit 6.824 lab2A ,raft 领导人选举实现(lab2D中有关于此处大量代码修改,找出了很多错误)

    lab2 说明: https://pdos.csail.mit.edu/6.824/labs/lab-raft.html 参考博客: https://zhuanlan.zhihu….

    Linux 2023年6月7日
    0127
  • ​探秘 Web 水印技术

    Web 水印技术在信息安全和版权保护等领域有着广泛的应用,对防止信息泄露或知识产品被侵犯有重要意义。水印根据可见性可分为可见水印和不可见水印(盲水印),本文将分别予以介绍,带你探秘…

    Linux 2023年6月8日
    0114
  • 保罗·艾伦的故事

    上周,保罗·艾伦逝世。《财新周刊》约我写一篇纪念文章,发表在他们杂志上面 一些个人新闻:最近,我了解到我在2009年与之抗争的非霍奇金淋巴瘤已经复发。我已经开始治疗,我的医生很乐观…

    Linux 2023年6月14日
    0106
  • JVM学习 类加载子系统

    JVM 哔哩哔哩 尚硅谷视频 宋红康老师 Java代码执行流程 简图 详细图 1、类加载子系统 类加载器子系统的作用 类加载器子系统负责从文件系统或者网络中加载Class文件,cl…

    Linux 2023年6月7日
    097
  • [ Calibre ] 利用 Calibre LVS 检查网表正确性的最小 rule

    利用 Calibre LVS 检查网表正确性的最小 rule https://www.cnblogs.com/yeungchie/ 顶层验证前先检查网表,再跑完整流程。 check…

    Linux 2023年6月7日
    089
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球