当前位置: 首页 > news >正文

7.Redis 主从复制(重在理解)

0.简介理解

Redis 主从复制是 Redis 提供的一种数据备份和读写分离方案,通过该机制可以实现将主节点(Master)的数据同步到从节点(Slave),从而提高系统的可用性和读取性能。

在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他服务器,满⾜故障恢
复和负载均衡等需求。Redis 也是如此,它为我们提供了复制的功能,实现了相同数据的多个 Redis 副本。复制功能是⾼可⽤ Redis 的基础,哨兵和集群都是在复制的基础上构建的。
就好比:
如果同学⽐较少, 那么⼀个⽼师既可以进⾏授课, 也可以进⾏答疑; 但是随着学⽣多了, ⼀个⽼师也就
应付不过来了. 就需要配⼏个助教⽼师, 助教⽼师从授课⽼师这⾥获取知识, 协助授课⽼师答疑

从节点得听主节点的(从节点的数据要跟随主节点变化;从节点的数据要和主节点保持一致)

本来,在主节点上保存一堆数据,引入从节点后,就是要把主节点上的数据复制出来,放到从节点中。后续,要是主节点这里对于数据有任何修改,都会把这样的修改给同步到从节点上。

如果我修改了从节点上的数据,是否要把从节点上的数据往主节点上同步呢??

Redis 主从模式中,从节点上的数据,不允许被修改!只能读取数据!

1.配置

配置 redis 主从结构,首先需要启动多个 redis 服务器;正常来说,每个 redis 服务器程序,应该在一个单独的主机上(这才是分布式)

建立复制

参与复制的 Redis 实例划分为主节点(master)和从节点(slave)。每个从结点只能有⼀个主节点,⽽⼀个主节点可以同时具有多个从结点。复制的数据流是单向的,只能由主节点到从节点。配置复制的⽅式有以下三种:
1.在配置⽂件中加⼊ slaveof {masterHost} {masterPort} 随 Redis 启动⽣效
2.在 redis-server 启动命令时加⼊ --slaveof {masterHost} {masterPort} ⽣效
3.直接使⽤ redis 命令:slaveof {masterHost} {masterPort} ⽣效。
(以下命令了解即可,现用现查)
1.我们将 redis.conf 配置⽂件复制⼀份 redis-slave.conf,并且修改其 daemonize 为 yes。# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes2.默认启动的 redis 作为主 Redis,重新通过命令⾏启动⼀个 Redis 实例作为从 Redis:# ubuntu
redis-server /etc/redis/redis-slave.conf --port 6380 --slaveof 127.0.0.1 6379注意: 修改配置主要是修改从机的配置. 主机配置不变.3.通过 netstat -nlpt 确保两个 Redis 均已正确启动[root@host ~]# netstat -nlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name 
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 49264/redis-server 
tcp 0 0 127.0.0.1:6380 0.0.0.0:* LISTEN 272418/redis-server4.通过 redis-cli 可以连接主 Redis 实例,通过 redis-cli -p 6380 连接从 Redis。并且观察复制关系。
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"127.0.0.1:6380> get hello
"world"
Redis 主从节点复制过程

可以通过 info replication 命令查看复制相关状态。
1.主节点 6379 复制状态信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=100,lag=0
master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:100
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:100

2.从节点 6380 复制状态信息

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:170
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:170
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:170

断开复制

slaveof 命令不但可以建⽴复制,还可以在从节点执⾏ slaveof no one 来断开与主节点复制关系。
例如在 6380 节点上执⾏ slaveof no one 来断开复制。
 
断开复制主要流程:
1.断开与从节点复制关系
2.从节点晋升为主节点
从节点断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化
通过 slaveof 命令还可以实现切主操作,将当前从节点的数据源切换到另⼀个主节点。执⾏
slaveof {newMasterIp} {newMasterPort} 命令即可。
切主操作主要流程:
1)断开与旧主节点复制关系。
2)与新主节点建⽴复制关系。
3)删除从节点当前所有数据。
4)从新主节点进⾏复制操作。

安全性

对于数据⽐较重要的节点,主节点会通过设置 requirepass 参数进⾏密码验证,这时所有的客⼾
端访问必须使⽤ auth 命令实⾏校验。从节点与主节点的复制连接是通过⼀个特殊标识的客⼾端来完成,因此需要配置从节点的masterauth 参数与主节点密码保持⼀致,这样从节点才可以正确地连接到主节点并发起复制流程。

*只读

默认情况下,从节点使⽤ slave-read-only=yes 配置为只读模式。由于复制只能从主节点到从节
点,对于从节点的任何修改主节点都⽆法感知,修改从节点会造成主从数据不⼀致。所以建议线上不要修改从节点的只读模式

传输延迟

主从节点⼀般部署在不同机器上,复制时的⽹络延迟就成为需要考虑的问题,Redis 为我们提供
了 repl-disable-tcp-nodelay 参数⽤于控制是否关闭 TCP_NODELAY,默认为 no,即开启 tcp
nodelay 功能,说明如下:
1.当关闭时,主节点产⽣的命令数据⽆论⼤⼩都会及时地发送给从节点,这样主从之间延迟会变⼩,但增加了⽹络带宽的消耗。适⽤于主从之间的⽹络环境良好的场景,如同机房部署。
2.当开启时,主节点会合并较⼩的 TCP 数据包从⽽节省带宽。默认发送时间间隔取决于 Linux 的内核,⼀般默认为 40 毫秒。这种配置节省了带宽但增⼤主从之间的延迟。适⽤于主从⽹络环境复杂的场景,如跨机房部署。

2.拓扑

Redis 的复制拓扑结构可以⽀持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:⼀主⼀
从、⼀主多从、树状主从结构。

一主一从结构

⼀主⼀从结构是最简单的复制拓扑结构,⽤于主节点出现宕机时从节点提供故障转移⽀持,如图
所⽰。当应⽤写命令并发量较⾼且需要持久化时,可以只在从节点上开启 AOF,这样既可以保证数据安全性同时也避免了持久化对主节点的性能⼲扰。但需要注意的是,当主节点关闭持久化功能时,如果主节点宕机要避免⾃动重启操作。

一主多从结构

⼀主多从结构(星形结构)使得应⽤端可以利⽤多个从节点实现读写分离,如图所⽰。对于
读⽐重较⼤的场景,可以把读命令负载均衡到不同的从节点上来分担压⼒。同时⼀些耗时的读命令可以指定⼀台专⻔的从节点执⾏,避免破坏整体的稳定性。对于写并发量较高的场景,多个从节点会导致主节点写命令的多次发送从而加重主节点的负载。

树形主从结构

树形主从结构(分层结构)使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主
节点继续向下层复制。通过引⼊复制中间层,可以有效降低住系欸按负载和需要传送给从节点的数据量,数据写⼊节点 A 之后会同步给 B 和 C 节点,B 节点进⼀步把数据同步给 D 和 E 节点。当主节点需要挂载等多个从节点时为了避免对主节点的性能⼲扰,可以采⽤这种拓扑结构。

3.原理

主从节点建立复制流程图

1.保存主节点(master)的信息

开始配置主从同步关系之后,从节点只保存主节点的地址信息,此时建⽴复制流程还没有开始,
在从节点 6380 执⾏ info replication 可以看到如下信息:
master_host: 127.0.0.1
master_port: 6379
master_link_status: down
从统计信息可以看出,主节点的 ip 和 port 被保存下来,但是主节点的连接状态
(master_link_status)是下线状态。
2.从节点(slave)内部通过每秒运⾏的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与主节点建⽴基于 TCP 的⽹络连接。如果从节点⽆法建⽴连接,定时任务会⽆限重试直到连接成功或者⽤⼾停⽌主从复制。
3.发送 ping 命令。连接建⽴成功之后,从节点通过 ping 命令确认主节点在应⽤层上是⼯作良好的。如果 ping 命令的结果 pong 回复超时,从节点会断开 TCP 连接,等待定时任务下次重新建⽴连接。
4.权限验证。如果主节点设置了 requirepass 参数,则需要密码验证,从节点通过配置 masterauth
参数来设置密码。如果验证失败,则从节点的复制将会停⽌
5.同步数据集。对于⾸次建⽴复制的场景,主节点会把当前持有的所有数据全部发送给从节点,这步操作基本是耗时最⻓的,所以⼜划分称两种情况:全量同步和部分同步,后面重点介绍。
6.命令持续复制。当从节点复制了主节点的所有数据之后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执⾏修改命令,保证主从数据的⼀致性。

1.数据同步 psync

Redis 使⽤ psync 命令完成主从数据同步,同步过程分为:全量复制和部分复制。

1.全量复制:⼀般⽤于初次复制场景,Redis 早期⽀持的复制功能只有全量复制,它会把主节点全部数据⼀次性发送给从节点,当数据量较⼤时,会对主从节点和⽹络造成很⼤的开销。

2.部分复制:⽤于处理在主从复制中因⽹络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。因为补发的数据远⼩于全量数据,可以有效避免全量复制的过⾼开销。
PSYNC 的语法格式
psync replicationid offset如果 replicationid 设为 ? 并且 offset 设为 -1 此时就是在尝试进⾏全量复制.
如果 replicationid offset 设为了具体的数值, 则是尝试进⾏部分复制.

1. replicationid / replid(复制id)

主节点的复制 id. 主节点重新启动, 或者从节点晋级成主节点, 都会⽣成⼀个 replicationid. (同⼀个节点, 每次重启, ⽣成的 replicationid 也会变化).
从节点在和主节点建⽴连接之后, 就会获取到主节点的 replicationid.
通过 info replication 即可看到 replicationid
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:1da596acecf5a34b4b2aae45bd35be785691ae69
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

关于 master_replid 和 master_replid2
每个节点需要记录两组 master_replid . 这个设定解决的问题场景是这样的:
⽐如当前有两个节点 A 和 B, A 为 master, B 为 slave.
此时 B 就会记录 A 的 master_replid.
如果⽹络出现抖动, B 以为 A 挂了, B ⾃⼰就会成为主节点. 于是 B 给⾃⼰分配了新的 master_replid.
此时就会使⽤ master_replid2 来保存之前 A 的 master_replid.
1.后续如果⽹络恢复了, B 就可以根据 master_replid2 找回之前的主节点.
2.后续如果⽹络没有恢复, B 就按照新的 master_replid ⾃成⼀派, 继续处理后续的数据.

run id 是每个节点都不相同的

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

run id 主要是用在支撑实现 redis 哨兵这个功能(和主从复制没啥关系)

2. offset(偏移量)

不是从节点索要哪部分,主节点就一定给哪部分!主节点会自主判定,看当前是否方便给部分数据;不方便就只能给全量了。

参与复制的主从节点都会维护⾃⾝复制偏移量。主节点(master)在处理完写⼊命令后,会把命令的字节⻓度做累加记录,统计信息在 info replication 中的 master_repl_offset 指标中。
127.0.0.1:6379> info replication
# Replication
role:master
...
master_repl_offset:1055130
从节点(slave)每秒钟上报⾃⾝的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量,统计指标如下:
127.0.0.1:6379> info replication
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=1055214,lag=1
...
从节点在接受到主节点发送的命令后,也会累加记录⾃⾝的偏移量。统计信息在 info replication 中的slave_repl_offset 指标中:
127.0.0.1:6380> info replication
# Replication
role:slave
...
slave_repl_offset:1055214
通过对⽐主从节点的复制偏移量,可以判断主从节点数据是否⼀致。
复制偏移量维护
这个偏移量, 就相当于 "学习进度".
⽐如⽼师这边准备了 10 个课件的内容. 助教要想给同学答疑, 也就需要学习完这 10 个课件的内容. 这个偏移量就是当前助教学到了第⼏个课件了

 psync 运行流程

1.从节点发送 psync 命令给主节点,replid 和 offset 的默认值分别是?和 -1.

2.主节点根据 psync 参数和自身数据情况决定响应结果:

   (1)如果回复 +fullresync replid offset,则从节点需要进行全量复制流程

   (2)如果回复 +contineu,从节点进行部分复制流程

   (3)如果回复 -err,说明 Redis 主节点版本过低,不支持 psync 命令。从节点可以使用 sync 命令进行全量复制。

• psync ⼀般不需要⼿动执⾏. Redis 会在主从复制模式下⾃动调⽤执⾏.
• sync 会阻塞 redis server 处理其他请求. psync 则不会

3.全量复制

全量复制是 Redis 最早⽀持的复制⽅式,也是主从第⼀次建⽴复制时必须经历的阶段。
全量复制流程

1.从节点发送 psync 命令给主节点进⾏数据同步,由于是第⼀次进⾏复制,从节点没有主节点的运⾏ ID 和复制偏移量,所以发送 psync ? -1。

2.主节点根据命令,解析出要进⾏全量复制,回复 +FULLRESYNC 响应。

3.从节点接收主节点的运⾏信息进⾏保存

4.主节点执⾏ bgsave 进⾏ RDB ⽂件的持久化(rdb 是二进制文件,比较节省空间;不能使用已有的 rdb 文件,而必须要重新生成一下;已有的 rdb 文件可能会和当前最新的数据存在较大差异

5.从节点发送 RDB ⽂件给从节点,从节点保存 RDB 数据到本地硬盘

6.主节点将从⽣成 RDB 到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点保存完 RDB ⽂件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照 rdb 的⼆进制格式追加写⼊到收到的 rdb ⽂件中. 保持主从⼀致性。

7.从节点清空⾃⾝原有旧数据

8.从节点加载 RDB ⽂件得到与主节点⼀致的数据

9.如果从节点加载 RDB 完成之后,并且开启了 AOF 持久化功能,它会进⾏ bgrewrite 操作,得到最近的 AOF ⽂件。

通过分析全量复制的所有流程,我们会发现全量复制是⼀件⾼成本的操作:主节点 bgsave 的时间,RDB 在⽹络传输的时间,从节点清空旧数据的时间,从节点加载 RDB 的时间等。所以⼀般应该尽可能避免对已经有⼤量数据集的 Redis 进⾏全量复制。

4.部分复制

部分复制主要是 Redis 针对全量复制的过⾼开销做出的⼀种优化措施,使⽤ psync replicationId
offset 命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,如果主节点的复制积压缓冲区存在数据则直接发送给从节点,这样就可以保持主从节点复制的⼀致性。补发的这部分数据⼀般远远⼩于全量数据,所以开销很⼩。

部分复制过程

1)当主从节点之间出现⽹络中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并终端复制连接。
2)主从连接中断期间主节点依然响应命令,但这些复制命令都因⽹络中断⽆法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
3)当主从节点⽹络恢复后,从节点再次连上主节点。
4)从节点将之前保存的 replicationId(replicationld 其实就是在描述“数据的来源” offset 描述“数据的复制进度”) 和 复制偏移量作为 psync 的参数发送给主节点,请求进⾏部分复制。

5)主节点接到 psync 请求后,进⾏必要的验证。随后根据 offset 去复制积压缓冲区查找合适的数据,并响应 +CONTINUE 给从节点。
6)主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性。
(相当于:如果某个课件传输失败了, 助教可以单独要这个缺失的课件)

复制积压缓冲区

复制积压缓冲区是保存在主节点上的⼀个固定⻓度的队列,默认⼤⼩为 1MB,当主节点有连接的从节点(slave)时被创建,这时主节点(master)响应写命令时,不但会把命令发送给从节点,还会写⼊复制积压缓冲区。
由于缓冲区本质上是先进先出的定⻓队列,所以能实现保存最近已复制数据的功能,⽤于部分复制和复制命令丢失的数据补救。复制缓冲区相关统计信息可以通过主节点的 info replication 中:
127.0.0.1:6379> info replication
# Replication
role:master
...
repl_backlog_active:1 // 开启复制缓冲区
repl_backlog_size:1048576 // 缓冲区最⼤⻓度
repl_backlog_first_byte_offset:7479 // 起始偏移量,计算当前缓冲区可⽤范围
repl_backlog_histlen:1048576 // 已保存数据的有效⻓度根据统计指标,可算出复制积压缓冲区内的可⽤偏移量范围:[repl_backlog_first_byte_offset,
repl_backlog_first_byte_offset + repl_backlog_histlen]。这个相当于⼀个基于数组实现的环形队列. 上述区间中的值就是 "数组下标"

5.实时复制

主从节点在建⽴复制连接后,主节点会把⾃⼰收到的 修改操作 , 通过 tcp 长连接的方式, 源源不断的传输给从节点. 从节点就会根据这些请求来同时修改⾃⾝的数据. 从⽽保持和主节点数据的⼀致性.
另外, 这样的⻓连接, 需要通过心跳包的⽅式来维护连接状态. (这⾥的⼼跳是指应⽤层⾃⼰实现的⼼跳,⽽不是 TCP ⾃带的⼼跳).
1)主从节点彼此都有⼼跳检测机制,各⾃模拟成对⽅的客⼾端进⾏通信。
2)主节点默认每隔 10 秒对从节点发送 ping 命令,判断从节点的存活性和连接状态。
3)从节点默认每隔 1 秒向主节点发送 replconf ack {offset} 命令,给主节点上报⾃⾝当前的复制偏移量。
如果主节点发现从节点通信延迟超过 repl-timeout 配置的值(默认 60 秒),则判定从节点下线,断开复制客⼾端连接。从节点恢复连接后,⼼跳机制继续进⾏。

6.小结:

主从复制解决的问题:
单点问题.
1. 单个 redis 节点, 可⽤性不⾼.
2. 单个 redis 节点, 性能有限
主从复制的特点:
1. Redis 通过复制功能实现主节点的多个副本。
2. 主节点⽤来写, 从节点⽤来读. 这样做可以降低主节点的访问压⼒.
3. 复制⽀持多种拓扑结构,可以在适当的场景选择合适的拓扑结构。
4. 复制分为全量复制, 部分复制和实时复制。
5. 主从节点之间通过⼼跳机制保证主从节点通信正常和数据⼀致性。
主从复制配置的过程:
1. 主节点配置不需要改动.
2. 从节点在配置⽂件中加⼊ slaveof 主节点ip 主节点端⼝ 的形式即可
主从复制的缺点:
1. 从机多了, 复制数据的延时⾮常明显.
2. 主机挂了, 从机不会升级成主机. 只能通过⼈⼯⼲预的⽅式恢复.

附录:

主从复制,最大的问题还是在主节点上。主节点挂了,从节点就迷茫了~~ 虽然能够提供读操作,但是从节点不能自动的升级成主节点~ 不能替换原有主节点对应的角色。此时,就需要程序员/运维手工恢复主节点~~(非常繁琐的)
Redis 哨兵:自动的对挂了的主节点进行替换


文章转载自:

http://qAW6GQOz.bhkLt.cn
http://86FA4rJv.bhkLt.cn
http://w4CoPrCh.bhkLt.cn
http://GbMiCHR9.bhkLt.cn
http://XQYWsgKQ.bhkLt.cn
http://BOrEpb4o.bhkLt.cn
http://4Z01Hkxj.bhkLt.cn
http://7eGQtPS5.bhkLt.cn
http://fgv4FvVa.bhkLt.cn
http://W1qQywxp.bhkLt.cn
http://ZpAizv0M.bhkLt.cn
http://KrS1zPLt.bhkLt.cn
http://QDTIYBMl.bhkLt.cn
http://whNKz84K.bhkLt.cn
http://GgVXPAjI.bhkLt.cn
http://2PXtuYcR.bhkLt.cn
http://j5BZz0Sw.bhkLt.cn
http://fS0tSMbr.bhkLt.cn
http://EewMBWrB.bhkLt.cn
http://GMl3o3DW.bhkLt.cn
http://HpDnx0ZI.bhkLt.cn
http://4o9J0DWL.bhkLt.cn
http://KOiEQfwQ.bhkLt.cn
http://Ul08NRoE.bhkLt.cn
http://ZDgMN4dZ.bhkLt.cn
http://e8XYFaf3.bhkLt.cn
http://UoZDzsfa.bhkLt.cn
http://wH3KUti9.bhkLt.cn
http://lPDGHCQw.bhkLt.cn
http://KAmLe7vl.bhkLt.cn
http://www.dtcms.com/a/385665.html

相关文章:

  • 从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现
  • 从0开始做一个完整项目 -- 软件跨平台编译打包全流程
  • comfyUI实战——使用openArt的工作流
  • linux 之 struct attribute
  • 强化学习PPO-分类任务
  • 决策树模型全解析:从分类到回归(基于鸢尾花数据集)
  • shell脚本部署lamp
  • c语言6:static 关键字控制变量/函数的 “生命周期” 与 “可见性”
  • MySQL 数据库对象与视图:从概念到实战,掌握虚拟表的核心价值
  • 【VPX361】基于3U VPX总线架构的XCZU47DR射频收发子模块
  • 消火栓设备工程量计算 -【图形识别】秒计量
  • 基于LangGraph的深度研究智能体技术解析
  • 【哈希表】1512. 好数对的数目|2506. 统计相似字符串对的数目
  • Java--多线程基础知识(2)
  • 活泼解析pthread_join函数:多线程世界的等待仪式
  • 机器视觉的智能手表后盖激光打标应用
  • 第七章 来日方长(2025.8学习总结)
  • 卡方检验公式中分母 (a+b)(c+d)(a+c)(b+d)的本质
  • IT基础知识——数据库
  • 电子衍射模拟:基于GPU加速的MATLAB/Julia实现
  • yum只安装指定软件库中的包
  • CentOS网卡接口配置文件详细指南
  • 计算机视觉 - 对比学习(上)MoCo + SimCLR + SWaV
  • SQL模糊查询完全指南
  • Qit_计网笔记
  • 新发布、却被遗忘的旗舰级编程模型、grok-code-fast-1
  • Python爬虫的反爬接口:应对策略与实战指南
  • Linux dma-buf核心函数实现分析
  • vue3 实现前端生成水印效果
  • 手机上有哪些比较好用的待办事项提醒工具