Redis系列(三):深入解读Redis主从同步机制

首发博客地址

https://blog.zysicyj.top/

Redis高可靠靠什么保证?

为什么要提这个呢,因为Redis主从库目的呢其实就是为了实现高可靠。上篇文章中我们说过Redis的AOF、RDB日志其实就是为了减少数据丢失,这是高可靠的一部分。

这篇文章呢,我们聊聊Redis实现高可靠的另一方面:尽量减少服务中断 。这里Redis是怎么做的呢?Redis的做法是增加副本冗余,将一份数据同时保存在多个实例上。这样某个实例挂掉并不影响其它实例提供对外服务,保证我们的业务正常运行。

Redis有哪些手段提高高可用呢?

  1. 数据持久化:Redis 支持多种数据持久化方式,包括快照(snapshotting)和日志(append-only file)。快照会定期将内存中的数据保存到磁盘文件,而日志会记录每次写操作,以便在重启时进行恢复。这些持久化方式可以确保即使服务器意外关闭,数据也不会丢失。
  2. 主从复制:Redis 支持主从复制机制,其中一个 Redis 实例作为主节点,负责写操作,而其他实例作为从节点,负责复制主节点的数据。这种方式可以实现数据的备份和负载均衡,从而提高可靠性和性能。
  3. Sentinel 哨兵:Redis Sentinel 是一个监控和自动故障恢复系统,可以监控 Redis 实例的健康状态并在主节点故障时自动进行故障切换。它可以确保系统在主节点发生故障时能够自动切换到备用的从节点,保证服务的连续性。
  4. Cluster 集群:Redis Cluster 是一种分布式系统,将数据分布在多个节点上,以提高可用性和扩展性。每个节点都持有部分数据,并且可以容忍部分节点的故障。当节点发生故障时,集群可以自动重新分配数据,确保服务的可靠性和高可用性。

如何保证副本数据一致?

首先我们要知道,Redis提供了主从库模式 ,以保证副本一致,主从库之间采用的是读写分离的方式。
Redis主从库和读写分离

Redis中的读写分离基本原理和步骤

Redis 读写分离是一种架构设计,将读操作和写操作分别路由到不同的 Redis 节点上,以提高性能和扩展性。在 Redis 读写分离中,通常会有一个主节点负责写操作,多个从节点负责读操作。

  1. 主节点(写节点)
    • 主节点负责处理所有的写操作,包括写入、更新和删除等。
    • 写操作在主节点上执行,然后主节点将写操作的结果同步到所有从节点。
  2. 从节点(读节点)
    • 从节点负责处理读操作,例如获取数据、查询等。
    • 从节点从主节点复制数据,并在本地保存一份与主节点相同的数据副本。
  3. 读写分离的实现
    • 客户端根据需要的操作类型将请求分发到主节点或从节点。
    • 读操作可以通过负载均衡策略,将请求分发到不同的从节点,实现负载分担。
    • 写操作仍然发送给主节点,确保数据的一致性和完整性。

需要注意的是,Redis 读写分离并不是完全的数据实时同步,因为从节点的数据可能会有一定的延迟。另外,读写分离适用于大多数场景下的负载均衡和性能优化,但在一些特定情况下,例如有序集合等复杂数据结构的查询,仍然需要访问主节点。

实现 Redis 读写分离需要正确配置主从节点的关系,以及在客户端中使用合适的策略进行读写操作的路由。同时,需要注意主节点和从节点之间的数据同步和故障处理,以确保系统的稳定性和可靠性。

Redis主从库第一次同步是如何实现的?

  1. 建立连接: 从服务器会向主服务器发送 PSYNC 命令,表示要进行同步。主服务器收到 PSYNC 命令后,会创建一个专门用于复制的后台线程(replication thread),并等待从服务器的连接。
  2. 全量复制(第一次同步): 当从服务器连接到主服务器后,主服务器会将自己的数据发送给从服务器。这个过程叫做全量复制,主服务器会遍历自己的数据集,将所有数据发送给从服务器。
    • 主服务器会在一个 RDB 文件中保存当前数据集的快照,然后将这个 RDB 文件发送给从服务器。从服务器接收到 RDB 文件后,会加载这个文件,将自己的数据集替换成主服务器的数据集。
    • 在 RDB 文件传输的过程中,主服务器会将在传输期间的写操作记录下来,称为命令传播(command propagation)。这样一来,主服务器就能够在发送完 RDB 文件后,将期间的写操作重新发送给从服务器,以保证从服务器的数据集与主服务器保持一致。
  3. 增量复制: 在完成全量复制后,主从服务器之间会保持一个 TCP 连接,主服务器会将自己的写操作发送给从服务器,从服务器执行这些写操作,从而保持数据一致性。增量复制的数据同步是异步的,但通过记录写操作,主从服务器之间的数据最终会达到一致状态。

需要注意的是,在第一次全量复制的过程中,可能会有一些网络故障、主从服务器负载等情况影响同步。为了提高稳定性和安全性,Redis 提供了一些配置选项和机制,如持久化、复制偏移量、主服务器验证等,来确保主从复制的正常进行。

PSYNC命令

当 Redis 主从复制中的从服务器(Slave)需要与主服务器(Master)进行数据同步时,可以使用 PSYNC(Partial SYNC)命令。PSYNC 命令在 Redis 2.8 版本引入,用于提高数据同步的效率和可靠性。

PSYNC 命令包括两种模式:完全同步(Full Sync)和部分同步(Partial Sync)。

  1. 完全同步(Full Sync): 完全同步在以下情况下发生:

    • 从服务器初次连接主服务器时。
    • 从服务器需要进行初次同步,或者复制偏移量与主服务器的偏移量差距较大时。
    • 主服务器没有保存 RDB 快照文件,所以无法进行部分同步。

    完全同步的过程如下:

    • 从服务器向主服务器发送一条 PSYNC 命令,并附带上自己的复制积压缓冲区的偏移量(offset)和 replid(复制 ID)。
    • 主服务器使用 bgsave命令,生成RDB文件,接着将文件发给从库。
    • 从库接收到RDB文件后,会先清空当前数据库,然后加载RDB文件。
  2. 部分同步(Partial Sync): 部分同步在以下情况下发生:

    • 从服务器已经复制了一部分数据,并且复制偏移量与主服务器的偏移量差距较小时。

    部分同步的过程如下:

    • 主库将后续所有 写操作记录到内存中的replication buffer中
    • 从服务器向主服务器发送一条 PSYNC 命令,并附带上自己的复制积压缓冲区的偏移量和 replid。
    • 主库将所有保存的写操作发送给从库,具体来说,就是当RDB发送完成后,就会把此时replication buffer中的修改发给从库,从库再重新执行这些操作。这样一来,主从库就实现同步了

PSYNC 命令的目标是在保证数据一致性的前提下,尽可能地减少数据同步所需的数据传输量,从而提高复制效率。完全同步和部分同步的选择取决于从服务器与主服务器之间的复制状态和数据差距。

主库的烦恼

这里我们能分析得到主库做全量同步时的两个耗时操作:

  1. 生成RDB文件
  2. 传输RDB文件

这里设想一个场景,如果是一主多从的架构,那么主节点就要生成多份RDB并传输给从节点,很显然,这种操作是非常耗时的。这里主要占用两块资源

  1. 通过fork子进程生成RDB快照会 阻塞主线程处理请求
  2. 传输RDB文件会占用 网络带宽

那么有什么方法可以解决这些问题呢? 这里呀,我们就引入了"主-从-从"架构,很容易理解,就是主库只需要同步一份给某从库A,其他从库从从库A同步数据。

如何理解 主-从-从 架构?

主从(Master-Slave)架构是一种常见的数据库复制和数据备份方案。在这种架构中,存在一个主数据库(主服务器)和一个或多个从数据库(从服务器),主数据库负责处理写操作和读操作,从数据库负责复制主数据库的数据,以提供读取操作和备份。

主从架构的工作方式如下:

  1. 主数据库(主服务器):
    • 主数据库是系统的主要数据库,负责处理所有的写操作(数据的插入、更新、删除)和部分读操作。
    • 当主数据库接收到写操作时,会将这些写操作记录到自己的日志文件(例如 MySQL 的二进制日志)中,并发送给从数据库。
    • 主数据库也会保存一个复制积压缓冲区(replication backlog buffer),其中存储了一部分的写操作数据,用于满足部分同步和断线重连的需求。
  2. 从数据库(从服务器):
    • 从数据库是主数据库的复制副本,负责从主数据库复制数据以供读取操作和备份。
    • 从数据库会连接到主数据库,并发送复制请求(如 PSYNC 命令)以获取主数据库的数据更新。
    • 从数据库会持续地复制主数据库的写操作,将写操作应用到自己的数据副本中,以保持与主数据库的数据一致性。
    • 从数据库可以处理读取请求,从而减轻主数据库的读取压力。

主从架构的优势:

  • 负载均衡: 通过将读操作分发给从数据库,可以分担主数据库的读取压力,提高整体系统的吞吐量。
  • 高可用性: 当主数据库出现故障时,可以将其中一个从数据库提升为新的主数据库,从而实现快速故障切换。
  • 数据备份: 从数据库可以作为主数据库的数据备份,用于恢复数据和灾难恢复。
  • 数据分析: 从数据库可以用于读取操作,以进行数据分析、报表生成等工作,而不影响主数据库的性能。

需要注意的是,主从架构并不是完全实时的,因为从数据库需要时间来同步主数据库的数据更新。因此,在考虑使用主从架构时,需要权衡数据一致性和性能之间的需求。

如何配置主从从架构呢

  1. 安装和配置主服务器(Master):

    • 安装Redis主服务器并确保主服务器正常运行。

    • 在主服务器的配置文件(redis.conf)中开启持久化(通常使用RDB快照或AOF日志)和监听端口,确保配置项如下:

      复制代码
      port 6379
      save 900 1
      appendonly yes  # 如果使用AOF日志
    • 如果需要对外提供访问,确保防火墙或网络设置允许访问主服务器的6379端口。

  2. 安装和配置第一个从服务器(Slave1):

    • 在从服务器1上安装Redis数据库。

    • 在从服务器1的配置文件中配置主从关系。在配置文件中添加类似如下的内容,其中 masterauth是主服务器的密码, master是主服务器的IP和端口:

      复制代码
      slaveof master_ip master_port
      masterauth your_master_password
    • 重启从服务器1使配置生效。

  3. 安装和配置第二个从服务器(Slave2):

    • 在从服务器2上安装Redis数据库。
    • 在从服务器2的配置文件中配置主从关系,与从服务器1相似。确保配置项不冲突。
    • 重启从服务器2使配置生效。
  4. 重启主服务器:

    • 在主服务器上查看主服务器的信息,如IP和端口。通常使用以下命令:

      复制代码
      INFO server
  5. 测试主从从架构:

    • 在主服务器上进行写操作,如插入、更新或删除数据。
    • 查看从服务器1和从服务器2是否同步了主服务器的数据。

需要注意的是,Redis的主从从架构在部署和配置上与主从架构类似,只是需要在从服务器上再次配置主从关系。另外,Redis还可以配置更多高可用性的功能,如哨兵(Sentinel)和集群(Cluster),以实现更强大的架构。具体配置细节可能会因版本和需求而有所不同,建议参考官方文档或相关资源进行详细了解和配置。

主从库间网络断了怎么办?

在 Redis 2.8 之前,如果主从库在命令传播时出现了网络闪断,那么,从库就会和主库重新进行一次全量复制,开销非常大。

2.8之后呢是支持增量同步的,那么Redis是怎么实现增量同步的呢? 当Redis主从库之间的网络断开后,网络恢复时从库需要进行增量同步,以获取在网络断开期间主库中的更新数据。Redis实现增量同步的方式是通过Redis复制机制,具体流程如下:

  1. 保存主服务器的数据: 主服务器会将更新的数据写入内存,并在内存中保存一份副本。同时,主服务器会将更新的数据写入AOF(Append-Only File)日志文件,以便在断电或宕机情况下能够进行数据恢复。
  2. 记录复制偏移量: 在主服务器的复制过程中,主服务器会记录一个复制偏移量(replication offset),表示从服务器在主服务器中的数据位置。这个偏移量会随着数据的更新而递增。
  3. 网络恢复: 当网络恢复时,从服务器会尝试连接主服务器并请求进行复制。
  4. 发送SYNC命令: 从服务器会发送SYNC命令给主服务器。如果是初次连接复制,从服务器发送的SYNC命令中不包含任何参数。如果是增量同步,从服务器会发送带有偏移量参数的SYNC命令。
  5. 全量复制或部分复制: 根据情况,主服务器会执行全量复制或部分复制:
    • 全量复制(初次连接): 如果是初次连接复制,主服务器会执行全量复制。它会创建一个RDB快照(数据库快照),将数据库中的数据快照发送给从服务器。这样从服务器就能够拥有主服务器的完整数据集。
    • 部分复制(增量同步): 如果是增量同步,主服务器会从记录的偏移量处开始,将从偏移量后的所有更新数据发送给从服务器。这样从服务器就能够获取在断开网络期间主服务器的更新数据。
  6. 复制数据传输: 主服务器会将全量数据或增量数据通过网络传输给从服务器。从服务器会接收并处理这些数据,更新自己的数据集。
  7. 复制过程继续: 一旦复制数据传输完成,从服务器会持续地与主服务器保持连接,接收来自主服务器的增量更新。这样,主从库之间的数据保持同步。

需要注意的是,当网络断开时间较长或断开期间数据更新较大时,增量同步可能会导致从服务器落后于主服务器。在网络恢复后,从服务器需要足够的时间来接收和处理更新数据,以保持与主服务器的数据同步。

一般的排查流程

  1. 检查网络连接问题: 首先,确保网络连接问题的确是造成主从库通信中断的原因。检查网络配置、防火墙规则、路由等设置,确保主从库之间可以互相访问。
  2. 重新连接网络: 如果网络问题是暂时的,你可以尝试恢复网络连接,让主从库之间恢复通信。
  3. 检查主从状态: 在主从库网络连接恢复后,使用INFO replication命令检查主从库的同步状态。确保主库已将数据同步到从库。
  4. 手动重新同步: 如果主从库之间的网络断开时间较长,可以考虑进行手动重新同步:
    • 在从库上,使用 SLAVEOF NO ONE命令解除从库状态。
    • 在从库上,删除持久化文件(RDB文件或AOF文件)。
    • 在从库上,执行 SLAVEOF master_ip master_port命令,将其重新设置为主库的从库。
    • 在主库上,执行 SLAVEOF NO ONE命令解除主库状态。
    • 在主库上,执行 SLAVEOF slave_ip slave_port命令,将其重新设置为从库的主库。
  5. 手动复制数据: 如果网络断开时间较长且重新同步不可行,你可能需要手动复制数据。在主库上导出数据,并在从库上导入数据。
  6. 备份和恢复: 如果网络问题无法解决,你可能需要在网络恢复后考虑从主库重新备份数据,然后在从库上进行数据恢复。

总结

文章中介绍了Redis主从库架构以及如何配置、维护和解决主从库网络断开的问题。以下是文章中涉及到的主要内容:

  1. Redis主从库架构及其保证的高可靠性:
    • Redis主从库的目的是实现高可靠性,通过数据持久化、主从复制、Sentinel哨兵和Cluster集群等方式来保障数据的安全性和可用性。
  2. 如何保证副本数据一致:
    • Redis通过全量复制和部分复制(增量同步)来保证主从库之间的数据一致性。复制偏移量和复制积压缓冲区等机制用于记录和传输数据。
  3. 主从库第一次同步的过程:
    • 主从库之间的第一次同步涉及主服务器创建RDB快照,发送给从服务器,以及记录期间的写操作进行命令传播。
  4. PSYNC命令和增量同步:
    • PSYNC命令用于主从库网络断开后的增量同步。完全同步用于初次连接,部分同步用于增量同步,从而减少数据传输量。
  5. 主从从架构及其优势:
    • 主从从架构是在主从架构基础上的扩展,通过级联的方式减轻主服务器的复制压力,实现更高的可用性和负载均衡。
  6. 配置主从从架构的步骤:
    • 安装和配置主服务器,从服务器1和从服务器2。
    • 重启主服务器,查看主服务器信息。
    • 进行测试,验证主从库之间是否同步。
  7. 解决主从库间网络断开问题:
    • 检查网络连接问题,确保主从库之间可以互相访问。
    • 重新连接网络,恢复通信。
    • 检查主从状态,确保同步。
    • 手动重新同步,尝试恢复数据一致性。
    • 手动复制数据或备份恢复数据。

本文由mdnice多平台发布

相关推荐
小旭Coding18 分钟前
卧靠!Go 传给前端的 int64 竟然变成了这个?
后端
用户2986985301419 分钟前
Word 文档文本查找与替换的 Java 实现方案
java·后端
kunge201322 分钟前
深度剖析Claude Code 的CLAUDE.md加载逻辑
后端·vibecoding
米沙AI23 分钟前
MSYS2 快速使用版本
后端
Csvn32 分钟前
Docker 进阶 — 网络模型、数据持久化与多阶段构建
后端
用户42792540517136 分钟前
《微博开放平台官方CLI开源了:70+API一行搞定,AI Agent原生支持》
后端
Csvn36 分钟前
文本处理三剑客 — grep、sed、awk 实战精讲
后端
sarasuki39 分钟前
JavaScript的对象、new的机制与原型包装类
javascript·后端
某鹏43 分钟前
java伪共享问题的稳定解法
后端