暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Redis主从复制技术:理论基础、运行逻辑与应用场景

83

写在文章开头

在当今数字化时代,数据量呈爆炸式增长,对于应用程序而言,保障数据的高可用性和高性能变得至关重要。在众多的解决方案中,Redis
凭借其丰富的特性脱颖而出,而主从复制便是其中一项关键技术。

想象一下,一个大型电商平台在促销活动期间,海量的用户请求如潮水般涌来。此时,单一的Redis
实例很难应对如此巨大的流量压力,而且一旦出现故障,整个系统可能会陷入瘫痪。Redis
主从复制机制就如同为系统搭建了一道坚固的防线,通过复制主节点的数据到多个从节点,不仅提升了系统的读取性能,还增强了数据的可靠性。

Redis主从复制是如何巧妙地实现数据同步的?在实际应用中又该如何进行配置和管理?不同节点之间的角色是如何协同工作的?接下来,就让我们一同深入Redis主从复制的世界,揭开其神秘的面纱,探寻其中的奥秘。

Hi,我是 sharkChili ,是个不断在硬核技术上作死的技术人,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili 。


同时也非常欢迎你star我的开源项目mini-redis:https://github.com/shark-ctrl/mini-redis

因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注  “加群”  即可和笔者和笔者的朋友们进行深入交流。

详解redis主从复制

主从复制的基本概念

主从复制就是将主节点(master)
的数据复制到从节点(slave)
,让多个节点承载用户的请求:

主从复制具备以下几个特点:

1. 数据冗余:主节点的数据都会同步到从节点上,所以多个节点都会有相同数据,从而实现数据冗余。
 2. 故障恢复:主节点出现故障后,从节点可以继续承载用户的请求,做到服务上的冗余。
 3. 负载均衡:主从复制机制实现主节点接收用户写请求,从节点承载用户读请求,对于读多写少的场景,这种机制可以大大提高redis的并发量。
 4. 高负载:主从复制+哨兵机制可以实现高负载,这点后文会介绍到。

主从复制使用示例

首先我们先来介绍一下一主二从,即搭建一个主节点和两个从节点,主节点负责写入请求,从节点同步数据对外提供数据读服务:

创建3个redis
配置文件,以笔者为例,名字分别为redis6379.conf
redis6380.conf
redis6381.conf
,同时我们将6379
这个端口号的redis
作为主节点,配置内容如下:

# 引入redis基本配置,注意这个配置只支持RDB
include root/redis/redis.conf
pidfile var/run/redis_6379.pid
port 6379
# 设置RDB文件名
dbfilename dump6379.rdb

从节点以6380,配置如下

# 引入redis基本配置,注意这个配置只支持RDB
include root/redis/redis.conf
pidfile var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
# 作为6379的主节点
slaveof 127.0.0.1 6379

分别启动这几个redis

 redis-server root/redis/conf/redis6379.conf
 redis-server root/redis/conf/redis6380.conf
 redis-server root/redis/conf/redis6381.conf

完成配置后,我们就可以开始测试了,首先对清空主节点数据,并设置一些值进去

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set master_key value
OK
127.0.0.1:6379>

我们看看从节点是否存在这个key值,可以发现这个值确实存在。

# 可以看到主节点的key来了
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli -p 6380
127.0.0.1:6380> keys *
1) "master_key"
127.0.0.1:6380>



再使用命令看看6380,发现其角色也确实是从节点


127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
.... 略

演示主从复制运行时异常

  1. 从节点挂掉,在启动,数据不会丢失,照样是主节点的从节点,这个点我们也可以拿个例子来展示一下,首先我们可以将从节点挂掉:
# 强制挂掉从节点
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli -p 6380
127.0.0.1:6380> SHUTDOWN
not connected>

清空数据主节点设置一些新数据,再次启动从节点,可以发现它还是从节点的角色

# 启动 发现数据都在,并且角色也是slave
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-server root/redis/conf/redis6380.conf
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
.....略


  1. 主节点挂了,从节点仍然是从节点,主节点恢复后仍然是主节点。

这个例子,首先我们也是需要将主节点挂掉:

# 强制挂掉主节点
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli
127.0.0.1:6379> SHUTDOWN
not connected>

完成后再次将主节点启动,然后进行操作,发现角色仍然是master
,而且进行各种set操作80这个从节点也会同步复制。


# 再次启动主节点,发现key都在并且角色仍然是master,设置一个k2值
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-server root/redis/conf/redis6379.conf
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli
127.0.0.1:6379> set key2 v2
OK
127.0.0.1:6379>

# 从节点仍然可以收到,说明主节点仍然是6379
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli -p 6380
127.0.0.1:6380> keys *
1) "key2"
2) "master_key"
127.0.0.1:6380>


主从复制下的解薪火相传

如果大量主节点配合大量从节点,会导致主节点会导致数据同步时长增加,所以我们可以将部分从节点挂到某部分从节点下面,以此类推,作为从节点的从节点:

以笔者本次示例为例,我们将81作为80的从节点

# 为了方便,笔者使用命令的形式,读者也可以使用conf文件配置
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6381>

再次查看80节点,可以看到slave0:ip=127.0.0.1,port=6381,state=online,offset=810,lag=1
,由此可知从节点的从节点配置完成

[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
# 6381变为它的从节点
slave0:ip=127.0.0.1,port=6381,state=online,offset=810,lag=1


反客为主

对着从节点键入下面在这段命令,即直接让从节点停止复制并直接晋升为主节点:

slaveof  no one

主从复制进阶知识点

主从复制的原理

主从复制有两种模式,我就先来说说全量复制吧,如下图,整体步骤为:

  1. 从节点向主节点发送同步请求,因为不知道主库的runID
    ,并且不知道同步的偏移量是多少,所以参数分别为? -1
    ,同步请求的指令为psync
  2. 主库执行bgsave
    指令生成rdb
    指令,将数据发送给从库,从库为了保证数据一致性,会将数据清空,然后加载rdb
    文件,完成数据同步。在此期间,主库收到的新数据都会被存入replication buffer
    中。
  3. 主库会将replication buffer
    发送给从库,完成最新数据的同步。

从 Redis 2.8 开始,因为网络断开导致数据同步中断的情况,会采用增量复制的方式完成数据补充。

需要了解的是,当主从同步过程中因为网络等问题发生中断,repl_backlog_buffer
会保存两者之间差异的数据,如果从库长时间没有恢复,很可能出现该环形缓冲区数据被覆盖进而出现增量复制失败,只能通过全量复制的方式实现数据同步。

需要一个概念replication buffer
,这个缓冲区用于存放用户写入的新指令,完成全量复制之后的数据都是通过这个buffer
的数据传输实现数据增量同步。

当然如果对主从复制源码感兴趣的读者,可以阅读笔者这篇文章:

以从节点的角度看看Redis主从复制的实现:https://mp.weixin.qq.com/s/YmyhDfpWkco5rVX7xoF6aQ

主服务器不进行持久化复制存在什么问题

设想下面这样一个场景,主节点没有使用RDB持久化,数据没有持久化到磁盘,在此期间主节点挂掉又立刻恢复了,此时主节点所有数据都丢失了,从节点很可能会因此清空原本数据进而导致数据丢失。

为什么主从复制使用RDB而不是AOF

RDB
是二进制且压缩过的文件,传输速度以及加载速度都远远快速AOF。且AOF存的都是指令非常耗费磁盘空间,加载时都是重放每个写命令,非常耗时。需要注意的是RDB是按照时间间隔进行持久化,对于数据不敏感的场景我们还是建议使用RDB。

什么是无磁盘复制模式

数据同步不经过主进程以及硬盘,直接创建一个新进程dump RDB
数据到从节点。对于磁盘性能较差的服务器可以使用这种方式。配置参数为:

repl-diskless-sync no # 决定是否开启无磁盘复制模式
repl-diskless-sync-delay 5 # 决定同步的时间间隔

为什么会有从库的从库设计

由上可知,主库执行数据同步时,需要执行如下步骤:

  1. 生成rdb文件。
  2. 传输数据给从库。

为避免主库因为频繁为大量从库做同步导致性能下降,于是我们才引入从库的从库这一设计方案分散同步压力:

在这里插入图片描述

读写分离及其中的问题

大抵需要考虑以下这些问题:

  1. 延迟与不一致问题:如果对数据一致性容忍度较低,网络延迟导致数据不一致问题只能通过提高网络带宽,或者通知应用不在通过该节点获取数据
  2. 数据过期问题,从节点很可能在某一时刻某些过期数据被读取到了,这就会给用户造成很诡异的场景。
  3. 故障切换问题

如果在网络断开期间,repl_backlog_buffer 环形缓冲区写满之后,是进行全量还是增量复制

针对这个问题我们必须要了解repl_backlog_buffer
是什么,它是redis
主从同步时master
的一个环形缓冲区,在master节点同步指令给slave时,这个缓冲区也会临时缓冲这部分数据以保证slave断线重连后的数据补偿,针对该问题,我们需要分两种情况说:

  1. 若主库的repl_backlog_buffer
    slave_repl_offset
    已经被覆盖,那么同步就需要全量复制了
  2. 从库会通过psync
    命令把自己记录的slave_repl_offset
    发给主库,主库根据复制进度决定是增量复制还是全量复制。

1主2从redis架构如何抗住1000w的qps

结合redis官方给出压测报告来看,redis的qps基本在8w~15w这个区间,所以如果需要应对1000w的qps我们就需要考虑水平复制数据并拓展,按照压测的情况并结合只需要抗住qps的需求,我们可以得出第一个方案——通过薪火相传的架构来保证数据同步。

按照单机10w的qps来换算,我们可以通过100个redis节点搭建一个薪火相传的架构抗住并发压力:

在这里插入图片描述

当然考虑到100个节点的成本可能不切实际,所以我们也可以采取另一套相对折中的方案,结合服务器资源部署一套redis主从架构+哨兵架构保证高可用,然后各个服务模块基于本地内存到redis中同步热点数据,让应用直接对外提供缓存数据检索,由此节约了资源成本还间接的减小的接口响应的RT:

在这里插入图片描述

小结

我是 sharkchili ,CSDN Java 领域博客专家mini-redis的作者,我想写一些有意思的东西,希望对你有帮助,如果你想实时收到我写的硬核的文章也欢迎你关注我的公众号: 写代码的SharkChili 。


同时也非常欢迎你star我的开源项目mini-redis:https://github.com/shark-ctrl/mini-redis

因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注  “加群”  即可和笔者和笔者的朋友们进行深入交流。

参考

Redis进阶 - 高可用:主从复制详解:https://www.pdai.tech/md/db/nosql-redis/db-redis-x-copy.html

Redis进阶 - 高可用:哨兵机制(Redis Sentinel)详解:https://www.pdai.tech/md/db/nosql-redis/db-redis-x-sentinel.html

redis哨兵模式以及选举策略:https://juejin.cn/post/7042090753006239774#:~:text=哨兵模式:主要是,前主节点的从节点

redis-sentinel.conf配置项说明如下:https://www.cnblogs.com/xuliangxing/p/7149322.html


文章转载自写代码的SharkChili,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论