当前位置: 首页 > article >正文

浅析 Redis 分片集群 Cluster 原理、手动搭建、动态伸缩集群、故障转移

大家好,我是此林。

之前的文章中分享了 Redis 集群方案的一种:主从集群+哨兵机制

浅谈 Redis 主从集群原理(一)-CSDN博客

浅谈 Redis 主从复制原理(二)-CSDN博客

这种模式有什么缺点呢?

1. 虽然从节点有多个,提高了读的性能。但主节点只有一个,写的性能无法提高

2. 要存储大量的数据,就要保证 master 内存容量大。但是 master 内存容量大了以后,fork 生成 RDB 文件的时间就会边长,RDB 文件也会变得很大,导致了下面的问题。

  • RDB 文件网络传输开销大
  • master 和 slave 第一次做全量同步,耗时长
  • 若 master 宕机,新 master 会和 slave 重新全量同步,开销大

所以,要解决上面的问题,实现存储海量的数据,就引入了新的集群方案:分片集群(Cluster)。

1. 分片集群概述

可以发现,分片集群有以下特征:

1. 集群中有多个master,每个master保存不同数据

2. 每个master都可以有多个slave节点

3. master之间通过心跳机制监测彼此健康状态

4. 客户端请求可以访问集群任意节点,最终都会被路由转发到正确节点

可以发现,Cluster 集群里面没有了哨兵机制,而是不同 master 之间通过心跳机制互相检测彼此的健康状态,如果发现有 master 宕机,会和哨兵一样重新选 master ,进行故障转移。

2. 分片集群搭建

这里我们部署6个节点,一主一从。

节点IP端口
master192.168.183.1287001
master192.168.183.1287002
master192.168.183.1287003
slave192.168.183.1288001
slave192.168.183.1288002
slave192.168.183.1288003

1. 创建目录

cd /root/redis-cluster/

mkdir 7001 7002 7003 8001 8002 8003

ll

2. 在当前目录下创建 redis.conf

port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file  /root/redis-cluster/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /root/redis-cluster/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip(可以多个)
replica-announce-ip 192.168.183.128
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /root/redis-cluster/6379/run.log
# requirepass 123123

 3. 每个节点都需要配置 redis.conf,以下命令把 redis.conf 批量复制到对应目录。

echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

4. 批量修改,把6379替换成对应的端口。

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

5. 然后批量启动 Cluster 集群。也可以使用 通过 redis-server + redis.conf文件路径分别启动。

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf

查看 redis 相关进程。 

ps -ef | grep redis

6. 批量关闭,关闭 Cluster 集群。 

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。

所以还需要下面的命令:

redis-cli --cluster create \
          --cluster-replicas 1 \
          192.168.183.128:7001 192.168.183.128:7002 192.168.183.128:7003 \
          192.168.183.128:8001 192.168.183.128:8002 192.168.183.128:8003 

--cluster-replicas 1 代表每个 master 有1个从节点。

那么列个方程,假设 master 有 x 个,那么 slave 就有 x 个,x + x = 6,x = 3。

那么计算出来,master 3 个,slave 3个。

前三个 IP+端口 就是 master,后 3 个就是 slave。

3. 散列插槽

Cluster 集群启动后,可以发现每一个 master 节点都被映射到了0-16383共16384个插槽上(hash slot)上。

那为什么要有散列插槽呢?

Redis 在存一个 <key, value> 的时候,会通过 CRC16 哈希算法对 key 进行运算,得到一个 hash 值,然后对 16384 取余,得到结果就是 slot 值,以此来 决定这个 <key, value> 落到哪一个 master 上

注:如果 key 是 num,那就根据 num 计算 hash,如果 key 是 {iphone}num,那么就根据 phone 计算 hash。

也就是说,如果将来我们希望某些 key 落到同一个 master 上,可以在 set key 的时候,加上 {},这样 redis 就会根据花括号里的内容计算 hash 值,从而落到同一个节点上。

重定向举例:

4. 集群动态伸缩

Cluster 集群有个重要的特点,就是集群能够动态增加或删除节点。

案例:

向集群添加一个新的 master 节点,并向其中存储 num = 10

需求:

1. 启动一个新的 redis 实例,端口为 7004

2. 添加 7004 到 Cluster 集群,并且作为一个 master

3. 给 7004 分配插槽,使得 num 这个 key 可以存储到 7004

1. 同样的,创建目录,复制修改配置文件。 

mkdir 7004
cp redis.conf 7004
sed -i s/6379/7004/g 7004/redis.conf

2. 启动 redis 服务。 

redis-server 7004/redis.conf

3. 把 7004 添加到 Cluster 集群。 

redis-cli --cluster add-node 192.168.183.128:7004 192.168.183.128:7001

4. 查看 Cluster 集群信息。

redis-cli -c -h 192.168.183.128 -p 7001 cluster nodes

可以看到,目前 7004 还没有分配哈希槽(hash slot)。 

5. 给  7004 结点分配插槽

redis-cli --cluster reshard 192.168.183.128:7001

6. 查看 Cluster 集群信息。

redis-cli -p 7001 cluster nodes

 分配成功!

7. 测试,num 已经落到了 7004 节点上。

8. 删除 7004 节点,先 reshard hash slot。

9. 再次查看节点信息,发现 7004 没有 hash slot 了,且已经成为了 7001 的 slave。

10. forget 删除 7004 节点,后面的 id 写 7004 的 id 就行。

redis-cli -c -h 192.168.183.128 -p 7001 cluster forget d8ec7fc70c782114d6db60eb11863ad7a24801b8

5. 故障转移

当一个集群中一个 master 宕机了会发生什么?

  • 与其他实例失去连接:当一个 master 节点宕机时,它和其他节点的连接会中断,集群中的节点会检测到该节点不可用。

  • 其他 master 监测到该节点宕机(疑似宕机):由于 Redis Cluster 本身是去中心化的,不同于哨兵机制,集群内的其他节点会通过 Gossip 协议(节点之间相互通知)来交换信息,检测到宕机的节点,但这并不会立刻导致故障转移。

  • 最后确定下线,选举一个 slave 成为 master:如果集群中的节点确认该 master 节点宕机(通过 QUORUM 达成共识),集群会通过故障转移机制,将该节点的 slave 之一提升为新的 master。在 Redis Cluster 中,只有当 slave 存在且健康时,才会进行主从切换。

注:如果一个 master 节点宕机,但没有足够的 slave 节点(或者没有足够的健康 slave),那么该槽的服务将暂时不可用,直到新的 master 被选举出来。

所以,整体来说,Cluster 的容错机制确实也与哨兵机制类似,但集群是去中心化的,节点之间的自动故障转移是通过 Gossip 协议和共识机制来实现的。

手动故障转移

有时候,比如 7001 机器比较老旧,需要升级。

我们新开一个机器性能好的结点,主动成为 7001 的 slave。

然后通过 cluster failover 命令手动让 7001 宕机。

这时候新开的结点被选举为master,实现机器的无感故障转移升级。

6. RedisTemplate 配置

和哨兵的玩法类似,只不过配置文件稍微有点不同。

application.yml

主从读写分离配置还是一样:

    @Bean
    public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer() {
        return configBuilder -> configBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }

    这里的 ReadFrom 是配置 Redis 的读取策略:

    MASTER:从主节点读取

    MASTER_PERFERRED:优先从 MASTER 读取,MASTER 不可用才读取 slave。

    REPLICA:从从节点读取

    REPLICA_PERFERRED:优先从从节点读取,slave 不可用才读取 MASTER。

    主从切换、读写分离、故障转移通知接收由 RedisTemplate 全自动完成,底层已经封装好了,我们无需关注。


      http://www.kler.cn/a/563382.html

      相关文章:

    • 【自学笔记】Vue基础知识点总览-持续更新
    • flutter boost接入
    • go 查看版本
    • 【算法通关村 Day12】字符串
    • Express + MongoDB 实现更新用户时用户名变化验证数据库是否存在,不变不验证
    • Linux:文本处理三剑客之sed命令用法详解
    • 【江科协-STM32】1. GPIO
    • WebGPU驱动的下一代Web图形引擎:突破浏览器计算性能瓶颈
    • Github 2025-02-24 开源项目周报 Top15
    • PostgreSQL vs MongoDB:优劣分析及适用场景
    • ubuntu系统 pycharm 卡死了,我用资源监视器将其杀死后,再打开就变成了直接卡死 且在点击Quit Windows无法关闭,只能再次杀死
    • vLLM专题(十三)-结构化输出(Structured Outputs)
    • 【苍穹外卖】问题笔记
    • IDEA 使用codeGPT+deepseek
    • 双重因子认证:守护数字安全的“双保险”
    • 数据如何安全“过桥”?分类分级与风险评估,守护数据流通安全
    • HTML操作详解
    • 【C/C++】删除链表的倒数第 N 个结点(leetcode T19)
    • Maven Spring框架依赖包
    • 自动驾驶之BEVDet