抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文介绍了Redis的集群模式。

环境

Windows 10 企业版 LTSC 21H2
Redis 7.4.8

1 概述

集群模式(Cluster)是Redis的一种高可用方案,它将数据分布在多个节点上,实现数据的自动分片和高可用性。

相对于哨兵模式,集群模式不仅支持自动故障转移,还实现了数据的自动分片,提高了系统的横向扩展能力。

集群模式是Redis官方推荐的高可用方案,适用于大规模生产环境。

2 作用

集群模式的作用:

  1. 数据分片:将数据自动分布在多个节点上,提高系统的存储容量。
  2. 横向扩展:可以通过添加节点来扩展集群的容量和性能。
  3. 负载均衡:自动将请求分发到不同的节点,提高系统的整体性能。
  4. 故障转移:当集群中的主节点发生故障时,自动将从节点升级为主节点。
  5. 高可用:当部分节点发生故障时,集群仍然可以正常工作。

3 原理

3.1 数据分片

集群采用哈希槽(Hash Slot)的方式进行数据分片:

  • 整个集群共有16384个哈希槽。
  • 每个键通过CRC16算法计算哈希值,然后对16384取模,得到对应的哈希槽。
  • 每个节点负责一部分哈希槽。

3.2 节点类型

集群中的节点分为两种类型:

  • 主节点:负责处理读写请求,维护哈希槽。
  • 从节点:作为主节点的备份,当主节点发生故障时可以升级为主节点。

对于主节点来说,存在两种特殊情况:

  • 孤立主节点:指的是只有哈希槽,没有从节点的主节点,有数据但是缺少从节点。
  • 空壳主节点:指的是没有哈希槽,只有从节点的主节点,无数据所以从节点闲置。

3.3 通信机制

集群中的节点通过Gossip协议进行通信:

  • 节点定期随机向其他节点发送PING消息,包含自身状态和集群信息。
  • 其他节点回复PONG消息,更新本地集群状态。

通过Gossip协议,集群可以快速传播状态变化,保持一致性。

3.4 故障转移

当主节点发生故障时,集群会自动进行故障转移:

  • 从节点检测到主节点故障,标记为PFAIL表示可能故障。
  • 超过半数的从节点确认主节点故障,标记为FAIL表示确定故障。
  • 从节点之间进行投票,选举新的主节点。
  • 新的主节点接管原主节点的哈希槽。
  • 新的主节点向集群广播更新拓扑结构,通知其他节点。

3.5 资格检查

当主节点发生故障时,如果从节点发现自身数据过于陈旧,会避免发起故障转移,不参与主节点的选举。

为了衡量从节点的数据是否过期,节点会根据超时时间 * 检查因素 + 交互周期来计算节点的过期时间,如果从节点与主节点最后交互的时间超过这个时间,从节点会放弃尝试故障转移。

对于能够参与故障转移的从节点,会根据复制偏移量排序,复制偏移量越大,说明数据越新,成为主节点的概率越高。

3.6 客户端支持

为了简化客户端的使用,许多高级客户端(Jedis、Lettuce)实现了智能客户端(Smart Client)的功能,它能够:

  • 缓存槽位映射:首次连接时,从集群中获取并缓存槽位和节点的映射关系。
  • 自动计算槽位:计算键对应的槽位,将请求发往正确的节点,避免重定向开销。
  • 自动更新拓扑:当集群拓扑发生变化时,客户端能感知并更新本地的槽位映射。
  • 自动重定向:自动处理MOVED和ASK(槽位迁移中的临时重定向)错误。

4 配置

修改每个节点的redis.conf配置文件,启用集群模式:

redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 启用集群模式
cluster-enabled yes

# 集群配置文件路径,不同的节点需要不同的配置文件
cluster-config-file nodes-6379.conf

# 集群节点超时时间,默认为15000毫秒
# cluster-node-timeout 15000

# 集群端口,默认为0表示使用主端口+10000作为集群端口
# cluster-port 0

# 集群节点检查因素,默认为10,建议设置为0,保证所有从节点都会参与故障转移,避免没有主节点参与故障转移的极端困境
# cluster-replica-validity-factor 10

# 集群从节点迁移阈值,默认为1
# 设置为固定值:避免出现孤立主节点,当主节点的从节点数量超过阈值时,就会将其中某个从节点迁移到孤立主节点
# 设置为非常大的值:禁止迁移,允许出现孤立主节点
# 设置为0:会导致从节点随时可能迁移到孤立主节点,从而导致出现更多孤立主节点,引发集群震荡,生产环境不建议使用
# cluster-migration-barrier 1

# 集群是否允许从节点迁移,默认为yes
# yes:允许从节点迁移,避免出现孤立主节点
# no:禁止从节点迁移,也禁止从空壳主节点迁移从节点到孤立主节点,允许出现孤立主节点
# cluster-allow-replica-migration yes

# 集群是否要求所有槽位都可用,默认为yes
# yes:要求所有槽位都可用,不允许有空槽位,某个主节点故障并且无法产生新的主节点,整个集群将停止运行
# no:允许有槽位不可用,某个主节点故障并且无法产生新的主节点,整个集群将继续运行
# cluster-require-full-coverage yes

# 集群是否禁止从节点故障转移,默认为no
# yes:表示禁止从节点故障转移,从节点不能成为主节点,宁愿降低可用性也要追求数据绝对正确,可以防止脑裂问题,在多数据中心场景下建议使用
# no:表示允许从节点故障转移,从节点可以成为主节点,追求极致可用性可以牺牲数据一致性
# cluster-replica-no-failover no

# 集群因为槽位失效导致整体下线时,是否允许处理读取请求,默认为no
# yes:表示允许读取数据,保证高可用
# no:表示不允许读取数据
# cluster-allow-reads-when-down no

# 集群因为槽位失效导致整体下线时,是否允许处理发布订阅请求,默认为yes
# yes:表示允许处理发布订阅请求,保证高可用
# no:表示不允许处理发布订阅请求
# cluster-allow-pubsubshard-when-down yes

# 集群节点发送缓冲区大小,超过限制将会释放集群链路,默认为0表示不限制
# 超过限制说明节点接收消息过慢,防止缓冲区无限增长,推荐最小限制为1GB,至少能容纳单条消息(单条消息默认为1GB)
# cluster-link-sendbuf-limit 0

# 集群域名,解决IP地址变化但是域名固定的问题
# cluster-announce-hostname ""

# 集群节点名称,让日志和命令更容易阅读
# cluster-announce-human-nodename ""

# 集群连接方式,默认为IP地址
# ip:表示使用IP地址连接
# hostname:表示使用域名连接,需要设置集群域名
# unknown-endpoint:表示连接方式不固定,使用上次连接方式
# cluster-preferred-endpoint-type ip

5 搭建

5.1 准备节点

准备6个Redis节点,用于实现3主3从集群架构。

打开redis.conf配置文件,修改端口号并开启集群模式:

redis.conf
1
2
3
4
5
6
# 修改端口号
port 端口号
# 启用集群模式
cluster-enabled yes
# 集群配置文件路径,不同的节点需要不同的配置文件
cluster-config-file nodes-端口号.conf

启动6个Redis节点。

5.2 创建集群

语法:

cmd
1
redis-cli --cluster create 节点IP地址:节点端口号 ... 节点IP地址:节点端口号 --cluster-replicas 1 --cluster-yes

说明:

  • --cluster-replicas 1:表示每个主节点都有1个从节点。
  • --cluster-yes:表示自动确认创建集群,不需要手动确认。

示例:

cmd
1
redis-cli --cluster create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 127.0.0.1:6386 --cluster-replicas 1 --cluster-yes

执行成功后,集群自动分配槽位并完成主从绑定。

5.3 检查集群

语法:

cmd
1
redis-cli --cluster check 节点IP地址:节点端口号

示例:

cmd
1
redis-cli --cluster check 127.0.0.1:6381

5.4 查看信息

语法:

cmd
1
redis-cli --cluster info 节点IP地址:节点端口号

示例:

cmd
1
redis-cli --cluster info 127.0.0.1:6381

6 状态监控

6.1 连接集群

使用命令连接集群节点:

cmd
1
redis-cli -c -h 127.0.0.1 -p 6381

6.2 查看基本信息

使用命令查看集群的基本信息:

cmd
1
CLUSTER INFO

显示结果:

  • cluster_state:ok:集群状态,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:541:发送的PING消息数量
  • cluster_stats_messages_pong_sent:562:发送的PONG消息数量
  • cluster_stats_messages_sent:1103:发送的消息总数
  • cluster_stats_messages_ping_received:557:接收的PING消息数量
  • cluster_stats_messages_pong_received:541:接收的PONG消息数量
  • cluster_stats_messages_meet_received:5:接收的MEET消息数量
  • cluster_stats_messages_received:1103:接收的消息总数

6.3 查看节点状态

使用命令查看集群的节点状态:

cmd
1
CLUSTER NODES

6.4 查看哈希槽分配

使用命令查看集群的哈希槽分配:

cmd
1
CLUSTER SLOTS

7 集群管理

7.1 迁移槽位

语法:

cmd
1
2
3
4
5
redis-cli --cluster reshard 节点IP地址:节点端口号
--cluster-from 源节点ID,...,源节点ID
--cluster-to 目标节点ID
--cluster-slots 迁移槽位数量
--cluster-yes

说明:

  • --cluster-from 源节点ID,...,源节点ID:指定要迁移的源节点ID,多个节点用逗号分隔,使用all表示全部节点平均迁移。
  • --cluster-to 目标节点ID:指定要迁移的目标节点ID。
  • --cluster-slots 迁移槽位数量:指定要迁移的槽位数量。
  • --cluster-yes:表示自动确认迁移槽位,不需要手动确认。

如果不使用参数,会通过交互方式迁移槽位。

7.2 平衡集群

语法:

cmd
1
2
3
4
5
redis-cli --cluster rebalance 节点IP地址:节点端口号
--cluster-use-empty-masters
--cluster-weight 节点ID=权重 ... 节点ID=权重
--cluster-threshold 百分比
--cluster-simulate

说明:

  • --cluster-use-empty-masters:把槽位分配给当前没有槽位的主节点,扩容后负载均衡的常用选项。
  • --cluster-weight 节点ID=权重 ... 节点ID=权重:根据权重分配槽位给节点,权重支持整数和浮点数。
  • --cluster-threshold 百分比:设置触发平衡的阈值,避免微小波动引起不必要的数据迁移,只有节点槽位偏离平均值超过阈值时才会触发平衡,默认是2。
  • --cluster-simulate:模拟执行模式,显示将要执行的数据迁移计划,是生产环境操作前进行安全评估的首选工具。

如果不使用参数,只会平衡已有槽位并且偏离平均值2%的主节点,不会处理空节点。

7.3 添加节点

语法:

cmd
1
2
3
redis-cli --cluster add-node 新节点IP地址:新节点端口号 现有节点IP地址:现有节点端口号
--cluster-slave
--cluster-master-id 主节点ID

说明:

  • --cluster-slave:表示添加从节点,默认添加主节点。
  • --cluster-master-id 主节点ID:指定主节点的ID,默认随机主节点。

添加主节点后,需要迁移槽位或者平衡集群。

7.4 删除节点

语法:

cmd
1
redis-cli --cluster del-node 现有节点IP地址:现有节点端口号 删除节点ID

删除主节点之前,需要先将主节点的槽位分配给其他节点。

8 故障转移

8.1 自动故障转移

主节点宕机后,等待超时之后,集群自动发起故障选举,将从节点升级为主节点并接管槽位。

整个过程可能会丢失在主节点宕机前尚未同步给从节点的数据。

8.2 手动故障转移

在从节点上执行命令:

cmd
1
CLUSTER FAILOVER

从节点会与主节点进行一次数据同步,确保数据与主节点一致,然后发起切换,从节点先向集群宣布自己将要成为主节点,然后集群会将旧主节点降级为从节点并重新分配槽位。

整个过程中不会丢失已确认写入的数据,能够保证数据一致性,如果主节点宕机,命令直接报错,不会触发任何切换。

8.3 强制故障转移

在从节点上执行命令:

cmd
1
CLUSTER FAILOVER FORCE

从节点不等待数据同步,立即发起切换,从节点立刻升级为主节点并接管旧主节点所有槽位,旧主节点会降级为从节点并使用新主节点的数据。

整个过程可能会丢失未同步给从节点的数据,建议在主节点宕机时使用。

9 最佳实践

建议部署至少6个节点,形成3主3从的集群架构,以保证高可用性。

所有节点的硬件配置应尽可能一致,以保证集群的性能均衡。

评论