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

浅析 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 全自动完成,底层已经封装好了,我们无需关注。

      相关文章:

    • 《Spring Boot + MySQL高性能应用实战:性能优化技巧与最佳实践》
    • CMake小结2(PICO为例)
    • 【目标检测旋转框xml2txt】rolabelimg标注的xml格式label转YOLO格式txt文件
    • 【Java项目】基于Spring Boot的旅游管理系统
    • Blueprint —— Events
    • vue3-07模拟vue3的响应式原理Proxy (代理对象)与Reflect (反射对象)
    • NNP_test_cpp
    • 深度强化学习落地调参技巧
    • 企业之IT安全管控概览和实践案例
    • Docker下ARM64架构的源码编译Qt5.15.1,并移植到开发板上
    • 新版本的idea用不习惯,怎么还原为之前版本的UI界面?idea界面还原,idea新版本ui设置
    • 一文了解Java中的虚拟线程新特性
    • linux内核驱动:I2C子系统笔记
    • Android 10.0 Settings中系统菜单去掉备份二级菜单
    • 数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用
    • Java数组学习
    • 初识JavaFX-IDEA中创建第一个JavaFX项目
    • mysql中的计算日期函数 理解、用法
    • 从0-1学习Mysql第六章: 缓存与性能优化
    • Windows提权之基本流程(二)
    • 7月纽约举办“上海日”,上海大剧院舞剧《白蛇》连演三场
    • 美国调整对华加征关税
    • 加拿大新政府宣誓就职
    • 真人秀《幸存者》百万美元奖金,25年间“缩水”近一半
    • 印称印巴军事行动总指挥同意将局势降级
    • 中美瑞士会谈后中国会否取消矿产出口许可要求?外交部回应