尚硅谷redis7 74-85 redis集群分片之集群是什么

article/2025/8/29 19:18:30

74 redis集群分片之集群是什么

如果主机宕机,那么写操作就被暂时中断,后面就要由哨兵进行投票和选举。那么一瞬间若有大量的数据修改,由于写操作中断就会导致数据流失。

由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展。每个复制集只负责存储整个数据集的一部分,这就是Redis的集群,共作用是提供在多个Redis节点间共享数据的程序集。

75 redis集群分片之集群能干嘛

redis集群是一个提供在多个redis节点间共享数据的程序集

redsi集群可以支持多个master

左图是一个master,右图是多个master

多个master对外是一个集群整体,里面具体是哪个redis实例提供服务和访问的客户端无关。若三个master中有一个挂了,没关系,还有另外两个master可以工作。每个master都有对应的从机,如果m1挂了那么s1可以顶上。

redis集群的作用

  • Redis集群支持多个Master,每个Master又可以挂载多个Slave
  • 由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
  • 客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
  • 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系

76 redis集群分片之槽位slot

在 Redis 集群中,密钥空间(Keyspace) 是指 Redis 用来存储所有键的一个逻辑空间。而集群的密钥空间,则是这个概念在 Redis 集群架构中的具体体现,它决定了数据在集群中如何分布和定位。

分片机制

  • Redis 集群将整个密钥空间划分为 16384 个槽位(slots),编号从 0 到 16383。

  • 每个键根据其名字的哈希值被分配到这 16384 个槽位中的某一个槽。

  • 每个节点(Redis 实例)负责其中的一部分槽位,这样可以实现数据的分布式存储。

槽位计算方式

Redis 使用 CRC16 哈希算法计算键的哈希值,然后对 16384 取模,确定该键属于哪个槽。

slot = CRC16(key) % 16384

密钥空间的划分意义

  • 它决定了键值对的物理存储位置。

  • 客户端在访问一个键时,可以通过这个槽位快速定位到具体负责这个槽的节点。

redis集群的槽位slot

引入了 哈希槽的概念.
Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽。
举个例子,比如当前集群有3个节点,那么:

77 redis集群分片之分片

redis集群的分片

分片是什么

使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。

如何找到给定key的分片

为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。

槽位是逻辑单位,分片是物理单位。Redis 通过槽位把键分配到分片上。

假设你有 3 个 Redis 节点(A、B、C)组成一个集群:

  • 节点 A:负责槽位 0 ~ 5460

  • 节点 B:负责槽位 5461 ~ 10922

  • 节点 C:负责槽位 10923 ~ 16383

这 3 个节点就是 3 个分片,每个分片负责一部分 槽位,通过这些槽位将键分布到各个节点上。

78 redis集群分片之分片优势

槽位slot和分片的优势

假设系统要扩容,从三主三从变成五主五从。

最大优势,方便扩缩容和数据分派查找

这种结构很易添加或者删除节点,比如如果我想新添加个节点D,并不需要改变所有槽的分布,只需要将部分槽(比如 A 的一部分、B 的一部分)“迁移”到 D 上。比如把 A 的 1000 个槽给 D,B 的 1000 个槽也给 D。如果我想移除节点A.需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希的数量都不会造成集群不可用的状态。

槽位迁移不会造成集群停机

动态数据迁移(Rebalancing)
  • 在 Redis 集群中,槽位迁移是在线进行的

  • 当槽从 A 迁移到 D 时,Redis 会逐个 key 从 A 发送到 D(带着 key 的值)。

  • 在迁移过程中,如果有客户端访问该 key,Redis 仍然能处理请求(可能会返回 MOVEDASK 重定向,让客户端重试)。

79 reids集群分片之哈希取余分区算法

slot槽位映射,一般业界有3种解决方案:哈希取余分区、一致性哈希算法分区、哈希槽分区

哈希取余分区

2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:
hash(key)% N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

优点:
简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时问的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。

缺点:

原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key)/?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。
某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

一致性哈希算法

一致性Hash算法背景:一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。

提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系

算法构建一致性哈希环

一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0=2^32),这样让它逻辑上形成了一个环形空问

它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数最进行取模。而一致性Hash算法是对2^32取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:

整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、 …… 直到2^32-1,也就是说0点左侧的第一个点代表2^32-1,0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。

支持节点的动态增减而“最小代价”地迁移数据

假设原来你有 3 个节点:A、B、C,分布在环上:

数据 "x" 的哈希值在 A 和 B 之间,那么它就会映射到 B。

 如果增加一个新节点 D,映射到 A 和 B 之间:
  • 只有 hash 值落在 A 和 D 之间的数据,才会迁移到 D。

  • 其他数据仍然映射到原来的节点上。

 只影响局部,不影响全局

redis服务器IP节点映射

将集群中各个IP节点映射到环上的某一个位置。
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:

key落到服务器的落键规则

当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。
如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

优点

一致性哈希算法的容错性

假设Node C宕机,可以看到此时对象A、B、D不会受到影响。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是
B、C之间的数据且这些数据会转移到D进行存储。

一致性哈希算法的扩展性

数据量增加了,需要增加一台节点NodeX,X的位置在A和B之问,那收到影响的也就是A到X之问的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。

缺点

一致性哈希算法的数据倾斜问题

一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器:

总结

  • 为了在节点数目发生改变时尽可能少的迁移数据
    • 将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。
  • 优点
    • 加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。
  • 缺点
    • 数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

哈希槽分区

一致性哈希算法的数据倾斜问题

什么是哈希槽

哈希槽实质就是一个数组,数组[0,2^14-1]形成hash slot空间。

哈希槽能干什么


解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。

槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配

有多少个哈希槽

一个集群只能有16384个槽,编号0-16383(0-2^14-1),这些槽会分配给集群中的所有主节点,分配策略没有要求。
集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取视,余数是几key就落入对应的槽里。
HASH_SLOT=CRC16(key)mod 16384.以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

哈希槽的计算

Redis 集群中内置了16384个哈希槽.redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在Redis集群中放置一个key-value时,redis先对key使用crc16算法算出一个结果然后用结果对16384求余数[CRC16(key)% 16384],这样每个key都会对应一个编号在0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A、B在Node2,key之C落在Node3上

为什么“哈希槽”能帮助实现均匀分布

1. 槽数远大于节点数,有助于细粒度均衡

  • 有 16384 个槽,但也许只有 3 个节点。

  • 可以灵活分配槽数来做到负载均衡:比如 5461 个槽一个节点。

  • 增加节点时,只需要重新分配槽 → 不需要重新 hash 所有 key。

 细粒度的槽控制可以最大程度地做到“平衡”数据分布。

2. 使用好的哈希函数能保证槽分布近似均匀

Redis 使用的是 CRC16(key) % 16384

  • CRC16 是一种分布较均匀的哈希函数;

  • 对于大多数 key,它能让结果在 0~16383 之间近似均匀分布

类比:

假如你用 hash(key) % 3 映射 3 台服务器,hash 函数如果分布不均匀,就可能导致大部分 key 落在某一台服务器上。

而:

  • hash(key) % 16384 得到均匀分布的槽;

  • 然后把槽“均匀分配”给节点;

  • 就间接达到了key 的均匀分布

经典面试题

为什么redis集群的最大槽数是16384个?

Redis集群并没有使用一致性hash而是引入了哈希槽的概念。Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。但为什么哈希槽的数量是16384(2^14)个呢?

CRC16算法产生的hash值有16bit,该算法可以产生2^16=65536个值。
换句话说值是分布在0~65535之间,有更大的65536不用为什么只用16384就够?
作者在做mod运算的时候,为什么不mod65536,而选择mod16384?HASH_SLOT=CRC16(key)mod 65536为什么没启用

(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。当槽位为65536时,这块的大小是:65536÷8÷1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。当槽位为16384时,这块的大小是:16384÷8÷1024=2kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

前提:Redis 集群的每个节点需要知道哪些节点负责哪些槽(slot)。这就是为什么在节点之间发送心跳(PING/PONG)时,消息头中会包含该节点负责的槽位信息。

(2)redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。

(3)槽位越小,节点少的情况下,压缩比来,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots/N很高的话(N表示节点数)。bitmap的压缩率就很低。如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

85 redis集群分片之不保证强一致性

Redis集群不保证强一致性,这意味着在特定的条件下,Redis集群可能会丢掉一些被系统收到的写入请求命令

什么是“强一致性”?

  • 强一致性(Strong Consistency)意味着:一旦系统对外确认写入成功,所有节点(或客户端)随后读取到的都是这个值,永远不会丢失。

  • 而 Redis 集群遵循的是 最终一致性(Eventual Consistency),强调的是“最终节点状态会一致”,但在中间阶段可能不同步或丢失数据

Redis 集群中可能丢数据的典型场景

1. 主从复制延迟(Replication Lag)

  • Redis 集群采用异步复制:主节点执行写操作后,不会等待从节点确认再响应客户端。

  • 如果主节点刚写完数据就宕机:

    • 数据还未复制到从节点;

    • Redis 集群选了一个从节点晋升为新的主节点;

    • 这个新主节点上 可能没有那条写入的数据,就相当于“数据丢失”。

 这是一种典型的“已确认但未持久”的写丢失


2. 脑裂(Split-Brain)或网络分区

  • 如果集群节点之间发生网络故障,某些节点无法感知彼此状态,可能会:

    • 重复选举主节点;

    • 有两个主节点接收写入;

    • 最后产生数据不一致或写入丢失。


http://www.hkcw.cn/article/UdbGvRwkxy.shtml

相关文章

【Linux笔记】——进程间关系与守护进程

🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:linux 🌹往期回顾🌹: 【计算机网络】基于TCP进行socket编程——实现客户端到服务端远程命令行操作 🔖流水不争&#xf…

OSI 七大层详解

一、应用层 人与电脑相互沟通的桥梁,该层协议定义了应用进程之间的交互规则,通过不同的应用层协议为不同的网络应用提供服务。 二、表示层 定义数据格式(比如.pdf .txt)、加密解密、压缩解压缩 三、会话层 建立、管理和终止链…

Vue的生命周期

一、生命周期是什么 生命周期(Life Cycle)的概念应用很广泛,特别是在政治、经济、环境、技术、社会等诸多领域经常出现,其基本涵义可以通俗地理解为“从摇篮到坟墓”(Cradle-to-Grave)的整个过程在Vue中实…

如何用Go创建一个 deployment 到容器拉起来的全流程

整体流程概述: 认证与配置: 连接到Kubernetes集群。创建Deployment对象: 构建一个appsv1.Deployment结构体,定义Pod的模板、副本数量、选择器等。发送创建请求: 使用Kubernetes Go客户端库将Deployment对象发送到API服…

echarts主题切换实现

文章目录 一、实现方式1.实现思路2.指定主题3.设置图表背景透明 二、具体实现1.监听与销毁2修改主题色细节 参考链接 一、实现方式 场景: 首先是我的项目有不同主题色,切换主题时候想要将echarts的图表主题色也一并更改,暂时只设置’light’和’dark’…

如何在 Ubuntu 24.04 服务器上安装 Apache Solr

Apache Solr 是一个免费、开源的搜索平台,广泛应用于实时索引。其强大的可扩展性和容错能力使其在高流量互联网场景下表现优异。 Solr 基于 Java 开发,提供了分布式索引、复制、负载均衡及自动故障转移和恢复等功能。 本教程将指导您如何在 Ubuntu 24.…

从零开始的云计算生活——第十四天,困难重重,安全管理。

一故事背景 在前面的基本无操作内容后,来到了大头内容,安全管理!其中的防火墙相关的内容更是重中之重,要好好掌握,熟练运用。 二SELinux安全上下文 1SELinux 简介 a. SELinux(Security-Enhanced Linux&…

UDP编程

udp是无连接的,没有listen 与 accept。 bind 服务端一定需要bind,告知别人自己的ip和port。 客户端可以不bind,在发送数据时候可以随机分配,客户端推荐bind(与tcp不同,udp本身无连接)。 注意&am…

【计网】分片

MF DF MAC帧 MTU 首部数据载荷 片偏移是整数

记录一个梦,借助大语言模型图片生成

梦见家门口有一条大河,但大河和其它景物都是灰暗没有鲜艳色彩很普通的梦中场景。大河似乎是长江的支流,但也可能有一个响亮的名字似乎是金沙江。 突然看到一条金红色的龙在快速游动,不敢相信自己的眼睛,因为一直不相信有这种生物…

PostgreSQL查询一个表的数据

要从一个表中检索数据就是按要求查询表的信息,。SQL的SELECT语句可分为: 1.选择列表(选择查询返回的列) 2.表列表操作(从中查询出的数据,进一步进行加减乘除-*/、筛选等操作) 3.可选的条件 whe…

聊聊后端面试中的MySQL高频考题

如大家所了解的,SQL( Structured Query Language )是一门在开发者中使用覆盖率超50%的数据库结构化查询语言。 不可否认,无论是常年与数据打交道的数据分析师和数据科学家,经常需要管理和维护数据库的数据库管理员&am…

R3GAN利用配置好的Pytorch训练自己的数据集

简介 简介:这篇论文挑战了"GANs难以训练"的广泛观点,通过提出一个更稳定的损失函数和现代化的网络架构,构建了一个简洁而高效的GAN基线模型R3GAN。作者证明了通过合适的理论基础和架构设计,GANs可以稳定训练并达到优异性能。 论文题目:The GAN is dead; long l…

【python深度学习】Day 39 图像数据与显存

知识点 图像数据的格式:灰度和彩色数据模型的定义显存占用的4种地方 模型参数梯度参数优化器参数数据批量所占显存神经元输出中间状态 batchisize和训练的关系 作业:今日代码较少,理解内容即可 一、图像数据的介绍 结构化数据(如表…

mongodb源码分析session接受客户端find命令过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制。 现在继续研究ASIOSession和connection是怎么接受客户端命令的? mongo/transport/service_state_machine.cpp核心方法有&#xf…

酒店管理破局:AI 引领智能化转型

一、酒店行业现状:规模扩张加速与效率瓶颈并存 根据中国五矿证券《中国酒店行业格局分析》报告,国内酒店行业呈现头部集中化趋势。截至2024年第三季度,锦江酒店以13,186家门店、125.8万间客房的规模稳居行业第一[1]。华住集团则以178.68亿元…

大模型深度学习之双塔模型

前言 双塔模型(Two-Tower Model)是一种在推荐系统、信息检索和自然语言处理等领域广泛应用的深度学习架构。其核心思想是通过两个独立的神经网络(用户塔和物品塔)分别处理用户和物品的特征,并在共享的语义空间中通过相…

【Java Web】速通CSS

参考笔记:JavaWeb 速通CSS_java css-CSDN博客 目录 一、CSS入门 1. 基本介绍 2. 作用 二、CSS的3种引入方式 1. 行内式 1.1 示例代码 1.2 存在问题 2. 写在head标签的style子标签中 2.1 示例代码 2.2 存在问题 3.以外部文件的形式引入(开发中推荐使用)⭐⭐⭐ 3.1 说明 3…

PostgreSQL安装

我们使用开源的对象关系型数据库--PostgreSQL,它具有高性能、可扩展和支持复杂查询的特性,非常适合现在学习使用。 一.安装PostgreSQL 我用的windows,就在windows上安装。 1.首先访问 PostgreSQL 官方网站https://www.postgresql.org/dow…

C++:栈帧、命名空间、引用

一、前置知识 1.1、栈区(Stack) 1.1.1、内存分配与回收机制 分配方式​​:由编译器自动管理,通过调整栈指针(ESP/RSP)实现。 函数调用时,栈指针下移(栈从高地址向低地址增长&…