写点什么

🕋【Redis 干货领域】彻底走进主从架构的世界(入门篇)

发布于: 2021 年 05 月 13 日
🕋【Redis干货领域】彻底走进主从架构的世界(入门篇)

📕 系列背景 📕


本片文章属于,彻底走进主从架构的世界三部曲中的入门篇此外之后还有进阶篇强化篇,前用循序渐进的方式去学习和介绍。

📕 人生箴言 📕


自由只存在于束缚之中,没有堤岸,哪里来江河? —— 金斯伯格

📕 前提摘要 📕


面试不少公司都很重视高并发高可用高性能的技术,特别是一线互联网公司:分布式JVM

Spring 源码分析微服务等知识点几乎已是面试的必考题。今天我们就来将一个横跨高并发、高可用、高性能这三大特性集于一身的互联网高并发的“万金油”它叫做 Redis


对于 Redis 而言其本身的性能吞吐率是毋庸置疑的,但是在高可用以及高负载能力,一般会在其主从模式的分布式架构层面进行实现和提升。接下来我们就针对于它的主从模式进行分析,其中会有许多问题需要考虑,这里写了一些关于 Redis 在主从模型下的一些问题分析和总结。

📕 主从模式 📕


「主从复制」可以说是整个 Redis 高可用实现的基石。


  • 架构集群、分片功能实现的基础;

  • 高可用的一种策略。例如,解决单机并发问题、数据安全性等等问题。

💻 问题场景 💻


  • 负载超过了 Redis 单机能够处理的上限,还有一种情况 Redis 也无法保证自身的高可用性。

  • 即便 Redis 能够扛住所有流量,但是如果这个 Redis 进程所在的机器挂了呢?

此时所有的请求会直接调转枪口,大量的流量会瞬间把你的 DB 打挂(所谓缓存雪崩的最糟糕的情况)

💻 六大要素 💻


  • 数据的保障:RDB 和 AOF 再也不怕宕机丢失数据了,这里特别要注意的就是 AOF。

  • 产生的原因Redis 单节点存在单点故障问题,为了解决单点问题

  • 解决的方案一般都需要对 Redis 配置 slave 节点,然后使用哨兵(Sentinel)来监听主节点存活状态,如果主节点挂掉,从节点能继续提供缓存功能

  • 主从的特性Redis 从节点仅提供操作,主节点提供操作。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率

  • 数据的同步:Redis 数据的跨主机备份, Master 节点将自己的 RDB 文件同步给 Slave 节点,将数据冗余一份复制到 Slave Redis 服务器。

  • 高可用总结Redis 主从配置结合哨兵模式能解决单点故障问题,提高 Redis 高可用性(avaliable)

💻 基本特性 💻


  • 单一性前者称为主节点 (master),后者称为从节点 (slave)RDB 文件数据复制是单向的,只能由主节点到从节点

  • 唯一性:每台 Redis 服务器都是主节点;且一个主节点可以有多个从节点 (或没有从节点)但一个从节点只能有一个主节点

💻 总体架构 💻


【主从同步】中,将节点的角色划分为 master(主库)slave(从库),形成「一主多从」。slave 负责操作,而 master 负责操作,形成一个读写分离的架构,这样就能够承载更多的业务请求。

多数的业务场景下,Redis 的「读操作」都要多于「写操作」,所以当读请求量特别大的时候,我们可以通过增加 slave 节点来使 Redis 扛住更多的流量


💻 核心流程 💻


Redis(Slave)中我们可以通过 slaveof/replicaof 命令让一个 Redis(Slave)实例去复制另外一台 Redis(Master)的状态。被复制的 Redis 实例就是 Master 节点,而执行 slaveof/replicaof 命令的机器就是 Slave 节点,Slave 会按照某种策略从 Master 同步数据。Redis 的主从复制分为两个步骤,分别是「同步操作」「命令传播」


  • 「同步操作」用于将 master 节点内存状态复制给 slave 节点。

  • 「命令传播」在同步时,客户端又执行了一些「写」操作改变了服务器的状态,此时 master 节点的状态与同步操作执行的时候不一致了,所以需要命令传播来使 master slave 状态重新一致(将单独生成的 writer buffer 内的数据信息传递同步给 slave)。


注意:replicaof 是新版本的命令,旧版本是 slaveof 命令,如果你使用的是 Redis 5.0.0 之前的版本,那么请使用 SLAVEOF 命令代替本章中的 REPLICAOF 命令,并使用 slaveof 配置选项代替本章中的 replicaof 配置选项


同步的大致的流程如下:


  1. slave 节点向 master 节点发送 sync 命令。

  2. master 收到 sync 命令之后会执行 bgsave 命令,Redis fork 出一个子进程在后台生成 RDB 文件,同时将同步过程中的写命令记录到 Writer Buffer(缓冲区)中。

  3. RDB 文件生成后,master 会把 RDB 文件发送给 slaveslave 服务器接收到 RDB 文件会将其载入内存。

  4. 然后 master 将记录在 Writer Buffer缓冲区)的所有写命令发送给 slaveslave 对这些命令进行「重放」,将其数据库的状态更新至和 master 一致


通过图再来了解一下:

以上就是最基本的 Redis【主从同步】架构的基本流程和原理。

🖊如果当从库(Slave)出现的问题🖊


上面讨论的是 slave 第一次连接到 master,会执行「全量复制」,而针对上面这种情况,Redis 新老版本处理方式不一样。这就是接下来要将的新版本优化的功能「断点续传」(psync)了。

  • Redis2.8 之前,当主从完成了同步之后,slave 如果断线重连,向 master 发送 sync 命令,master 会将全量的数据再次同给 slave。(过于庞大的重放数据量以及延迟的恢复时间+重放给 CPU 和 IO 带来的性能损耗),此外 Redis 本来都是串行顺序化处理数据信息,就是大部分数据都是有序的,再次全量同步显得没有必要


  • Redis2.8 之后,为了解决这个问题,便使用了 psync 命令来代替 sync。简单来说 psync 命令就是将 slave 断线期间 master 接收到的写命令全部发送给 slaveslave 重放之后状态便与 master 一致了。


psync 的实现原理


psync 的实现依赖于主从双方共同维护的 offset 偏移量。


基于 offset只需要简单的比对就知道当前主从的状态是否是一致的了,然后基于 offset,将对应偏移量所对应的指令传播给 slave 重放即可,所以即使同步的时候 slave 挂掉了,基于 offset,也能达到断点续传的效果。


主库向从库同步数据


  • master slave 进行「命令传播」,传播多少个字节的数据,就将自己的 offset 加上传播的字节数

  • slave 每次收到多少字节的数据,也会同样的更新自己的 offset

🖊当主库(Master)出现的问题🖊


  • Redis 的确也有想到,实际上除了 offset 之外,slave 断线重连之后还会带上一个 master 的实例的 runid,每个服务实例都有自己的唯一的 runid,只要 Redis 服务重启,其 runid 就会发生改变。

  • master 收到这个 runid 之后会判断是否与自己当前的 runid 一致,如果一致说明断线之前还是与自己建立的连接,而如果不一致就说明 slave 断线期间,master 也发生了宕机,此时就需要将数据「全量同步」给 slave 了

需要通过这个 offset 去拿到真正需要的数据也就是指令,Redis 是通过「复制积压缓冲区」来实现的。

复制积压缓冲区的默认大小为 1M,Redis 在进行「命令传播」时,除了将写命令发送给 slave,还会将命令写到「复制积压缓冲区」内,并和当前的 offset 关联起来。这样一来就能够通过 offset 获取到对应的指令了。


但是由于缓冲区的大小有限,如果 slave 的断线时间太久,复制积压缓冲区内早些时候的指令就已经被新的指令覆盖掉了,此处可以理解为一个队列,早些时候入队的元素已经被出队了。

由于没有相对应的 offset 了,也就无法获取指令数据,此时 Redis 就会进行「全量同步」。当然,如果 offset 还存在于复制积压缓冲区中,则按照对应的 offset 进行「部分同步」

基于以上的全量、增量的主从复制,能够在 master 出现故障的情况下,进行主从的切换,保证服务的正常运行。除此之外还能解决异常情况下数据丢失的问题。基于读写分离的策略还能够提高整个 Redis 服务的并发量。

📕 案例操作 📕

环境演示中,有一台主机,启动了两个 Redis 示例。


💻 服务启动配置 💻


该方式通过在启动 Redis 服务时,通过命令行参数,进行启动主从复制功能。该方式的弊端是不能实现配置持久化,当服务停掉之后,启动服务时,需要添加相同的命令参数。


  1. master 服务器事先在 redis.confg 增加 requirepass 项。


requirepass 6379


  1. 启动从服务器


redis-server --port 6380 --replicaof/--slaveof 192.168.2.102 6379

💻 命令行配置 💻


该方式通过使用 redis-cli 进入操作行界面,进行配置。该方式的弊端是不能实现配置持久化,当服务停掉之后,启动服务需要执行同样的命令。


  1. master 服务器执行


127.0.0.1:6379> config set requirepass 6379

OK


  1. slave 服务器执行


127.0.0.1:6380> replicaof 192.168.2.102 6379

OK

127.0.0.1:6380> config set masterauth 6379

OK


💻 配置文件配置 💻


该方式是通过 redis.conf 配置文件进行设置,能够实现配置的持久化,是一种推荐使用的方式。


  1. 配置主服务器,redis.config


requirepass 6379


  1. 配置从服务器,redis.config


masterauth 6379

replicaof 192.168.2.102 6379

💻 配置说明💻

  • masterauth:设置 redis.config 连接密码,如果设置了该值。其他客户端在连接该服务器时,需要添加密码才可以访问。

  • requirepass:设置主服务器的连接密码,和 1 中 masterauth 一致。

  • replicaof:从服务器连接到主服务器的 IP 地址+端口号。

📕 效果测试📕

1.主服务器添加数据。


2.从服务器获取数据。




未完待续...... 后续会有同系列的下一篇(进阶篇),对于更高层次能力的开发者


用户头像

我们始于迷惘,终于更高水平的迷惘。 2020.03.25 加入

🏆 【酷爱计算机技术、醉心开发编程、喜爱健身运动、热衷悬疑推理的”极客狂人“】 🏅 【Java技术领域,MySQL技术领域,APM全链路追踪技术及微服务、分布式方向的技术体系等】 🤝未来我们希望可以共同进步🤝

评论

发布
暂无评论
🕋【Redis干货领域】彻底走进主从架构的世界(入门篇)