Redis搭建分片集群

一、前言:为什么需要 Redis 分片集群?

当你的 Redis 单实例面临以下问题时:

  • ❌ 内存超过 32GB,fork 阻塞严重
  • ❌ QPS 超过 10万,单机 CPU 成瓶颈
  • ❌ 数据量超 50GB,RDB/AOF 恢复慢如蜗牛

Redis Cluster(分片集群) 就是官方提供的分布式解决方案 ,它能:

自动分片(Sharding) :将数据分散到多个节点

高可用 :每个分片支持主从复制 + 自动故障转移

去中心化 :无 Proxy,客户端直连节点

线性扩展:加机器即可扩容

本文将手把手教你从零搭建一个 3 主 3 从的 Redis Cluster,并验证其高可用能力。


二、集群规划

2.1 节点分配(最小生产可用规模)

节点 IP 端口 角色 说明
node1 192.168.1.10 7001 master 分片 0
node2 192.168.1.10 7002 master 分片 1
node3 192.168.1.10 7003 master 分片 2
node4 192.168.1.10 7004 slave node1 的从
node5 192.168.1.10 7005 slave node2 的从
node6 192.168.1.10 7006 slave node3 的从

💡 单机测试 :可在一台机器用不同端口模拟
生产建议:6 台物理机(3 主 3 从跨机房部署)

2.2 分片原理

  • Redis Cluster 使用 16384 个哈希槽(slot)
  • 每个 key 通过 CRC16(key) % 16384 计算所属 slot
  • 每个 master 负责一部分 slot(如 0~5460, 5461~10922, 10923~16383)

三、第一步:准备 Redis 配置文件

为每个节点创建独立配置目录:

bash 复制代码
mkdir -p /opt/redis-cluster/{7001,7002,7003,7004,7005,7006}

3.1 创建通用配置模板(redis.conf)

复制代码
# /opt/redis-cluster/redis.conf.template
port 7001                    # 每个实例修改为对应端口
cluster-enabled yes          # 启用集群模式
cluster-config-file nodes.conf
cluster-node-timeout 15000   # 节点超时(毫秒)
appendonly yes               # 开启 AOF(推荐)
protected-mode no            # 关闭保护模式(生产环境应设密码)
bind 0.0.0.0
daemonize yes
dir /opt/redis-cluster/7001  # 每个实例修改为对应目录

3.2 为每个节点生成配置

bash 复制代码
for port in {7001..7006}; do
  cp redis.conf.template /opt/redis-cluster/$port/redis.conf
  sed -i "s/port 7001/port $port/g" /opt/redis-cluster/$port/redis.conf
  sed -i "s/dir .*/dir \/opt\/redis-cluster\/$port/g" /opt/redis-cluster/$port/redis.conf
done

四、第二步:启动所有 Redis 实例

bash 复制代码
for port in {7001..7006}; do
  redis-server /opt/redis-cluster/$port/redis.conf
done

验证进程:

bash 复制代码
ps -ef | grep redis-server
# 应看到 6 个进程,端口 7001~7006

五、第三步:创建集群(使用 redis-cli --cluster)

⚠️ Redis 5.0+ 才支持 --cluster 命令

5.1 执行集群创建命令

bash 复制代码
redis-cli --cluster create \
  192.168.1.10:7001 \
  192.168.1.10:7002 \
  192.168.1.10:7003 \
  192.168.1.10:7004 \
  192.168.1.10:7005 \
  192.168.1.10:7006 \
  --cluster-replicas 1 \  # 每个主节点配 1 个从节点
  --cluster-yes           # 自动确认

5.2 输出解读

复制代码
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.1.10:7004 to 192.168.1.10:7001
Adding replica 192.168.1.10:7005 to 192.168.1.10:7002
Adding replica 192.168.1.10:7006 to 192.168.1.10:7003
>>> 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 192.168.1.10:7001)
... OK

成功!集群已创建,slot 自动分配。


六、第四步:验证集群状态

6.1 查看集群信息

bash 复制代码
redis-cli -p 7001 cluster info

关键字段:

  • cluster_state:ok → 集群正常
  • cluster_slots_assigned:16384 → 所有 slot 已分配

6.2 查看节点拓扑

bash 复制代码
redis-cli -p 7001 cluster nodes

输出示例:

复制代码
a1b2c3d4... 192.168.1.10:7001@17001 master - 0 1700000000 1 connected 0-5460
e5f6g7h8... 192.168.1.10:7004@17004 slave a1b2c3d4... 0 1700000000 4 connected
...
  • master:主节点
  • slave <master-id>:从节点,指向主节点 ID
  • connected 0-5460:负责的 slot 范围

6.3 测试数据读写

bash 复制代码
# 写入 key(自动路由到对应分片)
redis-cli -c -p 7001 set user:1001 "Alice"
redis-cli -c -p 7001 set user:1002 "Bob"

# 读取(-c 参数启用集群模式,自动重定向)
redis-cli -c -p 7001 get user:1001

🔑 必须加 -c :否则会报 (error) MOVED 12345 192.168.1.10:7002


七、第五步:模拟故障转移(高可用验证)

7.1 手动杀死主节点

bash 复制代码
# 杀死 7001(假设它负责 user:1001)
kill $(pgrep -f "7001")

7.2 观察从节点升主

等待 15~30 秒(cluster-node-timeout),查看集群状态:

bash 复制代码
redis-cli -p 7004 cluster nodes

→ 应看到 7004 的角色变为 master,且接管 slot 0-5460

7.3 验证数据可读写

bash 复制代码
redis-cli -c -p 7004 get user:1001  # 仍可读取
redis-cli -c -p 7004 set user:1003 "Charlie"  # 可写入

7.4 原主恢复后自动变为从节点

重启 7001:

bash 复制代码
redis-server /opt/redis-cluster/7001/redis.conf

再次执行 cluster nodes → 7001 变为 slave,同步新主(7004)数据

自动故障转移成功!


八、客户端连接示例(Spring Boot)

8.1 Maven 依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

8.2 application.yml 配置

复制代码
spring:
  redis:
    cluster:
      nodes:
        - 192.168.1.10:7001
        - 192.168.1.10:7002
        - 192.168.1.10:7003
        - 192.168.1.10:7004
        - 192.168.1.10:7005
        - 192.168.1.10:7006
    lettuce:
      cluster:
        refresh-period: 30s  # 定期刷新拓扑

8.3 使用 RedisTemplate

java 复制代码
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void test() {
    redisTemplate.opsForValue().set("cluster:key", "hello"); // 自动路由
    String value = (String) redisTemplate.opsForValue().get("cluster:key");
}

✅ Spring Data Redis 自动处理 MOVED/ASK 重定向,无需手动干预!


九、生产环境最佳实践

✅ 必须遵守

  1. 至少 3 主 3 从(满足多数派,容忍 1 节点故障)
  2. 主从节点跨物理机/可用区部署(防单点故障)
  3. 开启 AOF + RDB 混合持久化aof-use-rdb-preamble yes
  4. 设置密码requirepass + masterauth

✅ 推荐配置

复制代码
# redis.conf
cluster-node-timeout 15000
cluster-require-full-coverage no  # 允许部分 slot 不可用(避免全集群不可用)
slowlog-log-slower-than 10000     # 记录慢查询

🚫 避免的操作

  • 跨 slot 的多 key 操作 (如 MGET key1 key2,若 key1 和 key2 不在同一 slot)
    • 解决方案:使用 Hash Tag ,如 user:{1001}:nameuser:{1001}:age 会落在同一 slot
  • 大 key / 热点 key(导致分片负载不均)

十、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
happymaker06262 小时前
JDBC(MySQL)——DAY04(调用存储过程,存储函数)
java·数据库·mysql
微学AI3 小时前
时序数据库选型:聚焦时间序列数据库Apache IoTDB——为工业物联网与大数据而生
数据库·apache·时序数据库
952363 小时前
MySQL - 集群架构与实践
数据库·学习·mysql·架构
原来是猿3 小时前
Linux-【文件系统下】
linux·运维·数据库
Java面试题总结3 小时前
2026最新Java八股文(完整版)
java·开发语言·jvm·数据库·java面试·java八股文
新缸中之脑3 小时前
68个适合个人GPU部署的LLM
数据库
麦聪聊数据3 小时前
SQL2API 网关的透明缓存与请求合并机制
数据库·sql·低代码·微服务
西门吹雪分身4 小时前
分布式架构之CAP与数据库分片架构
数据库·分布式·架构·分库分表
神奇萝卜头4 小时前
Redis 主从复制实现原理深度详解
redis