5.1 主从复制 (Master-Slave Replication)


文档摘要

5.1 主从复制 (Master-Slave Replication) Redis 复制 (Replication) 详解:5.1 主从复制 (Master-Slave Replication) 实践指南 在构建高可用、高性能的 Redis 应用时,数据冗余和读写分离是至关重要的策略。Redis 复制 (Replication) 正是实现这些目标的核心机制。它允许我们将数据从一个 Redis 服务器(主节点,Master)复制到一个或多个其他 Redis 服务器(从节点,Slave),从而在多个节点间同步数据,提升系统的可靠性和性能。 5.1 主从复制 (Master-Slave Replication) 概念详解 5.1.

5.1 主从复制 (Master-Slave Replication)

Redis 复制 (Replication) 详解:5.1 主从复制 (Master-Slave Replication) 实践指南

在构建高可用、高性能的 Redis 应用时,数据冗余和读写分离是至关重要的策略。Redis 复制 (Replication) 正是实现这些目标的核心机制。它允许我们将数据从一个 Redis 服务器(主节点,Master)复制到一个或多个其他 Redis 服务器(从节点,Slave),从而在多个节点间同步数据,提升系统的可靠性和性能。

5.1 主从复制 (Master-Slave Replication) 概念详解

5.1.1 核心概念

主从复制的核心思想是:将主节点的数据实时同步到一个或多个从节点。 主节点负责处理所有的写操作和部分读操作(可选),而从节点主要负责处理读操作,并作为主节点数据的备份。

关键角色:

  • 主节点 (Master): 负责接收写命令,并将数据变更同步给所有连接的从节点。主节点也可以处理读请求,但通常为了性能和稳定性,会将读请求分摊给从节点。

  • 从节点 (Slave): 连接到主节点,接收主节点同步过来的数据变更命令,并执行这些命令,保持自身数据与主节点一致。从节点通常只处理读请求,不允许执行写操作(默认配置)。

复制模式:

Redis 主从复制采用的是异步复制 (Asynchronous Replication) 模式。这意味着主节点在执行完写命令后,无需等待从节点的确认,即可继续处理后续命令。异步复制的优点是性能高,主节点的写入延迟低。缺点是数据一致性方面,在极端情况下(例如主节点突然宕机),可能会存在少量数据尚未同步到从节点的情况,导致数据丢失或短暂的不一致。

5.1.2 主从复制的工作流程

主从复制的建立和数据同步过程主要分为以下几个阶段:

  1. 连接建立 (Connection Establishment): 从节点启动后,通过配置或命令告知自身要复制的主节点地址和端口。从节点会与主节点建立连接,并发送 SYNCPSYNC 命令请求同步。

  2. 全量同步 (Full Synchronization): 这是首次复制或复制中断后重新连接时执行的操作。

    • 主节点接收到 SYNC 命令后,开始执行 BGSAVE 命令在后台生成 RDB 快照文件。

    • 主节点将生成的 RDB 快照文件发送给从节点。

    • 从节点接收到 RDB 文件后,先清空自身旧数据,然后加载 RDB 文件恢复数据。

    • 在发送 RDB 文件的过程中,主节点会将新的写命令缓存起来。

    • RDB 文件发送完成后,主节点会将缓存的写命令以 Redis 协议格式发送给从节点。

    • 从节点接收并执行这些缓存的写命令,完成全量数据同步。

  3. 增量同步 (Incremental Synchronization) / 命令传播 (Command Propagation): 全量同步完成后,主节点会将后续接收到的所有写命令(例如 SET, DEL, LPUSH 等)实时发送给从节点。从节点接收并执行这些命令,保持与主节点数据同步。这个过程是持续进行的,保证了数据的一致性。

  4. 心跳检测 (Heartbeat): 从节点会定期向主节点发送心跳包 (PING),检测主节点的健康状态。主节点也会响应从节点的心跳,并返回一些复制相关的信息。通过心跳检测,主从节点可以及时发现连接异常或故障。

PSYNC 命令:

为了优化复制效率,Redis 2.8 版本引入了 PSYNC 命令,用于支持增量复制 (Partial Synchronization)PSYNC 命令基于以下两个关键概念:

  • 复制偏移量 (Replication Offset): 主节点和从节点都会维护一个复制偏移量,用于记录各自已复制的数据位置。主节点每次向从节点发送数据时,都会更新自己的偏移量。从节点每次接收到主节点的数据时,也会更新自己的偏移量。

  • 复制积压缓冲区 (Replication Backlog Buffer): 主节点维护一个环形缓冲区,用于存储最近一段时间内的写命令日志。当从节点断线重连后,如果能从复制积压缓冲区中找到断线前的偏移量,就可以进行增量复制,只同步断线期间主节点产生的写命令,而无需进行全量同步,大大提高了复制效率。

PSYNC 命令的工作流程如下:

  • 从节点连接主节点后,发送 PSYNC <replication_id> <offset> 命令,其中 <replication_id> 是从节点之前复制的主节点的 ID,<offset> 是从节点上次复制的偏移量。

  • 主节点会根据 replication_idoffset 判断是否可以进行增量复制。

    • 情况 1 (增量复制): 如果主节点能找到匹配的 replication_idoffset 在复制积压缓冲区范围内,主节点会返回 CONTINUE 响应,并从偏移量 offset 开始,将复制积压缓冲区中缺失的数据发送给从节点,进行增量同步。

    • 情况 2 (全量同步): 如果主节点无法找到匹配的 replication_idoffset 超出复制积压缓冲区范围,主节点会返回 FULLRESYNC <new_replication_id> <offset> 响应,并执行全量同步流程(发送 RDB 文件)。

5.2 主从复制 (Master-Slave Replication) 代码实践

接下来,我们将通过实际的代码配置和操作,演示如何搭建和使用 Redis 主从复制。

5.2.1 环境准备

  • Redis 服务器: 你需要至少两台 Redis 服务器,一台作为主节点,一台作为从节点。你可以在同一台机器上启动多个 Redis 实例,通过不同的端口区分。

  • Redis 客户端: 可以使用 redis-cli 命令行客户端,或者各种编程语言的 Redis 客户端库(例如 Python 的 redis-py,Java 的 Jedis,Node.js 的 ioredis 等)。

5.2.2 配置主节点 (Master)

主节点通常不需要特别的配置,默认配置即可作为主节点。你可以检查主节点的配置文件 redis.conf (或通过 CONFIG GET 命令查看) 中是否设置了 slaveof 指令。如果设置了 slaveof 指令,则该实例将作为从节点启动。

确保主节点配置文件中没有 slaveof 指令。

5.2.3 配置从节点 (Slave)

配置从节点主要通过修改从节点的配置文件 redis.conf 或在 redis-cli 客户端中使用 SLAVEOF 命令。

方法一:修改 redis.conf 配置文件

打开从节点的 redis.conf 文件,找到 slaveof 指令,并修改为指向主节点的地址和端口。例如,假设主节点的 IP 地址为 192.168.1.100,端口为 6379,则在从节点的 redis.conf 中添加或修改以下配置:

slaveof 192.168.1.100 6379

可选配置 (根据需求调整):

  • masterauth <password>: 如果主节点设置了密码认证,则需要配置 masterauth 指令,指定主节点的密码。

  • slave-read-only yes/no: 默认情况下,从节点是只读的 (slave-read-only yes)。如果需要允许从节点执行写操作(不推荐),可以设置为 slave-read-only no

  • slave-priority <priority>: 设置从节点的优先级,用于在主节点宕机后,Sentinel 或手动故障转移时,选择哪个从节点晋升为主节点。优先级数字越小,优先级越高。

修改完配置文件后,重启从节点 Redis 服务,使配置生效。

方法二:使用 redis-cli 命令动态配置

连接到从节点的 redis-cli 客户端,执行 SLAVEOF 命令,指定主节点的地址和端口。例如:

redis-cli -h <slave_ip> -p <slave_port> SLAVEOF 192.168.1.100 6379

如果主节点设置了密码,需要先进行认证:

redis-cli -h <slave_ip> -p <slave_port> AUTH <slave_password> # 如果从节点也设置了密码 SLAVEOF 192.168.1.100 6379 <master_password>

使用 SLAVEOF 命令配置的复制关系是动态的,重启从节点后配置会失效。如果需要持久化配置,建议使用修改 redis.conf 文件的方式。

5.2.4 验证主从复制状态

配置完成后,可以通过以下方式验证主从复制是否成功建立:

1. 在主节点上查看信息:

连接到主节点的 redis-cli 客户端,执行 INFO replication 命令:

redis-cli -h <master_ip> -p <master_port> INFO replication

在输出信息中,你可以看到以下关键字段:

  • role:master: 表示当前节点是主节点。

  • connected_slaves:<N>: 表示连接到主节点的从节点数量。

  • slave<N>:ip=<slave_ip>,port=<slave_port>,state=online,offset=<offset>,lag=<lag>: 列出每个连接的从节点的信息,包括 IP 地址、端口、状态 (online 表示在线)、复制偏移量 (offset)、复制延迟 (lag) 等。

2. 在从节点上查看信息:

连接到从节点的 redis-cli 客户端,执行 INFO replication 命令:

redis-cli -h <slave_ip> -p <slave_port> INFO replication

在输出信息中,你可以看到以下关键字段:

  • role:slave: 表示当前节点是从节点。

  • master_host:<master_ip>: 表示主节点的 IP 地址。

  • master_port:<master_port>: 表示主节点的端口。

  • master_link_status:up: 表示与主节点的连接状态为正常 (up)。

  • master_sync_in_progress:0: 表示当前没有进行全量同步。

  • slave_repl_offset:<offset>: 表示从节点已复制的偏移量。

  • master_repl_offset:<offset>: 表示主节点的复制偏移量。从节点的 slave_repl_offset 应该逐渐追赶 master_repl_offset

3. 数据同步验证:

在主节点上执行写操作,例如:

redis-cli -h <master_ip> -p <master_port> SET mykey master_value

然后在从节点上读取数据:

redis-cli -h <slave_ip> -p <slave_port> GET mykey

如果从节点能够读取到主节点写入的数据 master_value,则说明主从复制工作正常。

5.2.5 代码示例 (Python redis-py)

以下 Python 代码示例演示了如何使用 redis-py 客户端连接主节点和从节点,并进行读写操作:

import redis # 主节点连接信息 master_host = "192.168.1.100" master_port = 6379 # 从节点连接信息 slave_host = "192.168.1.101" slave_port = 6380 try: # 连接主节点 master_client = redis.Redis(host=master_host, port=master_port) master_client.ping() # 检查连接 # 连接从节点 slave_client = redis.Redis(host=slave_host, port=slave_port) slave_client.ping() # 检查连接 # 在主节点上写入数据 master_client.set("mykey", "master_value") print("Master set key 'mykey' to 'master_value'") # 从从节点读取数据 slave_value = slave_client.get("mykey") print(f"Slave get key 'mykey': {slave_value.decode('utf-8')}") # 尝试在从节点上写入数据 (预期会失败,因为默认从节点只读) try: slave_client.set("slave_key", "slave_value") print("Error: Slave should not allow write operations!") # 不应该执行到这里 except redis.exceptions.ReadOnlyError as e: print(f"Expected ReadOnlyError on slave: {e}") except redis.exceptions.ConnectionError as e: print(f"Connection error: {e}") except Exception as e: print(f"An error occurred: {e}") finally: if 'master_client' in locals() and master_client: master_client.close() if 'slave_client' in locals() and slave_client: slave_client.close()

代码说明:

  • 代码分别创建了连接主节点和从节点的 redis.Redis 客户端实例。

  • 在主节点客户端上执行 SET 命令写入数据。

  • 在从节点客户端上执行 GET 命令读取数据,验证数据同步。

  • 尝试在从节点客户端上执行 SET 命令,预期会抛出 ReadOnlyError 异常,因为默认情况下从节点是只读的。

你可以根据你的编程语言选择相应的 Redis 客户端库,并参考上述代码示例进行主从复制的实践。

5.2.6 主从切换 (Failover) 演示 (手动)

在主从复制环境中,如果主节点发生故障宕机,我们需要将其中一个从节点晋升为主节点,以保证服务的可用性。以下演示手动主从切换的步骤:

假设场景:

  • 主节点 IP: 192.168.1.100:6379 (宕机)

  • 从节点 IP 1: 192.168.1.101:6380

  • 从节点 IP 2: 192.168.1.102:6381

手动切换步骤:

  1. 选择一个从节点晋升为主节点: 通常选择数据最新(复制延迟最小)的从节点。例如,选择 192.168.1.101:6380

  2. 在选定的从节点上执行 SLAVEOF NO ONE 命令:

    redis-cli -h 192.168.1.101 -p 6380 SLAVEOF NO ONE

    执行 SLAVEOF NO ONE 命令后,该从节点会停止复制,晋升为新的主节点。它将开始接受写操作,并成为其他从节点的复制源。

  3. 将其他从节点指向新的主节点: 将其他从节点(例如 192.168.1.102:6381)重新配置为复制新的主节点 192.168.1.101:6380

    redis-cli -h 192.168.1.102 -p 6381 SLAVEOF 192.168.1.101 6380
  4. 客户端切换: 应用程序客户端需要更新连接配置,将写操作指向新的主节点 192.168.1.101:6380,读操作可以继续分发到所有从节点。

注意事项:

  • 手动切换存在数据丢失风险: 在主节点宕机时,可能存在部分数据尚未同步到从节点,手动切换可能会导致这部分数据的丢失。

  • 手动切换操作繁琐且容易出错: 在生产环境中,手动切换容易出现人为失误,且切换时间较长,影响服务可用性。

  • 推荐使用 Sentinel 或 Cluster 进行自动故障转移: 为了实现更可靠、自动化的故障转移,生产环境通常会使用 Redis Sentinel 或 Redis Cluster,它们可以自动监控主节点状态,并在主节点宕机时自动进行主从切换,减少人工干预,提高系统可用性。

5.3 主从复制 (Master-Slave Replication) 总结与最佳实践

Redis 主从复制是构建高可用、高性能 Redis 应用的基础。它提供了数据冗余和读写分离能力,是 Redis 集群和 Sentinel 的基石。

总结:

  • 优点:

    • 数据冗余: 提供数据备份,提高数据安全性。

    • 读写分离: 分摊读请求压力,提高读取性能。

    • 高可用性基础: 为故障转移和高可用架构提供基础。

  • 缺点:

    • 异步复制可能存在数据丢失风险: 极端情况下可能丢失少量数据。

    • 手动故障转移操作复杂: 生产环境不推荐手动切换。

    • 主节点写入瓶颈: 所有写操作都集中在主节点,写入性能受主节点限制。

最佳实践:

  • 生产环境推荐使用 Sentinel 或 Cluster 进行自动故障转移。

  • 合理配置从节点的数量,根据读请求压力和数据冗余需求进行调整。

  • 监控复制状态和延迟,及时发现和处理复制异常。

  • 根据应用场景选择合适的持久化策略 (RDB 或 AOF),并确保主从节点持久化配置一致。

  • 在网络环境良好的情况下部署主从节点,减少网络延迟对复制性能的影响。

  • 合理利用从节点的只读特性,将读请求分发到从节点,减轻主节点压力。

掌握 Redis 主从复制是深入理解 Redis 高级特性的关键一步。通过本文的详细讲解和代码实践,相信你已经对 Redis 主从复制有了更深入的理解。在实际项目中,根据你的业务需求和场景,合理配置和使用 Redis 主从复制,将能够构建更稳定、高效的 Redis 应用系统。


发布者: 作者: 转发
评论区 (0)
U