在当今数字化时代,数据量呈爆炸式增长,对于应用程序而言,保障数据的高可用性和高性能变得至关重要。在众多的解决方案中,Redis凭借其丰富的特性脱颖而出,而主从复制便是其中一项关键技术。
想象一下,一个大型电商平台在促销活动期间,海量的用户请求如潮水般涌来。此时,单一的Redis实例很难应对如此巨大的流量压力,而且一旦出现故障,整个系统可能会陷入瘫痪。Redis主从复制机制就如同为系统搭建了一道坚固的防线,通过复制主节点的数据到多个从节点,不仅提升了系统的读取性能,还增强了数据的可靠性。
Redis主从复制是如何巧妙地实现数据同步的?在实际应用中又该如何进行配置和管理?不同节点之间的角色是如何协同工作的?接下来,就让我们一同深入Redis主从复制的世界,揭开其神秘的面纱,探寻其中的奥秘。
一、详解Redis主从复制
1. 主从复制的基本概念
主从复制就是将主节点(master)的数据复制到从节点(slave),让多个节点承载用户的请求:
主从复制具备以下几个特点:
- 数据冗余:主节点的数据都会同步到从节点上,所以多个节点都会有相同数据,从而实现数据冗余。
- 故障恢复:主节点出现故障后,从节点可以继续承载用户的请求,做到服务上的冗余。
- 负载均衡:主从复制机制实现主节点接收用户写请求,从节点承载用户读请求,对于读多写少的场景,这种机制可以大大提高redis的并发量。
- 高负载:主从复制+哨兵机制可以实现高负载,这点后文会介绍到。
2. 主从复制使用示例
首先我们先来介绍一下一主二从,即搭建一个主节点和两个从节点,主节点负责写入请求,从节点同步数据对外提供数据读服务:
创建3个redis配置文件,以笔者为例,名字分别为redis6379.conf、redis6380.conf、redis6381.conf,同时我们将6379这个端口号的redis作为主节点,配置内容如下:
从节点以6380,配置如下:
分别启动这几个redis:
完成配置后,我们就可以开始测试了,首先对清空主节点数据,并设置一些值进去:
我们看看从节点是否存在这个key值,可以发现这个值确实存在。
再使用命令看看6380,发现其角色也确实是从节点:
3. 演示主从复制运行时异常
从节点挂掉,在启动,数据不会丢失,照样是主节点的从节点,这个点我们也可以拿个例子来展示一下,首先我们可以将从节点挂掉:
清空数据主节点设置一些新数据,再次启动从节点,可以发现它还是从节点的角色:
主节点挂了,从节点仍然是从节点,主节点恢复后仍然是主节点。
这个例子,首先我们也是需要将主节点挂掉:
完成后再次将主节点启动,然后进行操作,发现角色仍然是master,而且进行各种set操作80这个从节点也会同步复制。
4. 主从复制下的薪火相传
如果大量主节点配合大量从节点,会导致主节点会导致数据同步时长增加,所以我们可以将部分从节点挂到某部分从节点下面,以此类推,作为从节点的从节点:
以笔者本次示例为例,我们将81作为80的从节点:
再次查看80节点,可以看到slave0:ip=127.0.0.1,port=6381,state=online,offset=810,lag=1,由此可知从节点的从节点配置完成:
5. 反客为主
对着从节点键入下面在这段命令,即直接让从节点停止复制并直接晋升为主节点:
二、、主从复制进阶知识点
1. 主从复制的原理
主从复制有两种模式,我就先来说说全量复制吧,如下图,整体步骤为:
- 从节点向主节点发送同步请求,因为不知道主库的runID,并且不知道同步的偏移量是多少,所以参数分别为? -1,同步请求的指令为psync
- 主库执行bgsave指令生成rdb指令,将数据发送给从库,从库为了保证数据一致性,会将数据清空,然后加载rdb文件,完成数据同步。在此期间,主库收到的新数据都会被存入replication buffer中。
- 主库会将replication buffer发送给从库,完成最新数据的同步。
从 Redis 2.8 开始,因为网络断开导致数据同步中断的情况,会采用增量复制的方式完成数据补充。
需要了解的是,当主从同步过程中因为网络等问题发生中断,repl_backlog_buffer会保存两者之间差异的数据,如果从库长时间没有恢复,很可能出现该环形缓冲区数据被覆盖进而出现增量复制失败,只能通过全量复制的方式实现数据同步。
需要一个概念replication buffer,这个缓冲区用于存放用户写入的新指令,完成全量复制之后的数据都是通过这个buffer的数据传输实现数据增量同步。
2. 主服务器不进行持久化复制存在什么问题
设想下面这样一个场景,主节点没有使用RDB持久化,数据没有持久化到磁盘,在此期间主节点挂掉又立刻恢复了,此时主节点所有数据都丢失了,从节点很可能会因此清空原本数据进而导致数据丢失。
3. 为什么主从复制使用RDB而不是AOF
RDB是二进制且压缩过的文件,传输速度以及加载速度都远远快速AOF。且AOF存的都是指令非常耗费磁盘空间,加载时都是重放每个写命令,非常耗时。需要注意的是RDB是按照时间间隔进行持久化,对于数据不敏感的场景我们还是建议使用RDB。
4. 什么是无磁盘复制模式
数据同步不经过主进程以及硬盘,直接创建一个新进程dump RDB数据到从节点。对于磁盘性能较差的服务器可以使用这种方式。配置参数为:
5. 为什么会有从库的从库设计
由上可知,主库执行数据同步时,需要执行如下步骤:
- 生成rdb文件。
- 传输数据给从库。
为避免主库因为频繁为大量从库做同步导致性能下降,于是我们才引入从库的从库这一设计方案分散同步压力:
6. 读写分离及其中的问题
大抵需要考虑以下这些问题:
- 延迟与不一致问题:如果对数据一致性容忍度较低,网络延迟导致数据不一致问题只能通过提高网络带宽,或者通知应用不在通过该节点获取数据
- 数据过期问题,从节点很可能在某一时刻某些过期数据被读取到了,这就会给用户造成很诡异的场景。
- 故障切换问题
7. 如果在网络断开期间,repl_backlog_buffer 环形缓冲区写满之后,是进行全量还是增量复制
针对这个问题我们必须要了解repl_backlog_buffer是什么,它是redis主从同步时master的一个环形缓冲区,在master节点同步指令给slave时,这个缓冲区也会临时缓冲这部分数据以保证slave断线重连后的数据补偿,针对该问题,我们需要分两种情况说:
- 若主库的repl_backlog_buffer的slave_repl_offset已经被覆盖,那么同步就需要全量复制了
- 从库会通过psync命令把自己记录的slave_repl_offset发给主库,主库根据复制进度决定是增量复制还是全量复制。
8. 1主2从redis架构如何抗住1000w的qps
结合redis官方给出压测报告来看,redis的qps基本在8w~15w这个区间,所以如果需要应对1000w的qps我们就需要考虑水平复制数据并拓展,按照压测的情况并结合只需要抗住qps的需求,我们可以得出第一个方案——通过薪火相传的架构来保证数据同步。
按照单机10w的qps来换算,我们可以通过100个redis节点搭建一个薪火相传的架构抗住并发压力:
当然考虑到100个节点的成本可能不切实际,所以我们也可以采取另一套相对折中的方案,结合服务器资源部署一套redis主从架构+哨兵架构保证高可用,然后各个服务模块基于本地内存到redis中同步热点数据,让应用直接对外提供缓存数据检索,由此节约了资源成本还间接的减小的接口响应的RT: