Redis分片集群

目录

    • [一、 为什么需要 Redis 分片集群? 🤔](#一、 为什么需要 Redis 分片集群? 🤔)
    • [二、 Redis 分片集群是什么? 💡](#二、 Redis 分片集群是什么? 💡)
    • [三、 散列插槽 (Slot) 是什么? (数据怎么分?) 📮](#三、 散列插槽 (Slot) 是什么? (数据怎么分?) 📮)
    • [四、 如何搭建三主六从的 Redis 分片集群? 🐳🔧](#四、 如何搭建三主六从的 Redis 分片集群? 🐳🔧)
    • [五、 分片集群的集群伸缩是什么? ➕➖](#五、 分片集群的集群伸缩是什么? ➕➖)
    • [六、 如何使用 RedisTemplate 访问分片集群?💻](#六、 如何使用 RedisTemplate 访问分片集群?💻)
    • [七、 分片集群的原理是什么? ⚙️🤝](#七、 分片集群的原理是什么? ⚙️🤝)
    • [八、 分片集群的优缺点是什么?](#八、 分片集群的优缺点是什么?)

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解 Redis 哨兵模式 请看 : Redis 哨兵模式:告别手动故障转移!

其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏(已完结)】...等

如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力

✨更多文章请看个人主页: 码熔burning

好的,我们来详细地、用大白话聊聊 Redis 分片集群 (Redis Cluster),这次加上一些小表情增加点趣味性!😊


一、 为什么需要 Redis 分片集群? 🤔

想象一下,你开了一家生意爆火的小卖部 (单个 Redis 实例) 🏪。

  • 问题一:地方不够大 (内存瓶颈) 😥:顾客越来越多,货架 (内存) 都堆满了,新商品放不下了。单个 Redis 服务器的内存是有限的,当数据量超过这台服务器的内存容量时,就存不下了。
  • 问题二:老板忙不过来 (CPU/网络瓶颈) 🏃‍♂️💨:顾客排长队结账,老板一个人收钱、打包、找零,忙得团团转 (CPU 达到极限)。同时,店门口的路太窄 (网络带宽),进出的人太多,堵车了 🚗🚕🚙。单个 Redis 服务器的 CPU 处理能力和网络带宽也是有限的,当请求量非常大时,它会成为性能瓶颈,响应变慢。
  • 问题三:老板病了就关门 (可用性问题) 🤒:万一老板生病了或者店里停电了 (服务器宕机),整个小卖部就得关门歇业,顾客买不到东西。单个 Redis 实例存在单点故障风险,一旦它挂了,整个服务就不可用了。

分片集群就是为了解决这些问题! 🎉

它的思路是:既然一个小卖部不够用,那就开连锁超市!🏢🏢🏢

  • 解决内存瓶颈 👍:开多家分店 (多个 Redis 节点),把商品 (数据) 分散到不同的店里。这样总的存储空间就大大增加了。
  • 解决 CPU/网络瓶颈 👍:顾客可以去不同的分店结账,每个店的老板 (CPU) 压力都小了,店门口的路 (网络) 也不会那么拥挤了。请求被分散到多个节点处理,提高了整体的吞吐量。
  • 解决可用性问题 👍:每个分店都配个副店长 (主从复制) 👥。万一某个店长病了 (主节点宕机),副店长立刻顶上 (从节点自动切换为主节点),超市还能继续营业。提供了高可用性。

所以,Redis 分片集群的核心思想就是:

  1. 分片 (Sharding) 🔪:把数据"切"成很多片,分散存储在多个 Redis 实例(主节点)上。
  2. 复制 (Replication) 👯:给每个存储数据的实例(主节点)配备一个或多个备份实例(从节点),保证高可用。

二、 Redis 分片集群是什么? 💡

Redis Cluster 是 Redis 官方提供的分布式 解决方案。它不是像哨兵(Sentinel)那样只负责高可用切换,而是同时 解决了数据分片高可用两个问题。✨

它是一个去中心化 的架构,这意味着没有一个"中央调度员"或者"代理服务器"来指挥所有请求。集群中的每个节点都知道其他节点的存在,也知道哪些数据(通过后面会讲的 Slot)应该由哪个节点负责。客户端可以直接连接到集群中的任意一个节点发起请求,如果这个节点恰好负责处理这个请求的数据,就直接处理;如果不是,它会告诉客户端"喂,你应该去找 XXX 节点 👉",然后客户端再去连接正确的节点。


三、 散列插槽 (Slot) 是什么? (数据怎么分?) 📮

前面说到要把数据"切片"分散到不同的店(主节点)。那具体怎么切?怎么知道哪个数据该去哪个店呢? 这就是散列插槽 (Hash Slot) 的作用。

  • 想象一个大邮局有 16384 个信箱 (Slot) 📬:Redis Cluster 预设了 16384 个 Slot (编号 0 到 16383)。这个数字是固定的。
  • 每封信 (Key) 都有个目标信箱 ✉️:当你存一个键值对 (比如 set mykey myvalue) 时,Redis Cluster 会对这个 key (也就是 "mykey") 做一个特殊的计算 (CRC16 算法),然后用计算结果对 16384 取模。HASH_SLOT = CRC16(key) % 16384。这个结果就是一个 0 到 16383 之间的数字,决定了这个 key 属于哪个 Slot。
  • 每个邮递员 (Master Node) 负责一部分信箱 🧑‍✈️:在集群初始化的时候,这 16384 个 Slot 会被平均分配给所有的主节点。比如你有 3 个主节点,那么:
    • 节点 A 可能负责 Slot 0 到 5460
    • 节点 B 可能负责 Slot 5461 到 10922
    • 节点 C 可能负责 Slot 10923 到 16383
  • 找对邮递员 👍:当客户端要操作一个 key 时,它会先计算这个 key 属于哪个 Slot,然后根据自己缓存的"Slot 分配表",找到负责这个 Slot 的主节点,再把请求发给那个主节点。

为什么是 16384? Redis 作者认为这个数字:

  1. 足够分散数据到最多 1000 个主节点(实践中很少有这么大规模的集群 💪)。
  2. 节点间传输 Slot 配置信息时,用 16384 个 Slot(即 16384 bit = 2KB)的位图 (bitmap) 来表示,这个大小比较合适,不会太大导致网络开销过高。👌

如何查看某个 Key 属于哪个 Slot?

可以使用命令:CLUSTER KEYSLOT {key},例如 CLUSTER KEYSLOT mykey


四、 如何搭建三主六从的 Redis 分片集群? 🐳🔧

这里我们用 Docker Compose 来模拟 9 个 Redis 实例,组成一个 3 主 6 从(每个主节点带 2 个从节点)的集群。

前提条件:

  • 你的 Linux 系统安装了 Docker。
  • 你的 Linux 系统安装了 Docker Compose。

步骤:

  1. 创建工作目录: 📂

    bash 复制代码
    mkdir redis-cluster-demo
    cd redis-cluster-demo
  2. 创建 docker-compose.yml 文件: 📝

    yaml 复制代码
    services:
      # 定义 9 个 Redis 节点服务 (这里只展示 node-1 和 node-4 作为例子, 其他类似)
      redis-node-1: # Master 1 Candidate
        image: redis:latest # 或者更新的版本
        container_name: redis-node-1
        # 注意:推荐将 nodes.conf 放在持久化数据目录中
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7001:6379"     # 客户端端口映射
          - "17001:16379"   # 集群总线端口映射
        volumes:
          - ./node-1/data:/data # 只映射数据目录
        networks:
          - redis-cluster-net
    
      redis-node-2: # Master 2 Candidate
        image: redis:latest 
        container_name: redis-node-2
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7002:6379"
          - "17002:16379"
        volumes:
          - ./node-2/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-3: # Master 3 Candidate
        image: redis:latest 
        container_name: redis-node-3
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7003:6379"
          - "17003:16379"
        volumes:
          - ./node-3/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-4: # Slave Candidate 1
        image: redis:latest 
        container_name: redis-node-4
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7004:6379"
          - "17004:16379"
        volumes:
          - ./node-4/data:/data
        networks:
          - redis-cluster-net
    
      # ... (省略 redis-node-5 到 redis-node-9 的定义,与 node-4 类似,只需修改名称、端口映射和卷映射目录即可) ...
      # 例如 redis-node-5: ports: ["7005:6379", "17005:16379"], volumes: ["./node-5/data:/data"]
      # 例如 redis-node-9: ports: ["7009:6379", "17009:16379"], volumes: ["./node-9/data:/data"]
    
      redis-node-5:
        image: redis:latest 
        container_name: redis-node-5
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7005:6379"
          - "17005:16379"
        volumes:
          - ./node-5/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-6:
        image: redis:latest 
        container_name: redis-node-6
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7006:6379"
          - "17006:16379"
        volumes:
          - ./node-6/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-7:
        image: redis:latest 
        container_name: redis-node-7
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7007:6379"
          - "17007:16379"
        volumes:
          - ./node-7/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-8:
        image: redis:latest 
        container_name: redis-node-8
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7008:6379"
          - "17008:16379"
        volumes:
          - ./node-8/data:/data
        networks:
          - redis-cluster-net
    
      redis-node-9:
        image: redis:latest 
        container_name: redis-node-9
        command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file /data/nodes.conf --cluster-node-timeout 5000 --appendonly yes --bind 0.0.0.0
        ports:
          - "7009:6379"
          - "17009:16379"
        volumes:
          - ./node-9/data:/data
        networks:
          - redis-cluster-net
    
    
    networks:
      redis-cluster-net:
        driver: bridge # 或者其他网络驱动

    说明:

    • command: 启动 Redis 并开启集群模式,指定配置文件在 /data 目录下。推荐 这种方式,让 Redis 自己管理 nodes.conf
    • ports: 映射客户端端口 (6379 -> 700x) 和集群总线端口 (16379 -> 1700x)。总线端口必须能互通! 🤝
    • volumes: 将数据目录挂载出来,保证持久化。
    • networks: 所有节点在一个共享网络里。
  3. 创建必要的目录: 🛠️

    bash 复制代码
    for i in {1..9}; do mkdir -p ./node-$i/data; done
  4. 启动所有 Redis 容器: ▶️

    bash 复制代码
    docker compose up -d

    等待所有容器启动完成。可以用 docker ps 查看状态。

  5. 创建集群:关键一步

    这一步需要使用 redis-cli 工具来告诉这些独立的 Redis 节点:"嘿,你们现在组成一个大家庭了!"

    • 找到你的宿主机 IP 地址: 不能用 127.0.0.1localhost。用 ip addrifconfig 查找。假设你的 IP 是 172.29.0.10 (请替换成你自己的!)。可以使用 docker inspect redis-node-1 | grep '"IPAddress":' 命令查看:

    • 执行集群创建命令:

      bash 复制代码
      # 获取任一节点的 redis-cli (用 node-1 举例)
      docker exec -it redis-node-1 redis-cli --cluster create \
      172.28.120.43:7001 172.28.120.43:7002 172.28.120.43:7003 \
      172.28.120.43:7004 172.28.120.43:7005 172.28.120.43:7006 \
      172.28.120.43:7007 172.28.120.43:7008 172.28.120.43:7009 \
      --cluster-replicas 2

      解释:

      • docker exec -it redis-node-1 redis-cli: 进入 redis-node-1 容器执行命令。
      • --cluster create: 创建集群。
      • 后面是一长串 IP:PORT 列表 (用宿主机 IP 和映射的客户端端口)。
      • --cluster-replicas 2: 核心参数!告诉工具,给每个主节点配 2 个从节点。它会自动算:9 个节点 / (1主 + 2从) = 3 个主节点。所以,它会把前 3 个 (7001, 7002, 7003) 当作主,后 6 个 (7004-7009) 当作从,并自动分配。 magically! ✨
    • 确认创建: redis-cli 会打印出计划的配置方案,问你 Can I set the cluster configuration? (type 'yes' to accept):。输入 yes 并回车。

  6. 验证集群状态:

    连接到任意一个节点(使用映射的端口),查看集群信息。

    bash 复制代码
    # 连接到 7001 节点 (在容器内)
    docker exec -it redis-node-1 redis-cli -p 6379 cluster info
    # 或者从宿主机连接 (需要安装 redis-cli, -c 表示启用集群模式)
    # redis-cli -c -h 172.29.0.10 -p 7001 cluster info

    你应该看到 cluster_state:ok

    查看节点信息:

    bash 复制代码
    docker exec -it redis-node-1 redis-cli -p 6379 cluster nodes
    # 或者从宿主机连接
    # redis-cli -c -h 172.29.0.10 -p 7001 cluster nodes

    你会看到 9 个节点的信息,包括角色 (master/slave)、负责的 Slot 等。你会发现 3 个 master 和 6 个 slave,关系明确。

🎉 恭喜!你的 3 主 6 从 Redis 集群现在跑起来了!


五、 分片集群的集群伸缩是什么? ➕➖

集群搭好了,但业务发展太快 📈,3 家分店又不够用了,或者某个区域顾客少了 📉,想关掉一家店。这就是集群伸缩

  • 伸:扩容 (Scale Out) - 增加新的 Redis 节点。

    1. 开新店 (添加节点) 🆕:先按照上面的方法启动一个新的 Redis 实例(比如 redis-node-10,映射端口 701017010),让它也运行在集群模式下,但它刚开始是"孤单"的。

    2. 把它拉进连锁体系 (加入集群) 🤝:使用 redis-cli --cluster add-node 命令,告诉集群里的某个老节点,把这个新家伙拉进来。

      bash 复制代码
      # 新节点 172.29.0.10:7010, 加入到现有集群 (通过 7001 节点操作)
      docker exec -it redis-node-1 redis-cli --cluster add-node 172.29.0.10:7010 172.29.0.10:7001

      默认加进来是作为 主节点 ,但它还没分到活儿 (Slot)。如果要加从节点,用 --cluster-slave--cluster-master-id <主节点ID>

    3. 分配工作 (迁移 Slot) 🚚:新来的主节点不能闲着,需要从老主节点那里"匀"一些 Slot (和对应的数据) 过来。这叫 Resharding (重新分片) 。使用 redis-cli --cluster reshard 命令,它会像个向导一样问你:

      • 要搬多少个 Slot 呀?
      • 搬给谁呢 (输入新节点的 Node ID)?
      • 从哪里搬 (可以输入 all 让大家分摊,或者指定某些节点)?
      bash 复制代码
      # 连接到任一节点发起 reshard (例如 7001)
      docker exec -it redis-node-1 redis-cli --cluster reshard 172.29.0.10:7001
      # ... 根据提示一步步操作 ...

      这个过程 Redis 会在后台默默进行,服务基本不受影响 (可能有短暂抖动)。

  • 缩:缩容 (Scale In) - 移除 Redis 节点。

    1. 交接工作 (迁移 Slot) ➡️:如果要移除的是一个 主节点 ,必须先把它的 Slot 全部迁走 ,交给其他主节点。还是用 redis-cli --cluster reshard,这次把要移除节点的所有 Slot 作为"源",分配给别人。确保它手里的 Slot 清零! 如果移除的是 从节点,就不用操心 Slot 了,直接下一步。

    2. 办理离职手续 (移除节点) 👋:使用 redis-cli --cluster del-node 命令,告诉集群,把这个节点"开除"掉。

      bash 复制代码
      # 假设要移除 7003 节点,其 Node ID 是 <node-3-id> (用 cluster nodes 查)
      # 通过 7001 节点操作
      docker exec -it redis-node-1 redis-cli --cluster del-node 172.29.0.10:7001 <node-3-id>
    3. 关店 (关闭实例) :最后,把被移除节点的 Redis 进程或 Docker 容器停掉。

      bash 复制代码
      docker-compose stop redis-node-3 # 如果用 docker-compose 管理
      # 或者 docker stop redis-node-3

伸缩操作都需要时间让集群状态同步和数据迁移。耐心点哦!⏳


六、 如何使用 RedisTemplate 访问分片集群?💻

在 Java 应用中(特别是 Spring Boot / Spring Data Redis),访问 Redis Cluster 很方便。配置好后,用 RedisTemplate 就行,跟用单实例差不多。

  1. 添加依赖: (pom.xml / build.gradle)

    确保有 spring-boot-starter-data-redis。它通常默认使用 Lettuce 客户端,Lettuce 对 Cluster 支持很好。

    xml 复制代码
    <!-- Maven 示例 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- 一般不需要额外添加 Lettuce 或 Jedis,除非你想强制用 Jedis -->
  2. 配置 application.propertiesapplication.yml:

    告诉 Spring Data Redis 你的集群在哪儿。不需要写全所有节点 ,写几个就行,客户端会自动发现其他的。👍
    application.properties 示例:

    properties 复制代码
    # Redis Cluster 节点列表 (逗号分隔 host:port)
    spring.redis.cluster.nodes=172.29.0.10:7001,172.29.0.10:7002,172.29.0.10:7003
    # 如果有密码
    # spring.redis.password=yourpassword
    # 连接池配置 (可选, Lettuce)
    spring.redis.lettuce.pool.max-active=8
    spring.redis.lettuce.pool.max-idle=8

    application.yml 示例:

    yaml 复制代码
    spring:
      redis:
        cluster:
          nodes:
            - 172.29.0.10:7001
            - 172.29.0.10:7002
            - 172.29.0.10:7003
        # password: yourpassword # 可选
        lettuce: # 可选连接池
          pool:
            max-active: 8
            max-idle: 8
  3. 在代码中使用 RedisTemplate:

    注入 RedisTemplateStringRedisTemplate,然后就像操作普通 Redis 一样用。

    java 复制代码
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Service;
    
    @Service
    public class MyRedisService {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate; // 或者 RedisTemplate<String, Object>
    
        public void setValue(String key, String value) {
            // 直接用!它会自动找到正确的节点去执行 set 命令
            stringRedisTemplate.opsForValue().set(key, value);
            System.out.println("设置 Key: " + key + " 到集群! 😎");
        }
    
        public String getValue(String key) {
            // 同样,自动路由到持有这个 key 的节点去 get
            String value = stringRedisTemplate.opsForValue().get(key);
            System.out.println("从集群获取 Key: " + key + ", Value: " + value + " 😊");
            return value;
        }
    
        // 其他操作 hash, list, set, zset 都类似!
    }

关键点:

  • 无感操作: 大部分单 Key 操作,你感觉不到集群的存在。😎
  • 自动寻址: 客户端库内部维护 Slot -> 节点映射,自动把命令发给对的节点。
  • 聪明纠错: 如果映射过时 (比如刚发生了故障转移),节点会返回 MOVEDASK 错误。客户端库收到后会自动 更新映射,然后重试命令,对你的程序来说几乎是透明的。🔄
  • 多 Key 操作要注意! ⚠️:像 MSET, MGET, 事务 (MULTI/EXEC) 这类涉及多个 Key 的,默认必须保证所有 Key 都在同一个 Slot 里 。怎么保证?用 Hash Tags ! Key 里用 {} 包起来的部分才参与 Slot 计算。例如 user:{1000}:nameuser:{1000}:profile 就会落到同一个 Slot,因为都看 {1000}。 如果 Key 不在同个 Slot,执行这些命令会报错哦!💥

七、 分片集群的原理是什么? ⚙️🤝

Redis Cluster 的魔法主要靠这几招:

  1. 节点间八卦 (Gossip 协议):

    深入了解Gossip协议请看:Gossip协议:分布式系统中的"八卦"传播艺术

    • 每个节点心里都有本账(集群状态:谁活着,谁管哪些 Slot,主从关系等)。
    • 节点之间通过 集群总线端口 (客户端端口+10000那个) 定期互相 PING/PONG,顺便交换自己知道的"八卦消息"(集群状态信息)。🗣️👥
    • 这种方式没有中心老大 ,大家互相通气,最终信息会传遍整个集群,达成一致(虽然可能有点延迟,叫最终一致性)。
  2. Slot 地盘划分与同步:

    • 每个主节点"认领"自己负责的 Slot。
    • 认领信息通过 Gossip 协议告诉所有人。
    • 客户端连上任何一个节点,都能拿到最新的"地盘划分图"(Slot -> 节点映射)。🗺️
  3. 心跳检测与"怀疑人生"(PFAIL & FAIL):

    • 节点间互相 PING,如果 A 在 cluster-node-timeout 内没收到 B 的 PONG 回复,A 就开始"怀疑" B 是不是挂了,标记为 PFAIL (Possible Fail - 可能挂了)。这只是 A 的个人看法。🤔
    • A 会把这个"怀疑"通过 Gossip 告诉其他主节点。
    • 如果超过一半 的主节点都觉得"嗯,我也联系不上 B 了",大家就达成共识:B 确实挂了 !状态升级为 FAIL。这个"噩耗"会广播给所有人。💀
  4. 小弟上位记 (自动故障转移 Failover):

    • 一旦某个主节点 被确认 FAIL 了,它的从节点们就开始骚动了:"大哥倒了,机会来了!" 💪
    • 谁能上位?得看:确认大哥真挂了,并且自己数据跟大哥差别不大(同步延迟小)。
    • 选举流程:
      • 想上位的从节点,先给自己"资历"加一分 (currentEpoch++), 然后广发英雄帖给所有主节点:"选我!选我!" 🗳️
      • 还活着的主节点收到帖子,如果在这个"任期"(epoch) 内还没投过票,就给第一个发帖的从节点投一票。
      • 哪个从节点最先拿到超过半数主节点的投票,就成功当选新大哥!👑
    • 走马上任 :新大哥(原从节点)立马:
      • 宣布自己是主节点了。
      • 接管原来大哥的所有 Slot 地盘。
      • 通过 Gossip 昭告天下:"从今天起,这些 Slot 归我管了!"📢
    • 服务恢复 :整个过程是自动的,客户端在短暂的切换后就能找到新大哥继续工作。注意 ⚠️:如果某个主节点和它的所有从节点同时 挂掉,那它负责的 Slot 就真的服务不了了,需要人工介入。另外,如果超过半数 的主节点都挂了,为了防止数据错乱,整个集群会停止服务!🛑
  5. 客户端导航 (MOVED & ASK):

    • MOVED (搬家了,去那边!) 👉:客户端可能拿着旧地图(过时的 Slot 映射)找错了节点。这个节点会说:"兄弟,这个 Slot 不归我管了,已经搬到 ip:port 那家去了,你去那边吧!" 并返回 MOVED <slot> <correct_ip>:<correct_port>。客户端收到后,会更新地图,然后乖乖去新地址重新请求。
    • ASK (稍等,问问那边) ➡️:在 Slot 迁移过程 中,比如 Slot X 正从 A 往 B 搬。客户端还是找旧主 A 问 Slot X 里的某个 key:
      • 如果 key 还在 A 这,A 就处理了。
      • 如果 key 已经 搬到 B 那了,A 会说:"这个 key 可能在 B 那了,你去问问 B 试试?" 并返回 ASK <slot> <destination_ip>:<destination_port>
      • 客户端收到 ASK不会 更新地图(因为搬家还没彻底完成)。它会先去 B 那边敲门说 ASKING(表明我是被 A 指过来的),然后再发真正的命令。B 收到 ASKING 就知道怎么回事了,即使 Slot X 还没完全归它管,也会临时处理这条命令。ASK 只管用一次。

八、 分片集群的优缺点是什么?

优点:

  1. 能屈能伸 (Scalability) ✅:加机器就能加容量、加性能,理论上可以搞很大规模。就像开连锁店,想开多少开多少。
  2. 打不死的小强 (High Availability) ✅:主从热备 + 自动切换,挂掉一两个节点服务基本不受影响(只要不是主从一起挂,或挂掉太多主)。
  3. 跑得快 (Performance) ✅:请求分散到多个节点,大家分担压力,整体响应快。
  4. 亲儿子待遇 (Official Solution) ✅:Redis 官方出品,稳定性和兼容性有保障,社区活跃。
  5. 群龙无首也行 (Decentralized) ✅:没有中央控制节点,避免了单点瓶颈和故障。

缺点:

  1. 多 Key 操作有点瘸 (Multi-key Operations Limitation) ⚠️:像 MSET、事务等,默认要求 Key 在同一个 Slot,否则报错。需要开发者注意,或者用 Hash Tags 绕一下。跨 Slot 的复杂操作比较麻烦。
  2. 有点复杂 (Complexity) ⚠️:配置、管理、排错比单机或哨兵模式复杂,需要懂 Slot、Gossip 这些概念。运维成本高点。
  3. 话痨费网 (Network Overhead) ⚠️:节点间需要不停地 Gossip 来同步状态,会消耗一些网络带宽和 CPU。
  4. 客户端要配套 (Client Compatibility) ⚠️:必须用支持 Redis Cluster 的客户端库(新版的 Lettuce、Jedis 都支持)。
  5. 可能偏心 (Data Skew) ⚠️:如果 Key 设计不好(比如 Hash Tag 用得太集中,或有超级热点 Key),可能导致数据和流量集中在少数节点,失去均衡效果。🤷‍♀️
  6. 批量活儿效率可能不高 (Batch Efficiency) ⚠️:如果要操作一大堆分布在不同 Slot 的 Key,客户端得跟多个节点打交道,可能不如单实例高效。
  7. 团结就是力量(但散了就...) (Cluster Integrity Requirement) ⚠️:集群的正常运行和故障转移依赖于"少数服从多数"原则。如果挂掉的主节点太多(超过半数),整个集群就"瘫痪"了,拒绝服务以保护数据。
相关推荐
降世神童39 分钟前
【KWDB创作者计划】_针对KWDB时序数据库(多副本集群环境)进行压力测试
数据库·压力测试·时序数据库
05091542 分钟前
测试基础笔记第九天
数据库·笔记·oracle
二年级程序员44 分钟前
多表查询之嵌套查询
数据库·sql·mysql
盖世英雄酱581361 小时前
同事说缓存都用redis啊,数据不会丢失!真的吗?
redis·后端·面试
techdashen1 小时前
性能比拼: Redis vs Dragonfly
数据库·redis·缓存
胡斌附体1 小时前
mysql增加字段并添加索引怎样写语句合适
数据库·sql·mysql
_Djhhh1 小时前
【Redis】缓存三剑客问题实践(上)
数据库·redis·缓存
互联网搬砖老肖2 小时前
Mongodb分布式文件存储数据库
数据库·分布式·mongodb
Romantic Rose2 小时前
使用手机归属地查询API,使效率事半功倍
大数据·数据库·mysql
VB.Net3 小时前
20.4 显示数据库数据
数据库·c#