6.2 Redis Cluster 的搭建与管理


文档摘要

6.2 Redis Cluster 的搭建与管理 6.2 Redis Cluster 的搭建与管理详解 (Redis 3.0+) 6.2.1 Redis Cluster 核心概念回顾 在深入搭建和管理之前,我们先回顾一下 Redis Cluster 的几个核心概念,这对于理解后续的操作至关重要: 节点 (Node): Redis Cluster 由多个 Redis 节点组成,每个节点负责存储一部分数据并参与集群的管理和数据路由。 槽 (Slot): Redis Cluster 将所有的数据划分为 16384 个槽 (slot),每个槽对应一个哈希范围。集群中的每个节点负责一部分槽。

6.2 Redis Cluster 的搭建与管理

6.2 Redis Cluster 的搭建与管理详解 (Redis 3.0+)

6.2.1 Redis Cluster 核心概念回顾

在深入搭建和管理之前,我们先回顾一下 Redis Cluster 的几个核心概念,这对于理解后续的操作至关重要:

  • 节点 (Node): Redis Cluster 由多个 Redis 节点组成,每个节点负责存储一部分数据并参与集群的管理和数据路由。

  • 槽 (Slot): Redis Cluster 将所有的数据划分为 16384 个槽 (slot),每个槽对应一个哈希范围。集群中的每个节点负责一部分槽。

  • 哈希分布 (Hash Distribution): 当客户端访问 Redis Cluster 时,键 (key) 会通过 CRC16 算法进行哈希计算,然后对 16384 取模,得到键对应的槽。集群会根据槽与节点的映射关系,将请求路由到负责该槽的节点。

  • Gossip 协议 (Gossip Protocol): 节点之间通过 Gossip 协议进行通信,交换集群信息,例如节点状态、槽分配情况等,保证集群状态的一致性。

  • 主从复制 (Master-Slave Replication): 为了保证数据的高可用性,Redis Cluster 采用主从复制机制。每个主节点可以有一个或多个从节点,当主节点故障时,从节点可以自动晋升为主节点。

  • 自动故障转移 (Automatic Failover): 当集群中的主节点发生故障时,集群能够自动检测到,并从其从节点中选举出一个新的主节点,接替原主节点的工作,从而保证集群的持续可用性。

6.2.2 Redis Cluster 搭建准备

在开始搭建 Redis Cluster 之前,我们需要准备以下环境和资源:

  1. 服务器环境: 建议准备至少 6 台服务器(或者虚拟机/Docker 容器),用于部署 Redis Cluster 节点。为了演示方便,我们可以在一台机器上模拟多个节点,但生产环境强烈建议使用独立的物理机或虚拟机。

  2. Redis 版本: 确保安装 Redis 3.0 或以上版本。本文基于 Redis 7.0 版本进行演示,建议使用较新的稳定版本。

  3. Ruby 环境 (可选): 早期版本的 Redis Cluster 工具 redis-trib.rb 需要 Ruby 环境。虽然新版本 Redis 已经提供了 redis-cli --cluster 命令用于集群管理,但了解 redis-trib.rb 仍然有助于理解集群的底层操作。如果使用 redis-trib.rb,需要安装 Ruby 和 Redis 的 Ruby 客户端 redis gem。

  4. 网络配置: 确保服务器之间网络互通,防火墙允许 Redis 端口(默认为 6379)和集群总线端口(默认端口 + 10000,即 16379)的通信。

6.2.3 Redis Cluster 搭建步骤 (使用 redis-cli --cluster)

以下步骤将演示如何使用 Redis 7.0 自带的 redis-cli --cluster 命令来搭建一个基本的 Redis Cluster。

步骤 1: 准备 Redis 配置文件

为每个 Redis 节点创建独立的配置文件,例如 redis-node1.conf, redis-node2.conf, ..., redis-node6.conf。 以下是一个基本的配置文件示例 (以 redis-node1.conf 为例):

port 7001 # 节点端口,每个节点端口不同 cluster-enabled yes # 启用集群模式 cluster-config-file nodes-7001.conf # 集群配置文件名,每个节点不同 cluster-node-timeout 15000 # 节点超时时间,单位毫秒 appendonly yes # 开启 AOF 持久化 (可选,建议开启) dir /data/redis/node1 # 数据目录,每个节点目录不同 logfile /data/redis/node1/redis.log # 日志文件路径,每个节点目录不同

关键配置项说明:

  • port: 每个节点的监听端口,需要确保端口不冲突。

  • cluster-enabled yes: 必须配置, 启用 Redis Cluster 模式。

  • cluster-config-file: 集群配置文件名,Redis 会自动维护该文件,记录集群节点信息、槽分配等。文件名可以自定义,但建议包含端口号以区分不同节点的配置文件。

  • cluster-node-timeout: 节点超时时间,集群节点在指定时间内未收到 PING 消息则认为节点下线。

  • appendonly yes: 建议开启 AOF 持久化,保证数据安全。

  • dir: 数据目录,用于存放 RDB 快照和 AOF 日志文件,每个节点需要配置不同的目录。

  • logfile: 日志文件路径,方便排查问题。

为所有 6 个节点创建类似的配置文件,并修改端口号 (7001, 7002, 7003, 7004, 7005, 7006) 和数据目录、日志文件路径。

步骤 2: 启动 Redis 节点

分别使用各自的配置文件启动 6 个 Redis 节点。

redis-server redis-node1.conf redis-server redis-node2.conf redis-server redis-node3.conf redis-server redis-node4.conf redis-server redis-node5.conf redis-server redis-node6.conf

启动后,可以通过 ps aux | grep redis-server 命令检查节点是否成功启动。

步骤 3: 创建 Redis Cluster

使用 redis-cli --cluster create 命令创建集群。我们需要指定至少 3 个 Master 节点的地址(IP:Port)。Redis Cluster 会自动将剩余的节点作为 Slave 节点分配给 Master 节点。

redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1

命令参数说明:

  • create: 指定创建集群操作。

  • 127.0.0.1:7001 ... 127.0.0.1:7006: 列出所有参与集群创建的节点地址,至少需要 3 个 Master 节点。

  • --cluster-replicas 1: 指定每个 Master 节点配备 1 个 Slave 节点。

执行命令后,会看到如下类似输出,确认集群配置信息,输入 yes 确认创建:

>>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 127.0.0.1:7004 to 127.0.0.1:7001 Adding replica 127.0.0.1:7005 to 127.0.0.1:7002 Adding replica 127.0.0.1:7006 to 127.0.0.1:7003 >>> Trying to optimize allocation of replicas on nodes... >>> M: e76467446411b390991f2b8f3950b796d6f8f223 127.0.0.1:7001 slots:[0-5460] (5461 slots) master >>> M: 1279a5679834b7819381a72b6509c2a7e9832d11 127.0.0.1:7002 slots:[5461-10922] (5462 slots) master >>> M: 48a8b987654c3421f987d654a321cba987654321 127.0.0.1:7003 slots:[10923-16383] (5461 slots) master >>> S: 987c654321a9b876c543d21a9876b543d21a9876 127.0.0.1:7004 replicates e76467446411b390991f2b8f3950b796d6f8f223 >>> S: c654321a987b6543d21a9876b543d21a98765432 127.0.0.1:7005 replicates 1279a5679834b7819381a72b6509c2a7e9832d11 >>> S: 54321a987b6543d21a9876b543d21a9876c6543 127.0.0.1:7006 replicates 48a8b987654c3421f987d654a321cba987654321 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .... >>> Performing Cluster Check (using node 127.0.0.1:7001) M: e76467446411b390991f2b8f3950b796d6f8f223 127.0.0.1:7001 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 987c654321a9b876c543d21a9876b543d21a9876 127.0.0.1:7004 slots: (0 slots) slave replicates e76467446411b390991f2b8f3950b796d6f8f223 M: 1279a5679834b7819381a72b6509c2a7e9832d11 127.0.0.1:7002 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: c654321a987b6543d21a9876b543d21a98765432 127.0.0.1:7005 slots: (0 slots) slave replicates 1279a5679834b7819381a72b6509c2a7e9832d11 M: 48a8b987654c3421f987d654a321cba987654321 127.0.0.1:7003 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 54321a987b6543d21a9876b543d21a9876c6543 127.0.0.1:7006 slots: (0 slots) slave replicates 48a8b987654c3421f987d654a321cba987654321 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

当看到 [OK] All 16384 slots covered.[OK] All nodes agree about slots configuration. 时,表示 Redis Cluster 创建成功。

步骤 4: 连接 Redis Cluster

使用 redis-cli -c 命令连接到 Redis Cluster。 -c 参数表示以集群模式连接。

redis-cli -c -p 7001

连接成功后,尝试执行一些 Redis 命令,例如 SET key value, GET key 等。Redis Cluster 会自动根据 key 的槽将请求路由到正确的节点。

代码实践示例:

127.0.0.1:7001> SET mykey myvalue -> Redirected to slot [13321] located at 127.0.0.1:7003 OK 127.0.0.1:7003> GET mykey "myvalue"

可以看到,当我们连接到 7001 端口的节点并设置 mykey 时,请求被重定向到 7003 端口的节点,这是因为 mykey 的槽 (13321) 归 7003 节点负责。

6.2.4 Redis Cluster 管理操作

Redis Cluster 创建完成后,还需要进行日常的管理操作,例如添加节点、删除节点、查看集群状态等。

1. 查看集群状态: CLUSTER INFOCLUSTER NODES

连接到集群中的任意节点,可以使用 CLUSTER INFOCLUSTER NODES 命令查看集群状态。

127.0.0.1:7001> CLUSTER INFO cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:1234 cluster_stats_messages_pong_sent:5678 cluster_stats_messages_sent:6912 cluster_stats_messages_received:6912
  • cluster_state:ok: 表示集群状态正常。

  • cluster_slots_assigned:16384: 已分配的槽数量。

  • cluster_slots_ok:16384: 正常服务的槽数量。

  • cluster_known_nodes:6: 集群已知节点数量。

  • cluster_size:3: 集群中 Master 节点数量。

127.0.0.1:7001> CLUSTER NODES e76467446411b390991f2b8f3950b796d6f8f223 127.0.0.1:7001@17001 master - 0 1699587654000 1 connected 0-5460 1279a5679834b7819381a72b6509c2a7e9832d11 127.0.0.1:7002@17002 master - 0 1699587655000 2 connected 5461-10922 48a8b987654c3421f987d654a321cba987654321 127.0.0.1:7003@17003 master - 0 1699587656000 3 connected 10923-16383 987c654321a9b876c543d21a9876b543d21a9876 127.0.0.1:7004@17004 slave e76467446411b390991f2b8f3950b796d6f8f223 0 1699587657000 1 connected c654321a987b6543d21a9876b543d21a98765432 127.0.0.1:7005@17005 slave 1279a5679834b7819381a72b6509c2a7e9832d11 0 1699587658000 2 connected 54321a987b6543d21a9876b543d21a9876c6543 127.0.0.1:7006@17006 slave 48a8b987654c3421f987d654a321cba987654321 0 1699587659000 3 connected
  • CLUSTER NODES 命令输出集群中所有节点的信息,包括节点 ID, IP:Port, 角色 (master/slave), 所负责的槽范围 (slots) 等。

2. 添加新节点

当集群需要扩容时,可以添加新的节点。添加节点分为两种情况:添加 Master 节点和添加 Slave 节点。

a. 添加 Master 节点:

假设我们要添加一个新的 Master 节点到端口 7007。

首先,准备 redis-node7.conf 配置文件,并启动 Redis 节点。

然后,使用 redis-cli --cluster add-node 命令将新节点添加到现有集群中。我们需要指定新节点的地址和集群中已存在节点的地址。

redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001

执行命令后,新节点会被加入到集群中,但此时它还没有分配任何槽,是一个孤立的 Master 节点。我们需要手动将一部分槽迁移到新节点,才能让它真正参与数据存储和服务。槽迁移操作比较复杂,将在后续 "集群伸缩 (Resharding)" 部分详细介绍。

b. 添加 Slave 节点:

添加 Slave 节点相对简单,可以使用 redis-cli --cluster add-node 命令,并指定新节点要复制的 Master 节点 ID。

假设我们要将端口 7008 的节点作为 7001 节点的 Slave 节点。

首先,准备 redis-node8.conf 配置文件,并启动 Redis 节点。

然后,使用 redis-cli --cluster add-node 命令,并使用 --cluster-slave--cluster-master-id 参数指定 Slave 节点和 Master 节点。

redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave --cluster-master-id e76467446411b390991f2b8f3950b796d6f8f223

其中 e76467446411b390991f2b8f3950b796d6f8f223 是 7001 节点的 Node ID,可以通过 CLUSTER NODES 命令查看。

执行命令后,7008 节点会成为 7001 节点的 Slave 节点,并开始同步数据。

3. 删除节点

删除节点也分为删除 Master 节点和删除 Slave 节点。

a. 删除 Slave 节点:

删除 Slave 节点比较简单,使用 redis-cli --cluster del-node 命令,指定要删除的 Slave 节点的 Node ID 即可。

redis-cli --cluster del-node 127.0.0.1:7001 <Slave Node ID>

b. 删除 Master 节点:

删除 Master 节点比较复杂,需要确保被删除的 Master 节点上的槽先被迁移到其他 Master 节点,否则会导致数据丢失。

删除 Master 节点的步骤如下:

  1. 将 Master 节点上的槽迁移到其他 Master 节点 (Resharding): 这是最关键的一步,确保数据安全。槽迁移操作将在后续 "集群伸缩 (Resharding)" 部分详细介绍。

  2. 删除 Master 节点: 当 Master 节点上的槽被迁移完毕后,可以使用 redis-cli --cluster del-node 命令删除 Master 节点。

redis-cli --cluster del-node 127.0.0.1:7001 <Master Node ID>

注意: 在生产环境中删除 Master 节点需要谨慎操作,务必先进行充分的测试和备份。

4. 集群伸缩 (Resharding)

集群伸缩是指在不停止服务的情况下,动态地调整集群的容量,包括添加 Master 节点和删除 Master 节点。集群伸缩的核心操作是槽迁移 (Resharding)。

槽迁移原理:

槽迁移是将一部分槽从一个 Master 节点迁移到另一个 Master 节点的过程。迁移过程中,集群需要保证数据的一致性和服务的可用性。Redis Cluster 采用增量迁移的方式,逐步将槽以及槽对应的数据从源节点迁移到目标节点。

使用 redis-cli --cluster reshard 进行槽迁移:

redis-cli --cluster reshard 命令提供了交互式的槽迁移功能。

redis-cli --cluster reshard 127.0.0.1:7001

执行命令后,会进入交互模式,需要按照提示进行操作:

  1. How many slots do you want to move (from 1 to 16384)? 输入要迁移的槽数量。

  2. What is the receiving node ID? 输入目标 Master 节点的 Node ID。

  3. Please enter all the source node IDs. 输入源 Master 节点的 Node ID (可以输入 all 表示从所有 Master 节点迁移)。

按照提示完成操作后,Redis Cluster 会自动进行槽迁移。可以使用 CLUSTER INFOCLUSTER NODES 命令监控迁移进度。

代码实践示例 (Resharding):

假设我们要将 1000 个槽从现有集群迁移到新添加的 Master 节点 7007 (假设其 Node ID 为 abcdefg1234567890)。

redis-cli --cluster reshard 127.0.0.1:7001 >>> Performing reshard... [OK] 127.0.0.1:7001: Resharding started... How many slots do you want to move (from 1 to 16384)? 1000 What is the receiving node ID? abcdefg1234567890 Please enter all the source node IDs. all ... (迁移过程输出) ... >>> Resharding finished!

5. 故障转移 (Failover)

Redis Cluster 具有自动故障转移功能。当 Master 节点发生故障时,集群会自动检测到,并从其 Slave 节点中选举出一个新的 Master 节点。

模拟 Master 节点故障:

可以手动停止一个 Master 节点的 Redis 进程来模拟故障。

redis-cli -p 7001 SHUTDOWN

停止 Master 节点后,集群会开始故障转移过程。可以通过 CLUSTER NODES 命令观察节点状态变化。

在故障转移过程中,原来的 Slave 节点会晋升为主节点,接替原 Master 节点的工作。客户端连接可能会短暂中断,但集群整体服务不会受到影响。

手动故障转移:

在某些情况下,我们可能需要手动触发故障转移,例如进行节点维护或升级。可以使用 CLUSTER FAILOVER 命令手动触发故障转移。

127.0.0.1:7001> CLUSTER FAILOVER OK

在需要进行故障转移的 Master 节点上执行 CLUSTER FAILOVER 命令,会强制该节点进行故障转移,将其 Slave 节点晋升为主节点。

6.2.5 Redis Cluster 持久化与备份

Redis Cluster 的持久化和备份策略与单机 Redis 类似,可以使用 RDB 快照和 AOF 日志。

  • 持久化: 建议同时开启 RDB 和 AOF 持久化,以提高数据安全性。在 redis.conf 配置文件中配置 saveappendonly yes 等选项。

  • 备份: Redis Cluster 的备份需要对每个节点的数据进行备份。可以编写脚本,定期执行 BGSAVE 命令生成 RDB 快照,并将 RDB 文件和 AOF 文件复制到备份存储。

集群备份脚本示例 (简易版):

#!/bin/bash BACKUP_DIR="/data/redis_cluster_backup" NODES="127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006" DATE=$(date +%Y%m%d%H%M%S) mkdir -p ${BACKUP_DIR}/${DATE} for NODE in ${NODES}; do IP=$(echo $NODE | awk -F ":" '{print $1}') PORT=$(echo $NODE | awk -F ":" '{print $2}') NODE_DIR="/data/redis/node${PORT}" # 假设数据目录命名规则 BACKUP_NODE_DIR="${BACKUP_DIR}/${DATE}/node${PORT}" mkdir -p ${BACKUP_NODE_DIR} redis-cli -h ${IP} -p ${PORT} BGSAVE sleep 5 # 等待 BGSAVE 完成 (生产环境需要更完善的判断机制) cp ${NODE_DIR}/dump.rdb ${BACKUP_NODE_DIR}/ cp ${NODE_DIR}/appendonly.aof ${BACKUP_NODE_DIR}/ echo "Backup node ${NODE} done." done echo "Redis Cluster backup finished at ${DATE}."

注意: 生产环境的备份脚本需要更加完善,例如加入错误处理、日志记录、备份文件压缩、远程存储等功能。

6.2.6 Redis Cluster 监控与优化

  • 监控: 可以使用 Redis 自带的 INFO 命令和 CLUSTER INFO 命令监控集群状态和性能指标。也可以使用第三方监控工具,例如 RedisInsight, Prometheus + Grafana 等。

  • 性能优化:

    • 合理配置硬件资源: 根据业务需求选择合适的 CPU, 内存, 磁盘等硬件资源。

    • 优化 Redis 配置: 根据实际情况调整 maxmemory, maxclients, timeout 等 Redis 配置参数。

    • 网络优化: 确保节点之间网络延迟低,带宽充足。

    • 客户端优化: 使用连接池,减少连接开销。批量操作 (pipeline) 可以提高吞吐量。


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