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

Redis-集群与分区

一. 分区的基本概念与作用

  • 定义:分区(Partitioning)是将Redis数据分散存储到多个独立Redis实例的技术,每个实例只存储部分数据。
  • 核心价值
    • 提升性能:分散单节点的读写压力,多个节点并行处理请求。
    • 扩展存储:突破单节点的内存上限,支持海量数据存储。
    • 提高可用性:单个节点故障仅影响部分数据,降低整体服务中断风险。

二. 分区方式与实现

  • 范围分区(Range Partitioning)

    • 按数据范围划分(如按用户ID区间:1-10000存节点A,10001-20000存节点B)。
    • 优势:实现简单;劣势:热点数据可能集中在某一节点(如新增用户集中在高ID区间)。
  • 哈希分区(Hash Partitioning)

    • 对键(Key)计算哈希值,按哈希结果分配到不同节点(如CRC16(key) % 节点数)。
    • 优势:数据分布更均匀;劣势:节点数量变化时需重新计算哈希,导致大量数据迁移。

三. 分区实现方案

  • 客户端分区(Client-side Partitioning)

    • 由客户端(如应用程序)决定键的存储节点,无需服务器参与。
    • 普通哈希:直接对键哈希后取模,节点变化时数据迁移量大。
    • 一致性哈希
      • 将节点和键映射到环形哈希空间,键按顺时针方向映射到最近的节点。
      • 优势:节点增减时仅影响相邻节点,数据迁移量小;
      • 优化:引入“虚拟节点”解决数据分布不均问题(每个物理节点对应多个虚拟节点)。
  • 代理端分区(Proxy-side Partitioning)

    • 客户端连接代理服务器(如Codis、Twemproxy),由代理决定键的存储节点。
    • 以Codis为例:
      • 基于一致性哈希,支持动态扩缩容,自动处理数据迁移;
      • 提供Redis兼容接口,客户端无需修改代码;
      • 劣势:增加代理层开销,可能成为性能瓶颈。

四. Redis Cluster(官方集群方案)

  • 基本概念:Redis 3.0后推出的去中心化集群方案,支持自动分片、故障转移和高可用。
  • 核心特性
    • 去中心化:无中心节点,所有节点平等通信,客户端可连接任意节点。
    • Slot机制
      • 共16384个哈希槽(Slot),每个节点负责部分槽位;
      • 键通过CRC16(key) % 16384计算所属槽位,映射到对应节点;
      • 优势:槽位固定,节点变化时仅需迁移槽位数据,无需重新计算所有键的哈希。
    • Gossip协议:节点间通过P2P协议定期交换信息(如节点状态、槽位分配),实现集群元数据同步。

五. Redis Cluster的关键机制

部署架构

  • 至少需3主3从(每个主节点配1个从节点),保证高可用;
  • 主节点负责读写和槽位管理,从节点作为主节点的备份。

客户端路由

在Redis集群(尤其是Redis Cluster)中,客户端路由指的是客户端如何确定某个键(Key)应该存储或读取到哪个节点的机制。由于集群将数据分散在多个节点(通过槽位Slot管理),客户端需要通过特定逻辑找到键所在的目标节点,才能完成读写操作。

1. 客户端路由的核心背景:槽位(Slot)与节点的映射

Redis Cluster将所有数据划分为16384个槽位(Slot),每个节点负责一部分槽位(如节点A负责0-5460槽,节点B负责5461-10922槽等)。

  • 键的槽位计算规则:CRC16(key) % 16384,结果即为该键所属的槽位。
  • 集群中每个节点会记录“槽位-节点”的映射关系(元数据),并通过Gossip协议同步给其他节点。

客户端路由的核心目标:根据键的槽位,找到负责该槽位的节点

2. 基础路由机制:重定向(Redirect)

客户端首次连接集群时,可能不知道键的槽位对应哪个节点,因此需要通过“重定向”机制动态调整请求目标。Redis Cluster定义了两种重定向方式:MOVEDASK

MOVED重定向:槽位已永久转移

当客户端向某个节点发送命令时,若该节点发现键的槽位不由自己负责,且槽位已固定分配给其他节点,则返回MOVED重定向命令,指引客户端连接正确的节点。

流程示例

  • 客户端连接节点7001(负责0-5460槽),执行set name zhaoyun
  • 节点7001计算name的槽位:CRC16("name") % 16384 = 15903,发现该槽位由节点7005负责。
  • 节点7001返回:MOVED 15903 127.0.0.1:7005(告知客户端槽位15903在节点7005)。
  • 客户端收到MOVED后,记录“槽位15903→节点7005”的映射,后续直接向7005发送该键的命令。

关键特点

  • MOVED表示槽位的归属已确定(永久转移),客户端会更新本地缓存的“槽位-节点”映射,避免下次再发错节点。
  • 常见于集群初始化、扩缩容后槽位分配完成的场景。

在这里插入图片描述

ASK重定向:槽位正在迁移中

当集群进行扩缩容时,槽位及对应数据会从源节点迁移到目标节点。迁移过程中,若客户端请求的键所在槽位正处于迁移状态(部分数据在源节点,部分在目标节点),则源节点返回ASK重定向,临时指引客户端访问目标节点。

流程示例

  • 槽位1000正在从节点A迁移到节点B,客户端向节点A发送get key1key1属于槽位1000)。
  • 节点A发现key1已迁移到节点B,返回:ASK 1000 127.0.0.1:B(告知客户端槽位1000临时在节点B)。
  • 客户端收到ASK后,先向节点B发送ASKING命令(临时允许访问),再发送get key1,节点B执行命令并返回结果。

关键特点

  • ASK是临时指引(仅对当前命令有效),客户端不会更新本地“槽位-节点”映射(因为槽位迁移可能未完成)。
  • 仅在槽位迁移过程中触发,确保数据迁移时客户端能正确访问数据。

在这里插入图片描述

MOVEDASK的核心区别
类型触发场景客户端行为槽位状态
MOVED槽位已永久分配给新节点更新本地“槽位-节点”缓存归属已确定
ASK槽位正在迁移(未完成)临时访问目标节点,不更新缓存归属临时变动

3. 智能客户端(Smart Client)的路由优化

原生的重定向机制需要客户端多次请求(先错后对),效率较低。因此,Redis客户端(如JedisCluster、Lettuce)通常实现“智能路由”功能,通过预缓存槽位映射、主动更新元数据,减少重定向次数。

JedisCluster为例,其路由逻辑如下:

1. 初始化:获取槽位映射
  • 客户端启动时,随机连接集群中的一个节点,发送CLUSTER SLOTS命令,获取所有槽位与节点的映射关系(如“槽0-5460→节点A”“槽5461-10922→节点B”等)。
  • 将映射关系缓存到本地(内存中),形成“槽位→节点连接池”的对应表。
2. 正常请求:直接路由到目标节点
  • 客户端执行命令时,先计算键的槽位(CRC16(key) % 16384)。
  • 根据本地缓存的映射关系,找到该槽位对应的节点,直接向该节点发送命令,无需重定向。
3. 异常处理:重定向时更新缓存
  • 若客户端发送命令后收到MOVED重定向(说明本地缓存已过期,槽位归属已变):
    • 重新发送CLUSTER SLOTS命令,获取最新的槽位映射,更新本地缓存。
    • 按新映射重新向目标节点发送命令。
  • 若收到ASK重定向(槽位迁移中):
    • 临时向目标节点发送ASKING命令和原命令,不更新本地缓存(避免干扰未完成的迁移)。
4. 容错机制:节点故障时的重试
  • 若客户端发现某个节点不可用(如连接超时),会标记该节点为“故障”,并从缓存中移除其负责的槽位映射。
  • 后续请求这些槽位时,客户端会随机连接其他节点,通过MOVED重定向获取新的节点信息,重建缓存。

5. 客户端路由的核心价值

  • 去中心化:Redis Cluster无需代理节点,客户端直接与数据节点通信,减少中间层开销。
  • 动态适应:通过重定向和智能客户端的缓存更新,集群在扩缩容、故障转移时,客户端能自动适应槽位的迁移和节点变化。
  • 高性能:智能客户端通过预缓存槽位映射,多数请求可直接路由到目标节点,避免多次网络往返。

扩缩容与数据迁移

在Redis Cluster中,扩缩容指的是动态增加或减少集群节点以调整性能和存储能力,而数据迁移是扩缩容过程中核心操作,负责将数据在节点间重新分配以保持负载均衡。以下是详细解析:

1. 扩缩容的核心目标与前提

  • 核心目标
    • 扩容:通过增加节点分担压力,提升集群整体性能和存储容量;
    • 缩容:移除冗余节点,降低维护成本,同时保证数据不丢失。
  • 前提
    • 集群需处于正常状态(cluster_state: ok);
    • 所有节点间网络通畅,通过Gossip协议正常通信;
    • 数据迁移基于槽位(Slot) 进行(Redis Cluster共16384个槽位,每个槽位对应部分数据)。

2. 扩容流程(新增节点并分配槽位)

在Redis Cluster中,可使用官方redis-cli --cluster reshard命令自动为新节点分配槽位,无需手动执行cluster setslot`等繁琐操作。以下是具体示例:

场景说明
  • 现有集群:3个主节点(A:6379、B:6380、C:6381),已平均分配16384个槽位(每个节点约5461个槽)。
  • 新增节点:节点D(6382),刚加入集群,目前不负责任何槽位。
  • 目标:从现有节点A、B、C中各迁移部分槽位到D,使D成为新主节点。
自动分配槽位步骤
  • 查看集群当前状态(确认新节点已加入)
    执行以下命令检查集群节点及槽位分配:

    redis-cli --cluster check 127.0.0.1:6379
    

    输出类似:

    127.0.0.1:6379 (node-id-A) -> 5461 slots (0-5460)
    127.0.0.1:6380 (node-id-B) -> 5461 slots (5461-10922)
    127.0.0.1:6381 (node-id-C) -> 5462 slots (10923-16383)
    127.0.0.1:6382 (node-id-D) -> 0 slots  # 新节点,无槽位
    
  • 执行自动重分片(分配槽位给新节点)
    运行reshard命令,指定任意现有节点作为入口:

    redis-cli --cluster reshard 127.0.0.1:6379
    
  • 按提示输入参数
    命令会引导你完成4个关键参数的配置,步骤如下:

    (1)输入需要迁移的槽位总数

    根据需求指定迁移的槽位数量(如从每个旧节点迁移1820个,共迁移5460个给D):

    How many slots do you want to move (from 1 to 16384)? 5460
    
    (2)指定目标节点(新节点D)的ID

    输入新节点D的node-id(可从步骤1的check结果中获取):

    What is the receiving node ID? node-id-D
    
    (3)指定源节点(从哪些节点迁移槽位)
    • 若想从所有旧节点平均迁移,输入all
    • 若想指定特定节点,输入其node-id,完成后输入done
    Please enter all the source node IDs.Type 'all' to use all the nodes as source nodes for the hash slots.Type 'done' once you entered all the source nodes IDs.
    Source node #1: all
    
    (4)确认迁移计划

    系统会显示迁移方案(如从A迁移1820个、B迁移1820个、C迁移1820个到D),输入yes确认:

    Do you want to proceed with the proposed reshard plan (yes/no)? yes
    
  • 等待迁移完成
    命令会自动执行槽位迁移:

    • 标记槽位为“迁移中”(migrating/importing);
    • 逐键迁移槽内数据(通过migrate命令);
    • 完成后更新槽位归属,并同步到所有节点。

迁移过程中,可通过redis-cli --cluster check 127.0.0.1:6379查看进度。

验证结果

迁移完成后,再次执行check命令,确认新节点已分配槽位:

redis-cli --cluster check 127.0.0.1:6379

输出应类似:

127.0.0.1:6379 (node-id-A) -> 3641 slots (0-3640)
127.0.0.1:6380 (node-id-B) -> 3641 slots (5461-9101)
127.0.0.1:6381 (node-id-C) -> 3642 slots (10923-14564)
127.0.0.1:6382 (node-id-D) -> 5460 slots (3641-5460, 9102-10922, 14565-16383)  # 新分配的槽位

3. 缩容流程(移除节点并迁移其槽位)

假设集群中有 4 个主节点(A:6379、B:6380、C:6381、D:6382),需下线节点 D(负责槽位 3641-5460、9102-10922、14565-16383),步骤如下::

  • 确认待下线节点的槽位数量
    先通过check命令查看节点 D 负责的槽位总数(假设共 5460 个):

    redis-cli --cluster check 127.0.0.1:6379
    # 输出中找到节点D的槽位信息,记录总数量(如5460)
    
  • 执行自动迁移命令(指定源节点为待下线节点)

    使用reshard命令,并通过参数强制指定从节点 D 迁移所有槽位到其他节点:

    redis-cli --cluster reshard \--cluster-from <node-id-D> \  # 待下线节点D的ID(源节点)--cluster-to <node-id-A> \    # 目标节点A的ID(可指定多个,用逗号分隔)--cluster-slots 5460 \        # 迁移的槽位总数(即节点D的所有槽位)--cluster-yes \               # 自动确认迁移计划,无需手动输入yes127.0.0.1:6379                # 集群中任意节点的地址(作为入口)
    
    • 参数说明:
      • cluster-from:指定待下线节点的node-id,表示仅从该节点迁移槽位;
      • cluster-to:指定接收槽位的目标节点(可填多个主节点 ID,用逗号分隔,如node-id-A,node-id-B);
      • cluster-slots:需迁移的槽位总数(必须等于待下线节点的总槽位,否则会迁移不完整);
      • cluster-yes:自动确认迁移计划,避免交互提示。
  • 验证迁移结果
    迁移完成后,再次执行check命令,确认节点 D 的槽位已全部迁移(槽位数量为 0):

    redis-cli --cluster check 127.0.0.1:6379
    # 输出中节点D的槽位应显示为0 slots
    
  • 移除待下线节点
    确认槽位全部迁移后,执行forget命令将节点 D 从集群中移除:

    redis-cli --cluster del-node 127.0.0.1:6379 <node-id-D>
    

4. 数据迁移的核心机制

数据迁移是扩缩容的核心,Redis通过以下机制保证迁移过程中数据一致性和服务可用性:

  • 迁移单位:以槽位为最小单元

    • 迁移按槽位进行,每个槽位包含多个键,迁移时先迁移槽位元数据,再迁移槽内键。
    • 优势:避免单个大键迁移导致的长时间阻塞,且槽位数量固定(16384),便于管理。
  • 迁移过程:逐键迁移,非阻塞

    • 逐键迁移:通过migrate命令逐个迁移槽内的键,每次迁移1个或少量键(如10个),避免单次操作耗时过长。
    • 非阻塞:迁移期间,源节点和目标节点均可处理其他请求,仅被迁移的键在迁移瞬间可能短暂不可写(毫秒级)。
  • 数据一致性保证

    • 迁移中键的访问
      • 若客户端访问正在迁移的键:
        • 若键仍在源节点,源节点正常处理;
        • 若键已迁移到目标节点,源节点返回ASK重定向,指引客户端访问目标节点(需先发送ASKING命令)。
    • 迁移完成的确认:只有当槽位所有键迁移完成,且通过cluster setslot更新归属后,集群才认为槽位已转移,避免部分迁移导致的数据分裂。
  • 迁移工具:redis-cli与第三方工具

    • 手动迁移:通过redis-clicluster命令手动执行(适合小规模迁移)。
    • 自动迁移
      • 官方工具:redis-cli --cluster reshard可自动计算槽位分配并完成迁移;
      • 第三方工具:如Codis、Redis Cluster Manager,支持可视化操作和批量迁移。

5. 扩缩容的注意事项

  1. 避免频繁操作:每次扩缩容会触发槽位迁移和Gossip协议同步,频繁操作可能导致集群抖动。
  2. 迁移时间估算:数据量越大,迁移耗时越长(需预留足够时间),可通过cluster getkeysinslot预估槽内键数量。
  3. 从节点处理:缩容主节点时,需先处理其从节点(如迁移为其他主节点的从节点,或随主节点一起下线)。
  4. 监控迁移状态:通过cluster slots命令查看槽位迁移进度,通过cluster nodes确认节点状态。

六. 各方案对比与适用场景

  • 客户端分区:适合简单场景,无额外组件,但客户端需实现路由逻辑,扩缩容复杂。
  • 代理端分区:适合需要兼容旧版Redis、客户端不愿修改代码的场景,依赖代理稳定性。
  • Redis Cluster:适合大规模集群,支持自动扩缩容和故障转移,去中心化设计避免单点瓶颈,是官方推荐的分布式方案。

集群与分区技术通过数据分散存储,解决了Redis单节点的性能和存储瓶颈,是Redis支持大规模应用的核心手段。

http://www.dtcms.com/a/286782.html

相关文章:

  • 5W8-3D牢游戏超级大集合[2012年6月] 地址 + 解压密码
  • 更适合后端宝宝的前端三件套之HTML
  • 光伏系统优化布局,实现从空间利用到效能的最大化
  • 2-大语言模型—理论基础:详解Transformer架构的实现(2)
  • Redisson 分布式锁
  • 一小时学习Redis
  • 使用 jar -xvf 解压JAR文件无反应怎么办?
  • Maven私服仓库,发布jar到私服仓库,依赖的版本号如何设置,规范是什么
  • 帆软可视化图
  • mave手动下载某个依赖,到本地库
  • 更适合后端宝宝的前端三件套之JavaScript
  • /字符串/
  • 《每日AI-人工智能-编程日报》--2025年7月18日
  • Simulink 按位控制的控制DO信号变量转换为uint16类型的控制字
  • Flux Kontext Lora 模型训练环境搭建
  • 软件维护全维度解析:从修复到进化的生命周期管理
  • linux制作镜像、压缩镜像、烧录的方法
  • 虚拟机centos服务器安装
  • Linux操作系统(练习一)
  • InnoDB 多版本控制 慢sql排查(基于MySQL 5.7)
  • Altera Quartus:图形化界面配置生成jic和pof文件
  • 京东店铺入鼎的全面分析与自研难度评估
  • AE MDX L6 L12 L18 电源手侧操作使用说明
  • 智能交通4G专网解决方案,引领智慧出行新时代
  • Entity Framework (EF) 深度解析
  • 数据查找 二叉查找树
  • 网关-微服务网关实现
  • AI大模型打造金融智能信审助手04.七大金融监管相关政策
  • 活动图描述场景
  • CityEngine自动化建模